-#glm-admin-content-container .admin-item-label,#glm-admin-content-container .admin-item-input,#glm-admin-content-container .admin-item-list{padding:0}.itemTitle-record{float:left}.admin-new-item{margin-bottom:15px}.admin-new-item .admin-new-item-link{padding:5px;background:#3D84D0;color:white;text-decoration:none;border-radius:4px}.no-padding{padding:0}.no-margin{margin:0}#glm-admin-content-container .admin-item-list-header{margin-bottom:20px;padding-bottom:2px;border-bottom:1px solid lightgray}.admin-item-list-row{padding-bottom:5px}.item-company-list-header,.item-date-list-header,.item-title-list-header{font-weight:bold;font-size:16px}.admin-item-list-row:nth-child(odd){background:#e3e3e5}.item-image{display:block}.item-image-row{border-bottom:1px solid lightgray;padding-bottom:10px}
+#glm-admin-content-container .admin-item-label,#glm-admin-content-container .admin-item-input,#glm-admin-content-container .admin-item-list{padding:0}.itemTitle-record{float:left}.admin-new-item{margin-bottom:15px}.admin-new-item .admin-new-item-link{padding:5px;background:#3D84D0;color:white;text-decoration:none;border-radius:4px}.no-padding{padding:0}.no-margin{margin:0}#glm-admin-content-container .admin-item-list-header{margin-bottom:20px;padding-bottom:2px;border-bottom:1px solid lightgray}.admin-item-list-row{padding-bottom:5px}.item-company-list-header,.item-date-list-header,.item-title-list-header{font-weight:bold;font-size:16px}.admin-item-list-row:nth-child(odd){background:#e3e3e5}.item-image{display:block;max-width:200px}.item-image-row{border-bottom:1px solid lightgray;padding-bottom:10px}
/*# sourceMappingURL=admin.css.map */
-{"version":3,"file":"admin.css","sources":["admin.scss"],"sourcesContent":["#glm-admin-content-container .admin-item-label,\n#glm-admin-content-container .admin-item-input,\n#glm-admin-content-container .admin-item-list{\n padding: 0;\n}\n.itemTitle-record{\n float: left;\n}\n.admin-item-input textarea{\n \n}\n.admin-new-item{\n margin-bottom: 15px;\n}\n.admin-new-item .admin-new-item-link{\n padding: 5px;\n background: #3D84D0;\n color: white;\n text-decoration: none;\n border-radius: 4px;\n}\n.no-padding{\n padding: 0;\n}\n.no-margin{\n margin: 0;\n}\n#glm-admin-content-container .admin-item-list-header{\n margin-bottom: 20px;\n padding-bottom: 2px;\n border-bottom: 1px solid lightgray;\n}\n.admin-item-list-row{\n padding-bottom: 5px;\n/* border-bottom: 1px solid lightgray;*/\n}\n.item-company-list-header,.item-date-list-header, .item-title-list-header{\n font-weight: bold;\n font-size: 16px;\n}\n.admin-item-list-row:nth-child(odd){\n background: #e3e3e5;\n}\n.item-image{\n display: block;\n}\n.item-image-row{\n border-bottom: 1px solid lightgray;\n padding-bottom: 10px;\n}\n"],"names":[],"mappings":"AAAA,AAA6B,4BAAD,CAAC,iBAAiB,CAC9C,AAA6B,4BAAD,CAAC,iBAAiB,CAC9C,AAA6B,4BAAD,CAAC,gBAAgB,AAAA,CACzC,OAAO,CAAE,CAAC,CACb,AACD,AAAA,iBAAiB,AAAA,CACb,KAAK,CAAE,IAAI,CACd,AAID,AAAA,eAAe,AAAA,CACX,aAAa,CAAE,IAAI,CACtB,AACD,AAAgB,eAAD,CAAC,oBAAoB,AAAA,CAChC,OAAO,CAAE,GAAG,CACZ,UAAU,CAAE,OAAO,CACnB,KAAK,CAAE,KAAK,CACZ,eAAe,CAAE,IAAI,CACrB,aAAa,CAAE,GAAG,CACrB,AACD,AAAA,WAAW,AAAA,CACP,OAAO,CAAE,CAAC,CACb,AACD,AAAA,UAAU,AAAA,CACN,MAAM,CAAE,CAAC,CACZ,AACD,AAA6B,4BAAD,CAAC,uBAAuB,AAAA,CAChD,aAAa,CAAE,IAAI,CACnB,cAAc,CAAE,GAAG,CACnB,aAAa,CAAE,mBAAmB,CACrC,AACD,AAAA,oBAAoB,AAAA,CAChB,cAAc,CAAE,GAAG,CAEtB,AACD,AAAA,yBAAyB,CAAC,AAAA,sBAAsB,CAAE,AAAA,uBAAuB,AAAA,CACrE,WAAW,CAAE,IAAI,CACjB,SAAS,CAAE,IAAI,CAClB,AACD,AAAA,oBAAoB,AAAA,UAAW,CAAA,AAAA,GAAG,CAAC,CAC/B,UAAU,CAAE,OAAO,CACtB,AACD,AAAA,WAAW,AAAA,CACP,OAAO,CAAE,KAAK,CACjB,AACD,AAAA,eAAe,AAAA,CACX,aAAa,CAAE,mBAAmB,CAClC,cAAc,CAAE,IAAI,CACvB"}
\ No newline at end of file
+{"version":3,"file":"admin.css","sources":["admin.scss"],"sourcesContent":["#glm-admin-content-container .admin-item-label,\n#glm-admin-content-container .admin-item-input,\n#glm-admin-content-container .admin-item-list{\n padding: 0;\n}\n.itemTitle-record{\n float: left;\n}\n.admin-item-input textarea{\n \n}\n.admin-new-item{\n margin-bottom: 15px;\n}\n.admin-new-item .admin-new-item-link{\n padding: 5px;\n background: #3D84D0;\n color: white;\n text-decoration: none;\n border-radius: 4px;\n}\n.no-padding{\n padding: 0;\n}\n.no-margin{\n margin: 0;\n}\n#glm-admin-content-container .admin-item-list-header{\n margin-bottom: 20px;\n padding-bottom: 2px;\n border-bottom: 1px solid lightgray;\n}\n.admin-item-list-row{\n padding-bottom: 5px;\n/* border-bottom: 1px solid lightgray;*/\n}\n.item-company-list-header,.item-date-list-header, .item-title-list-header{\n font-weight: bold;\n font-size: 16px;\n}\n.admin-item-list-row:nth-child(odd){\n background: #e3e3e5;\n}\n.item-image{\n display: block;\n max-width: 200px;\n}\n.item-image-row{\n border-bottom: 1px solid lightgray;\n padding-bottom: 10px;\n}\n"],"names":[],"mappings":"AAAA,AAA6B,4BAAD,CAAC,iBAAiB,CAC9C,AAA6B,4BAAD,CAAC,iBAAiB,CAC9C,AAA6B,4BAAD,CAAC,gBAAgB,AAAA,CACzC,OAAO,CAAE,CAAC,CACb,AACD,AAAA,iBAAiB,AAAA,CACb,KAAK,CAAE,IAAI,CACd,AAID,AAAA,eAAe,AAAA,CACX,aAAa,CAAE,IAAI,CACtB,AACD,AAAgB,eAAD,CAAC,oBAAoB,AAAA,CAChC,OAAO,CAAE,GAAG,CACZ,UAAU,CAAE,OAAO,CACnB,KAAK,CAAE,KAAK,CACZ,eAAe,CAAE,IAAI,CACrB,aAAa,CAAE,GAAG,CACrB,AACD,AAAA,WAAW,AAAA,CACP,OAAO,CAAE,CAAC,CACb,AACD,AAAA,UAAU,AAAA,CACN,MAAM,CAAE,CAAC,CACZ,AACD,AAA6B,4BAAD,CAAC,uBAAuB,AAAA,CAChD,aAAa,CAAE,IAAI,CACnB,cAAc,CAAE,GAAG,CACnB,aAAa,CAAE,mBAAmB,CACrC,AACD,AAAA,oBAAoB,AAAA,CAChB,cAAc,CAAE,GAAG,CAEtB,AACD,AAAA,yBAAyB,CAAC,AAAA,sBAAsB,CAAE,AAAA,uBAAuB,AAAA,CACrE,WAAW,CAAE,IAAI,CACjB,SAAS,CAAE,IAAI,CAClB,AACD,AAAA,oBAAoB,AAAA,UAAW,CAAA,AAAA,GAAG,CAAC,CAC/B,UAAU,CAAE,OAAO,CACtB,AACD,AAAA,WAAW,AAAA,CACP,OAAO,CAAE,KAAK,CACd,SAAS,CAAE,KAAK,CACnB,AACD,AAAA,eAAe,AAAA,CACX,aAAa,CAAE,mBAAmB,CAClC,cAAc,CAAE,IAAI,CACvB"}
\ No newline at end of file
-.no-padding{padding:0}.front-item-list-wrapper span{font-weight:bold}.front-item-list-wrapper .front-list-item{padding:10px 0;border-bottom:1px solid lightgray}.front-item-list-wrapper div{line-height:1.1;padding:5px}.front-item-list-wrapper .front-list-topic{padding:5px;width:100px;text-align:center;color:white;border-radius:5px;margin-bottom:10px}.front-item-list-wrapper .item-wanted{background:green}.front-item-list-wrapper .item-sale{background:red}
+.no-padding{padding:0}.front-item-list-wrapper span{font-weight:bold}.front-item-list-wrapper .front-list-item{padding:10px 0;border-bottom:1px solid lightgray}.front-item-list-wrapper div{line-height:1.1;padding:3px 0 3px 0}.front-item-list-wrapper .front-list-topic{padding:5px;width:100px;text-align:center;color:white;border-radius:5px;margin:0 auto 10px auto}.front-item-list-wrapper .item-wanted{background:green}.front-item-list-wrapper .item-sale{background:red}.front-item-list-wrapper .item-detail-link{display:inline-block;padding:5px;background:blue;color:white;text-decoration:none;margin-top:5px}.front-item-detail-wrapper .item-detail-images{padding-top:20px}
/*# sourceMappingURL=front.css.map */
-{"version":3,"file":"front.css","sources":["front.scss"],"sourcesContent":[".no-padding{\n padding: 0;\n}\n.front-item-list-wrapper{\n span{\n font-weight: bold;\n }\n .front-list-item{\n padding: 10px 0;\n border-bottom: 1px solid lightgray;\n }\n div{\n line-height: 1.1;\n padding: 5px;\n }\n .front-list-topic{\n padding: 5px;\n width: 100px;\n text-align: center;\n color: white;\n border-radius: 5px;\n margin-bottom: 10px;\n }\n .item-wanted{\n background: green;\n }\n .item-sale{\n background: red;\n }\n}"],"names":[],"mappings":"AAAA,AAAA,WAAW,AAAA,CACP,OAAO,CAAE,CAAC,CACb,AACD,AACI,wBADoB,CACpB,IAAI,AAAA,CACA,WAAW,CAAE,IAAI,CACpB,AAHL,AAII,wBAJoB,CAIpB,gBAAgB,AAAA,CACZ,OAAO,CAAE,MAAM,CACf,aAAa,CAAE,mBAAmB,CACrC,AAPL,AAQI,wBARoB,CAQpB,GAAG,AAAA,CACC,WAAW,CAAE,GAAG,CAChB,OAAO,CAAE,GAAG,CACf,AAXL,AAYI,wBAZoB,CAYpB,iBAAiB,AAAA,CACb,OAAO,CAAE,GAAG,CACZ,KAAK,CAAE,KAAK,CACZ,UAAU,CAAE,MAAM,CAClB,KAAK,CAAE,KAAK,CACZ,aAAa,CAAE,GAAG,CAClB,aAAa,CAAE,IAAI,CACtB,AAnBL,AAoBI,wBApBoB,CAoBpB,YAAY,AAAA,CACR,UAAU,CAAE,KAAK,CACpB,AAtBL,AAuBI,wBAvBoB,CAuBpB,UAAU,AAAA,CACN,UAAU,CAAE,GAAG,CAClB"}
\ No newline at end of file
+{"version":3,"file":"front.css","sources":["front.scss"],"sourcesContent":[".no-padding{\n padding: 0;\n}\n.front-item-list-wrapper{\n span{\n font-weight: bold;\n }\n .front-list-item{\n padding: 10px 0;\n border-bottom: 1px solid lightgray;\n }\n div{\n line-height: 1.1;\n padding: 3px 0 3px 0;\n }\n .front-list-topic{\n padding: 5px;\n width: 100px;\n text-align: center;\n color: white;\n border-radius: 5px;\n margin: 0 auto 10px auto;\n }\n .item-wanted{\n background: green;\n }\n .item-sale{\n background: red;\n }\n .item-detail-link{\n display: inline-block;\n padding: 5px;\n background: blue;\n color: white;\n text-decoration: none;\n margin-top: 5px;\n }\n}\n.front-item-detail-wrapper{\n .item-detail-images{\n padding-top: 20px;\n }\n}"],"names":[],"mappings":"AAAA,AAAA,WAAW,AAAA,CACP,OAAO,CAAE,CAAC,CACb,AACD,AACI,wBADoB,CACpB,IAAI,AAAA,CACA,WAAW,CAAE,IAAI,CACpB,AAHL,AAII,wBAJoB,CAIpB,gBAAgB,AAAA,CACZ,OAAO,CAAE,MAAM,CACf,aAAa,CAAE,mBAAmB,CACrC,AAPL,AAQI,wBARoB,CAQpB,GAAG,AAAA,CACC,WAAW,CAAE,GAAG,CAChB,OAAO,CAAE,WAAW,CACvB,AAXL,AAYI,wBAZoB,CAYpB,iBAAiB,AAAA,CACb,OAAO,CAAE,GAAG,CACZ,KAAK,CAAE,KAAK,CACZ,UAAU,CAAE,MAAM,CAClB,KAAK,CAAE,KAAK,CACZ,aAAa,CAAE,GAAG,CAClB,MAAM,CAAE,gBAAgB,CAC3B,AAnBL,AAoBI,wBApBoB,CAoBpB,YAAY,AAAA,CACR,UAAU,CAAE,KAAK,CACpB,AAtBL,AAuBI,wBAvBoB,CAuBpB,UAAU,AAAA,CACN,UAAU,CAAE,GAAG,CAClB,AAzBL,AA0BI,wBA1BoB,CA0BpB,iBAAiB,AAAA,CACb,OAAO,CAAE,YAAY,CACrB,OAAO,CAAE,GAAG,CACZ,UAAU,CAAE,IAAI,CAChB,KAAK,CAAE,KAAK,CACZ,eAAe,CAAE,IAAI,CACrB,UAAU,CAAE,GAAG,CAClB,AAEL,AACI,0BADsB,CACtB,mBAAmB,AAAA,CACf,WAAW,CAAE,IAAI,CACpB"}
\ No newline at end of file
--- /dev/null
+# fancyBox
+
+jQuery lightbox script for displaying images, videos and more.
+Touch enabled, responsive and fully customizable.
+
+See the [project page](http://fancyapps.com/fancybox/3/) for documentation and a demonstration.
+
+Follow [@thefancyapps](//twitter.com/thefancyapps) for updates.
+
+
+## Quick start
+
+1\. Add latest jQuery and fancyBox files
+
+```html
+<script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
+
+<link href="/path/to/jquery.fancybox.min.css" rel="stylesheet">
+<script src="/path/to/jquery.fancybox.min.js"></script>
+```
+
+
+2\. Create links
+
+```html
+<a data-fancybox="gallery" href="big_1.jpg">
+ <img src="small_1.jpg">
+</a>
+
+<a data-fancybox="gallery" href="big_2.jpg">
+ <img src="small_2.jpg">
+</a>
+```
+
+
+3\. Enjoy!
+
+
+## License
+
+fancyBox is licensed under the [GPLv3](http://choosealicense.com/licenses/gpl-3.0) license for all open source applications.
+A commercial license is required for all commercial applications (including sites, themes and apps you plan to sell).
+
+[Read more about fancyBox license](http://fancyapps.com/fancybox/#license).
+
+## Bugs and feature requests
+
+If you find a bug, please report it [here on Github](https://github.com/fancyapps/fancybox/issues).
+
+Guidelines for bug reports:
+
+1. Use the GitHub issue search — check if the issue has already been reported.
+2. Check if the issue has been fixed — try to reproduce it using the latest master or development branch in the repository.
+3. Isolate the problem — create a reduced test case and a live example. You can use CodePen to fork any demo found on documentation to use it as a template.
+
+A good bug report shouldn't leave others needing to chase you up for more information.
+Please try to be as detailed as possible in your report.
+
+
+Feature requests are welcome. Please look for existing ones and use GitHub's "reactions" feature to vote.
+
+Please do not use the issue tracker for personal support requests - use Stack Overflow ([fancybox-3](http://stackoverflow.com/questions/tagged/fancybox-3) tag) instead.
--- /dev/null
+{
+ "name": "fancybox",
+ "description": "Touch enabled, responsive and fully customizable jQuery lightbox script",
+ "keywords": [
+ "touch",
+ "responsive",
+ "lightbox",
+ "fancybox",
+ "gallery",
+ "jQuery",
+ "plugin"
+ ],
+ "homepage": "http://fancyapps.com/fancybox/",
+ "license": "GPL-3.0",
+ "moduleType": "globals",
+ "main": [
+ "dist/jquery.fancybox.min.css",
+ "dist/jquery.fancybox.min.js"
+ ],
+ "dependencies": {
+ "jquery": ">=1.9.0"
+ }
+}
--- /dev/null
+@charset "UTF-8";
+.fancybox-enabled {
+ overflow: hidden; }
+
+.fancybox-enabled body {
+ overflow: visible;
+ height: 100%; }
+
+.fancybox-is-hidden {
+ position: absolute;
+ top: -9999px;
+ left: -9999px;
+ visibility: hidden; }
+
+.fancybox-container {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 99993;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0); }
+
+/* Make sure that the first one is on the top */
+.fancybox-container ~ .fancybox-container {
+ z-index: 99992; }
+
+.fancybox-outer,
+.fancybox-inner,
+.fancybox-bg,
+.fancybox-stage {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0; }
+
+.fancybox-outer {
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch; }
+
+.fancybox-bg {
+ background: #1e1e1e;
+ opacity: 0;
+ transition-duration: inherit;
+ transition-property: opacity;
+ transition-timing-function: cubic-bezier(0.47, 0, 0.74, 0.71); }
+
+.fancybox-is-open .fancybox-bg {
+ opacity: 0.87;
+ transition-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1); }
+
+.fancybox-infobar,
+.fancybox-toolbar,
+.fancybox-caption-wrap {
+ position: absolute;
+ direction: ltr;
+ z-index: 99997;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity .25s, visibility 0s linear .25s;
+ box-sizing: border-box; }
+
+.fancybox-show-infobar .fancybox-infobar,
+.fancybox-show-toolbar .fancybox-toolbar,
+.fancybox-show-caption .fancybox-caption-wrap {
+ opacity: 1;
+ visibility: visible;
+ transition: opacity .25s, visibility 0s; }
+
+.fancybox-infobar {
+ top: 0;
+ left: 50%;
+ margin-left: -79px; }
+
+.fancybox-infobar__body {
+ display: inline-block;
+ width: 70px;
+ line-height: 44px;
+ font-size: 13px;
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+ text-align: center;
+ color: #ddd;
+ background-color: rgba(30, 30, 30, 0.7);
+ pointer-events: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-touch-callout: none;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-font-smoothing: subpixel-antialiased; }
+
+.fancybox-toolbar {
+ top: 0;
+ right: 0; }
+
+.fancybox-stage {
+ overflow: hidden;
+ direction: ltr;
+ z-index: 99994;
+ -webkit-transform: translate3d(0, 0, 0); }
+
+.fancybox-slide {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ overflow: auto;
+ outline: none;
+ white-space: normal;
+ box-sizing: border-box;
+ text-align: center;
+ z-index: 99994;
+ -webkit-overflow-scrolling: touch;
+ display: none;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ transition-property: opacity, -webkit-transform;
+ transition-property: transform, opacity;
+ transition-property: transform, opacity, -webkit-transform;
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d; }
+
+.fancybox-slide::before {
+ content: '';
+ display: inline-block;
+ vertical-align: middle;
+ height: 100%;
+ width: 0; }
+
+.fancybox-is-sliding .fancybox-slide,
+.fancybox-slide--previous,
+.fancybox-slide--current,
+.fancybox-slide--next {
+ display: block; }
+
+.fancybox-slide--image {
+ overflow: visible; }
+
+.fancybox-slide--image::before {
+ display: none; }
+
+.fancybox-slide--video .fancybox-content,
+.fancybox-slide--video iframe {
+ background: #000; }
+
+.fancybox-slide--map .fancybox-content,
+.fancybox-slide--map iframe {
+ background: #E5E3DF; }
+
+.fancybox-slide--next {
+ z-index: 99995; }
+
+.fancybox-slide > * {
+ display: inline-block;
+ position: relative;
+ padding: 24px;
+ margin: 44px 0 44px;
+ border-width: 0;
+ vertical-align: middle;
+ text-align: left;
+ background-color: #fff;
+ overflow: auto;
+ box-sizing: border-box; }
+
+.fancybox-slide .fancybox-image-wrap {
+ position: absolute;
+ top: 0;
+ left: 0;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ z-index: 99995;
+ background: transparent;
+ cursor: default;
+ overflow: visible;
+ -webkit-transform-origin: top left;
+ -ms-transform-origin: top left;
+ transform-origin: top left;
+ background-size: 100% 100%;
+ background-repeat: no-repeat;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden; }
+
+.fancybox-can-zoomOut .fancybox-image-wrap {
+ cursor: -webkit-zoom-out;
+ cursor: zoom-out; }
+
+.fancybox-can-zoomIn .fancybox-image-wrap {
+ cursor: -webkit-zoom-in;
+ cursor: zoom-in; }
+
+.fancybox-can-drag .fancybox-image-wrap {
+ cursor: -webkit-grab;
+ cursor: grab; }
+
+.fancybox-is-dragging .fancybox-image-wrap {
+ cursor: -webkit-grabbing;
+ cursor: grabbing; }
+
+.fancybox-image,
+.fancybox-spaceball {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ max-width: none;
+ max-height: none; }
+
+.fancybox-spaceball {
+ z-index: 1; }
+
+.fancybox-slide--iframe .fancybox-content {
+ padding: 0;
+ width: 80%;
+ height: 80%;
+ max-width: calc(100% - 100px);
+ max-height: calc(100% - 88px);
+ overflow: visible;
+ background: #fff; }
+
+.fancybox-iframe {
+ display: block;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ width: 100%;
+ height: 100%;
+ background: #fff; }
+
+.fancybox-error {
+ margin: 0;
+ padding: 40px;
+ width: 100%;
+ max-width: 380px;
+ background: #fff;
+ cursor: default; }
+
+.fancybox-error p {
+ margin: 0;
+ padding: 0;
+ color: #444;
+ font: 16px/20px "Helvetica Neue",Helvetica,Arial,sans-serif; }
+
+.fancybox-close-small {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 44px;
+ height: 44px;
+ padding: 0;
+ margin: 0;
+ border: 0;
+ border-radius: 0;
+ outline: none;
+ background: transparent;
+ z-index: 10;
+ cursor: pointer; }
+
+.fancybox-close-small:after {
+ content: '×';
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ width: 30px;
+ height: 30px;
+ font: 20px/30px Arial,"Helvetica Neue",Helvetica,sans-serif;
+ color: #888;
+ font-weight: 300;
+ text-align: center;
+ border-radius: 50%;
+ border-width: 0;
+ background: #fff;
+ transition: background .25s;
+ box-sizing: border-box;
+ z-index: 2; }
+
+.fancybox-close-small:focus:after {
+ outline: 1px dotted #888; }
+
+.fancybox-close-small:hover:after {
+ color: #555;
+ background: #eee; }
+
+.fancybox-slide--iframe .fancybox-close-small {
+ top: 0;
+ right: -44px; }
+
+.fancybox-slide--iframe .fancybox-close-small:after {
+ background: transparent;
+ font-size: 35px;
+ color: #aaa; }
+
+.fancybox-slide--iframe .fancybox-close-small:hover:after {
+ color: #fff; }
+
+/* Caption */
+.fancybox-caption-wrap {
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 60px 30px 0 30px;
+ background: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.1) 20%, rgba(0, 0, 0, 0.2) 40%, rgba(0, 0, 0, 0.6) 80%, rgba(0, 0, 0, 0.8) 100%);
+ pointer-events: none; }
+
+.fancybox-caption {
+ padding: 30px 0;
+ border-top: 1px solid rgba(255, 255, 255, 0.4);
+ font-size: 14px;
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+ color: #fff;
+ line-height: 20px;
+ -webkit-text-size-adjust: none; }
+
+.fancybox-caption a,
+.fancybox-caption button,
+.fancybox-caption select {
+ pointer-events: all; }
+
+.fancybox-caption a {
+ color: #fff;
+ text-decoration: underline; }
+
+/* Buttons */
+.fancybox-button {
+ display: inline-block;
+ position: relative;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ width: 44px;
+ height: 44px;
+ line-height: 44px;
+ text-align: center;
+ background: transparent;
+ color: #ddd;
+ border-radius: 0;
+ cursor: pointer;
+ vertical-align: top;
+ outline: none; }
+
+.fancybox-button[disabled] {
+ cursor: default;
+ pointer-events: none; }
+
+.fancybox-infobar__body, .fancybox-button {
+ background: rgba(30, 30, 30, 0.6); }
+
+.fancybox-button:hover:not([disabled]) {
+ color: #fff;
+ background: rgba(0, 0, 0, 0.8); }
+
+.fancybox-button::before,
+.fancybox-button::after {
+ content: '';
+ pointer-events: none;
+ position: absolute;
+ background-color: currentColor;
+ color: currentColor;
+ opacity: 0.9;
+ box-sizing: border-box;
+ display: inline-block; }
+
+.fancybox-button[disabled]::before,
+.fancybox-button[disabled]::after {
+ opacity: 0.3; }
+
+.fancybox-button--left::after,
+.fancybox-button--right::after {
+ top: 18px;
+ width: 6px;
+ height: 6px;
+ background: transparent;
+ border-top: solid 2px currentColor;
+ border-right: solid 2px currentColor; }
+
+.fancybox-button--left::after {
+ left: 20px;
+ -webkit-transform: rotate(-135deg);
+ -ms-transform: rotate(-135deg);
+ transform: rotate(-135deg); }
+
+.fancybox-button--right::after {
+ right: 20px;
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg); }
+
+.fancybox-button--left {
+ border-bottom-left-radius: 5px; }
+
+.fancybox-button--right {
+ border-bottom-right-radius: 5px; }
+
+.fancybox-button--close::before, .fancybox-button--close::after {
+ content: '';
+ display: inline-block;
+ position: absolute;
+ height: 2px;
+ width: 16px;
+ top: calc(50% - 1px);
+ left: calc(50% - 8px); }
+
+.fancybox-button--close::before {
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg); }
+
+.fancybox-button--close::after {
+ -webkit-transform: rotate(-45deg);
+ -ms-transform: rotate(-45deg);
+ transform: rotate(-45deg); }
+
+/* Navigation arrows */
+.fancybox-arrow {
+ position: absolute;
+ top: 50%;
+ margin: -50px 0 0 0;
+ height: 100px;
+ width: 54px;
+ padding: 0;
+ border: 0;
+ outline: none;
+ background: none;
+ cursor: pointer;
+ z-index: 99995;
+ opacity: 0;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ transition: opacity .25s; }
+
+.fancybox-arrow::after {
+ content: '';
+ position: absolute;
+ top: 28px;
+ width: 44px;
+ height: 44px;
+ background-color: rgba(30, 30, 30, 0.8);
+ background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjQ4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSI0OCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMTIgNGwtMS40MSAxLjQxTDE2LjE3IDExSDR2MmgxMi4xN2wtNS41OCA1LjU5TDEyIDIwbDgtOHoiLz48L3N2Zz4=);
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-size: 24px 24px; }
+
+.fancybox-arrow--right {
+ right: 0; }
+
+.fancybox-arrow--left {
+ left: 0;
+ -webkit-transform: scaleX(-1);
+ -ms-transform: scaleX(-1);
+ transform: scaleX(-1); }
+
+.fancybox-arrow--right::after,
+.fancybox-arrow--left::after {
+ left: 0; }
+
+.fancybox-show-nav .fancybox-arrow {
+ opacity: 0.6; }
+
+.fancybox-show-nav .fancybox-arrow[disabled] {
+ opacity: 0.3; }
+
+/* Loading indicator */
+.fancybox-loading {
+ border: 6px solid rgba(100, 100, 100, 0.4);
+ border-top: 6px solid rgba(255, 255, 255, 0.6);
+ border-radius: 100%;
+ height: 50px;
+ width: 50px;
+ -webkit-animation: fancybox-rotate .8s infinite linear;
+ animation: fancybox-rotate .8s infinite linear;
+ background: transparent;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -25px;
+ margin-left: -25px;
+ z-index: 99999; }
+
+@-webkit-keyframes fancybox-rotate {
+ from {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+ to {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg); } }
+
+@keyframes fancybox-rotate {
+ from {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+ to {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg); } }
+
+/* Transition effects */
+.fancybox-animated {
+ transition-timing-function: cubic-bezier(0, 0, 0.25, 1); }
+
+/* transitionEffect: slide */
+.fancybox-fx-slide.fancybox-slide--previous {
+ -webkit-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0);
+ opacity: 0; }
+
+.fancybox-fx-slide.fancybox-slide--next {
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ opacity: 0; }
+
+.fancybox-fx-slide.fancybox-slide--current {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ opacity: 1; }
+
+/* transitionEffect: fade */
+.fancybox-fx-fade.fancybox-slide--previous,
+.fancybox-fx-fade.fancybox-slide--next {
+ opacity: 0;
+ transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1); }
+
+.fancybox-fx-fade.fancybox-slide--current {
+ opacity: 1; }
+
+/* transitionEffect: zoom-in-out */
+.fancybox-fx-zoom-in-out.fancybox-slide--previous {
+ -webkit-transform: scale3d(1.5, 1.5, 1.5);
+ transform: scale3d(1.5, 1.5, 1.5);
+ opacity: 0; }
+
+.fancybox-fx-zoom-in-out.fancybox-slide--next {
+ -webkit-transform: scale3d(0.5, 0.5, 0.5);
+ transform: scale3d(0.5, 0.5, 0.5);
+ opacity: 0; }
+
+.fancybox-fx-zoom-in-out.fancybox-slide--current {
+ -webkit-transform: scale3d(1, 1, 1);
+ transform: scale3d(1, 1, 1);
+ opacity: 1; }
+
+/* transitionEffect: rotate */
+.fancybox-fx-rotate.fancybox-slide--previous {
+ -webkit-transform: rotate(-360deg);
+ -ms-transform: rotate(-360deg);
+ transform: rotate(-360deg);
+ opacity: 0; }
+
+.fancybox-fx-rotate.fancybox-slide--next {
+ -webkit-transform: rotate(360deg);
+ -ms-transform: rotate(360deg);
+ transform: rotate(360deg);
+ opacity: 0; }
+
+.fancybox-fx-rotate.fancybox-slide--current {
+ -webkit-transform: rotate(0deg);
+ -ms-transform: rotate(0deg);
+ transform: rotate(0deg);
+ opacity: 1; }
+
+/* transitionEffect: circular */
+.fancybox-fx-circular.fancybox-slide--previous {
+ -webkit-transform: scale3d(0, 0, 0) translate3d(-100%, 0, 0);
+ transform: scale3d(0, 0, 0) translate3d(-100%, 0, 0);
+ opacity: 0; }
+
+.fancybox-fx-circular.fancybox-slide--next {
+ -webkit-transform: scale3d(0, 0, 0) translate3d(100%, 0, 0);
+ transform: scale3d(0, 0, 0) translate3d(100%, 0, 0);
+ opacity: 0; }
+
+.fancybox-fx-circular.fancybox-slide--current {
+ -webkit-transform: scale3d(1, 1, 1) translate3d(0, 0, 0);
+ transform: scale3d(1, 1, 1) translate3d(0, 0, 0);
+ opacity: 1; }
+
+/* transitionEffect: tube */
+.fancybox-fx-tube.fancybox-slide--previous {
+ -webkit-transform: translate3d(-100%, 0, 0) scale(0.1) skew(-10deg);
+ transform: translate3d(-100%, 0, 0) scale(0.1) skew(-10deg); }
+
+.fancybox-fx-tube.fancybox-slide--next {
+ -webkit-transform: translate3d(100%, 0, 0) scale(0.1) skew(10deg);
+ transform: translate3d(100%, 0, 0) scale(0.1) skew(10deg); }
+
+.fancybox-fx-tube.fancybox-slide--current {
+ -webkit-transform: translate3d(0, 0, 0) scale(1);
+ transform: translate3d(0, 0, 0) scale(1); }
+
+/* Styling for Small-Screen Devices */
+@media all and (max-width: 800px) {
+ .fancybox-infobar {
+ left: 0;
+ margin-left: 0; }
+ .fancybox-button--left,
+ .fancybox-button--right {
+ display: none !important; }
+ .fancybox-caption {
+ padding: 20px 0;
+ margin: 0; } }
+
+/* Fullscreen */
+.fancybox-button--fullscreen::before {
+ width: 15px;
+ height: 11px;
+ left: calc(50% - 7px);
+ top: calc(50% - 6px);
+ border: 2px solid;
+ background: none; }
+
+/* Slideshow button */
+.fancybox-button--play::before,
+.fancybox-button--pause::before {
+ top: calc(50% - 6px);
+ left: calc(50% - 4px);
+ background: transparent; }
+
+.fancybox-button--play::before {
+ width: 0;
+ height: 0;
+ border-top: 6px inset transparent;
+ border-bottom: 6px inset transparent;
+ border-left: 10px solid;
+ border-radius: 1px; }
+
+.fancybox-button--pause::before {
+ width: 7px;
+ height: 11px;
+ border-style: solid;
+ border-width: 0 2px 0 2px; }
+
+/* Thumbs */
+.fancybox-thumbs {
+ display: none; }
+
+.fancybox-button--thumbs {
+ display: none; }
+
+@media all and (min-width: 800px) {
+ .fancybox-button--thumbs {
+ display: inline-block; }
+ .fancybox-button--thumbs span {
+ font-size: 23px; }
+ .fancybox-button--thumbs::before {
+ width: 3px;
+ height: 3px;
+ top: calc(50% - 2px);
+ left: calc(50% - 2px);
+ box-shadow: 0 -4px 0, -4px -4px 0, 4px -4px 0, 0 0 0 32px inset, -4px 0 0, 4px 0 0, 0 4px 0, -4px 4px 0, 4px 4px 0; }
+ .fancybox-thumbs {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: auto;
+ width: 220px;
+ margin: 0;
+ padding: 5px 5px 0 0;
+ background: #fff;
+ word-break: normal;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ box-sizing: border-box;
+ z-index: 99995; }
+ .fancybox-show-thumbs .fancybox-thumbs {
+ display: block; }
+ .fancybox-show-thumbs .fancybox-inner {
+ right: 220px; }
+ .fancybox-thumbs > ul {
+ list-style: none;
+ position: absolute;
+ position: relative;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ overflow-x: hidden;
+ overflow-y: auto;
+ font-size: 0; }
+ .fancybox-thumbs > ul > li {
+ float: left;
+ overflow: hidden;
+ max-width: 50%;
+ padding: 0;
+ margin: 0;
+ width: 105px;
+ height: 75px;
+ position: relative;
+ cursor: pointer;
+ outline: none;
+ border: 5px solid transparent;
+ border-top-width: 0;
+ border-right-width: 0;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ box-sizing: border-box; }
+ li.fancybox-thumbs-loading {
+ background: rgba(0, 0, 0, 0.1); }
+ .fancybox-thumbs > ul > li > img {
+ position: absolute;
+ top: 0;
+ left: 0;
+ min-width: 100%;
+ min-height: 100%;
+ max-width: none;
+ max-height: none;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+ .fancybox-thumbs > ul > li:before {
+ content: '';
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ border-radius: 2px;
+ border: 4px solid #4ea7f9;
+ z-index: 99991;
+ opacity: 0;
+ transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94); }
+ .fancybox-thumbs > ul > li.fancybox-thumbs-active:before {
+ opacity: 1; } }
--- /dev/null
+// ==================================================
+// fancyBox v3.1.24
+//
+// Licensed GPLv3 for open source use
+// or fancyBox Commercial License for commercial use
+//
+// http://fancyapps.com/fancybox/
+// Copyright 2017 fancyApps
+//
+// ==================================================
+;(function (window, document, $, undefined) {
+ 'use strict';
+
+ // If there's no jQuery, fancyBox can't work
+ // =========================================
+
+ if ( !$ ) {
+ return;
+ }
+
+ // Check if fancyBox is already initialized
+ // ========================================
+
+ if ( $.fn.fancybox ) {
+
+ $.error('fancyBox already initialized');
+
+ return;
+ }
+
+ // Private default settings
+ // ========================
+
+ var defaults = {
+
+ // Enable infinite gallery navigation
+ loop : false,
+
+ // Space around image, ignored if zoomed-in or viewport smaller than 800px
+ margin : [44, 0],
+
+ // Horizontal space between slides
+ gutter : 50,
+
+ // Enable keyboard navigation
+ keyboard : true,
+
+ // Should display navigation arrows at the screen edges
+ arrows : true,
+
+ // Should display infobar (counter and arrows at the top)
+ infobar : false,
+
+ // Should display toolbar (buttons at the top)
+ toolbar : true,
+
+ // What buttons should appear in the top right corner.
+ // Buttons will be created using templates from `btnTpl` option
+ // and they will be placed into toolbar (class="fancybox-toolbar"` element)
+ buttons : [
+ 'slideShow',
+ 'fullScreen',
+ 'thumbs',
+ 'close'
+ ],
+
+ // Detect "idle" time in seconds
+ idleTime : 4,
+
+ // Should display buttons at top right corner of the content
+ // If 'auto' - they will be created for content having type 'html', 'inline' or 'ajax'
+ // Use template from `btnTpl.smallBtn` for customization
+ smallBtn : 'auto',
+
+ // Disable right-click and use simple image protection for images
+ protect : false,
+
+ // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
+ modal : false,
+
+ image : {
+
+ // Wait for images to load before displaying
+ // Requires predefined image dimensions
+ // If 'auto' - will zoom in thumbnail if 'width' and 'height' attributes are found
+ preload : "auto",
+
+ },
+
+ ajax : {
+
+ // Object containing settings for ajax request
+ settings : {
+
+ // This helps to indicate that request comes from the modal
+ // Feel free to change naming
+ data : {
+ fancybox : true
+ }
+ }
+
+ },
+
+ iframe : {
+
+ // Iframe template
+ tpl : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen allowtransparency="true" src=""></iframe>',
+
+ // Preload iframe before displaying it
+ // This allows to calculate iframe content width and height
+ // (note: Due to "Same Origin Policy", you can't get cross domain data).
+ preload : true,
+
+ // Custom CSS styling for iframe wrapping element
+ // You can use this to set custom iframe dimensions
+ css : {},
+
+ // Iframe tag attributes
+ attr : {
+ scrolling : 'auto'
+ }
+
+ },
+
+ // Open/close animation type
+ // Possible values:
+ // false - disable
+ // "zoom" - zoom images from/to thumbnail
+ // "fade"
+ // "zoom-in-out"
+ //
+ animationEffect : "zoom",
+
+ // Duration in ms for open/close animation
+ animationDuration : 366,
+
+ // Should image change opacity while zooming
+ // If opacity is 'auto', then opacity will be changed if image and thumbnail have different aspect ratios
+ zoomOpacity : 'auto',
+
+ // Transition effect between slides
+ //
+ // Possible values:
+ // false - disable
+ // "fade'
+ // "slide'
+ // "circular'
+ // "tube'
+ // "zoom-in-out'
+ // "rotate'
+ //
+ transitionEffect : "fade",
+
+ // Duration in ms for transition animation
+ transitionDuration : 366,
+
+ // Custom CSS class for slide element
+ slideClass : '',
+
+ // Custom CSS class for layout
+ baseClass : '',
+
+ // Base template for layout
+ baseTpl :
+ '<div class="fancybox-container" role="dialog" tabindex="-1">' +
+ '<div class="fancybox-bg"></div>' +
+ '<div class="fancybox-inner">' +
+ '<div class="fancybox-infobar">' +
+ '<button data-fancybox-prev title="{{PREV}}" class="fancybox-button fancybox-button--left"></button>' +
+ '<div class="fancybox-infobar__body">' +
+ '<span data-fancybox-index></span> / <span data-fancybox-count></span>' +
+ '</div>' +
+ '<button data-fancybox-next title="{{NEXT}}" class="fancybox-button fancybox-button--right"></button>' +
+ '</div>' +
+ '<div class="fancybox-toolbar">' +
+ '{{BUTTONS}}' +
+ '</div>' +
+ '<div class="fancybox-navigation">' +
+ '<button data-fancybox-prev title="{{PREV}}" class="fancybox-arrow fancybox-arrow--left" />' +
+ '<button data-fancybox-next title="{{NEXT}}" class="fancybox-arrow fancybox-arrow--right" />' +
+ '</div>' +
+ '<div class="fancybox-stage"></div>' +
+ '<div class="fancybox-caption-wrap">' +
+ '<div class="fancybox-caption"></div>' +
+ '</div>' +
+ '</div>' +
+ '</div>',
+
+ // Loading indicator template
+ spinnerTpl : '<div class="fancybox-loading"></div>',
+
+ // Error message template
+ errorTpl : '<div class="fancybox-error"><p>{{ERROR}}<p></div>',
+
+ btnTpl : {
+ slideShow : '<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}"></button>',
+ fullScreen : '<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fullscreen" title="{{FULL_SCREEN}}"></button>',
+ thumbs : '<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}"></button>',
+ close : '<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}"></button>',
+
+ // This small close button will be appended to your html/inline/ajax content by default,
+ // if "smallBtn" option is not set to false
+ smallBtn : '<button data-fancybox-close class="fancybox-close-small" title="{{CLOSE}}"></button>'
+ },
+
+ // Container is injected into this element
+ parentEl : 'body',
+
+
+ // Focus handling
+ // ==============
+
+ // Try to focus on the first focusable element after opening
+ autoFocus : true,
+
+ // Put focus back to active element after closing
+ backFocus : true,
+
+ // Do not let user to focus on element outside modal content
+ trapFocus : true,
+
+
+ // Module specific options
+ // =======================
+
+ fullScreen : {
+ autoStart : false,
+ },
+
+ touch : {
+ vertical : true, // Allow to drag content vertically
+ momentum : true // Continue movement after releasing mouse/touch when panning
+ },
+
+ // Hash value when initializing manually,
+ // set `false` to disable hash change
+ hash : null,
+
+ // Customize or add new media types
+ // Example:
+ /*
+ media : {
+ youtube : {
+ params : {
+ autoplay : 0
+ }
+ }
+ }
+ */
+ media : {},
+
+ slideShow : {
+ autoStart : false,
+ speed : 4000
+ },
+
+ thumbs : {
+ autoStart : false, // Display thumbnails on opening
+ hideOnClose : true // Hide thumbnail grid when closing animation starts
+ },
+
+ // Callbacks
+ //==========
+
+ // See Documentation/API/Events for more information
+ // Example:
+ /*
+ afterShow: function( instance, current ) {
+ console.info( 'Clicked element:' );
+ console.info( current.opts.$orig );
+ }
+ */
+
+ onInit : $.noop, // When instance has been initialized
+
+ beforeLoad : $.noop, // Before the content of a slide is being loaded
+ afterLoad : $.noop, // When the content of a slide is done loading
+
+ beforeShow : $.noop, // Before open animation starts
+ afterShow : $.noop, // When content is done loading and animating
+
+ beforeClose : $.noop, // Before the instance attempts to close. Return false to cancel the close.
+ afterClose : $.noop, // After instance has been closed
+
+ onActivate : $.noop, // When instance is brought to front
+ onDeactivate : $.noop, // When other instance has been activated
+
+
+ // Interaction
+ // ===========
+
+ // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
+ // each option can be string or method that returns value.
+ //
+ // Possible values:
+ // "close" - close instance
+ // "next" - move to next gallery item
+ // "nextOrClose" - move to next gallery item or close if gallery has only one item
+ // "toggleControls" - show/hide controls
+ // "zoom" - zoom image (if loaded)
+ // false - do nothing
+
+ // Clicked on the content
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+
+ // Clicked on the slide
+ clickSlide : 'close',
+
+ // Clicked on the background (backdrop) element
+ clickOutside : 'close',
+
+ // Same as previous two, but for double click
+ dblclickContent : false,
+ dblclickSlide : false,
+ dblclickOutside : false,
+
+
+ // Custom options when mobile device is detected
+ // =============================================
+
+ mobile : {
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : false;
+ },
+ clickSlide : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : "close";
+ },
+ dblclickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+ dblclickSlide : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ }
+ },
+
+
+ // Internationalization
+ // ============
+
+ lang : 'en',
+ i18n : {
+ 'en' : {
+ CLOSE : 'Close',
+ NEXT : 'Next',
+ PREV : 'Previous',
+ ERROR : 'The requested content cannot be loaded. <br/> Please try again later.',
+ PLAY_START : 'Start slideshow',
+ PLAY_STOP : 'Pause slideshow',
+ FULL_SCREEN : 'Full screen',
+ THUMBS : 'Thumbnails'
+ },
+ 'de' : {
+ CLOSE : 'Schliessen',
+ NEXT : 'Weiter',
+ PREV : 'Zurück',
+ ERROR : 'Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es später nochmal.',
+ PLAY_START : 'Diaschau starten',
+ PLAY_STOP : 'Diaschau beenden',
+ FULL_SCREEN : 'Vollbild',
+ THUMBS : 'Vorschaubilder'
+ }
+ }
+
+ };
+
+ // Few useful variables and methods
+ // ================================
+
+ var $W = $(window);
+ var $D = $(document);
+
+ var called = 0;
+
+
+ // Check if an object is a jQuery object and not a native JavaScript object
+ // ========================================================================
+
+ var isQuery = function ( obj ) {
+ return obj && obj.hasOwnProperty && obj instanceof $;
+ };
+
+
+ // Handle multiple browsers for "requestAnimationFrame" and "cancelAnimationFrame"
+ // ===============================================================================
+
+ var requestAFrame = (function () {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ // if all else fails, use setTimeout
+ function (callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })();
+
+
+ // Detect the supported transition-end event property name
+ // =======================================================
+
+ var transitionEnd = (function () {
+ var t, el = document.createElement("fakeelement");
+
+ var transitions = {
+ "transition" : "transitionend",
+ "OTransition" : "oTransitionEnd",
+ "MozTransition" : "transitionend",
+ "WebkitTransition": "webkitTransitionEnd"
+ };
+
+ for (t in transitions) {
+ if (el.style[t] !== undefined){
+ return transitions[t];
+ }
+ }
+ })();
+
+
+ // Force redraw on an element.
+ // This helps in cases where the browser doesn't redraw an updated element properly.
+ // =================================================================================
+
+ var forceRedraw = function( $el ) {
+ return ( $el && $el.length && $el[0].offsetHeight );
+ };
+
+
+ // Class definition
+ // ================
+
+ var FancyBox = function( content, opts, index ) {
+ var self = this;
+
+ self.opts = $.extend( true, { index : index }, defaults, opts || {} );
+
+ // Exclude buttons option from deep merging
+ if ( opts && $.isArray( opts.buttons ) ) {
+ self.opts.buttons = opts.buttons;
+ }
+
+ self.id = self.opts.id || ++called;
+ self.group = [];
+
+ self.currIndex = parseInt( self.opts.index, 10 ) || 0;
+ self.prevIndex = null;
+
+ self.prevPos = null;
+ self.currPos = 0;
+
+ self.firstRun = null;
+
+ // Create group elements from original item collection
+ self.createGroup( content );
+
+ if ( !self.group.length ) {
+ return;
+ }
+
+ // Save last active element and current scroll position
+ self.$lastFocus = $(document.activeElement).blur();
+
+ // Collection of gallery objects
+ self.slides = {};
+
+ self.init( content );
+
+ };
+
+ $.extend(FancyBox.prototype, {
+
+ // Create DOM structure
+ // ====================
+
+ init : function() {
+ var self = this;
+
+ var testWidth, $container, buttonStr;
+
+ var firstItemOpts = self.group[ self.currIndex ].opts;
+
+ self.scrollTop = $D.scrollTop();
+ self.scrollLeft = $D.scrollLeft();
+
+
+ // Hide scrollbars
+ // ===============
+
+ if ( !$.fancybox.getInstance() && !$.fancybox.isMobile && $( 'body' ).css('overflow') !== 'hidden' ) {
+ testWidth = $( 'body' ).width();
+
+ $( 'html' ).addClass( 'fancybox-enabled' );
+
+ // Compare body width after applying "overflow: hidden"
+ testWidth = $( 'body' ).width() - testWidth;
+
+ // If width has changed - compensate missing scrollbars by adding right margin
+ if ( testWidth > 1 ) {
+ $( 'head' ).append( '<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar, .fancybox-enabled body { margin-right: ' + testWidth + 'px; }</style>' );
+ }
+ }
+
+
+ // Build html markup and set references
+ // ====================================
+
+ // Build html code for buttons and insert into main template
+ buttonStr = '';
+
+ $.each( firstItemOpts.buttons, function( index, value ) {
+ buttonStr += ( firstItemOpts.btnTpl[ value ] || '' );
+ });
+
+ // Create markup from base template, it will be initially hidden to
+ // avoid unnecessary work like painting while initializing is not complete
+ $container = $( self.translate( self, firstItemOpts.baseTpl.replace( '\{\{BUTTONS\}\}', buttonStr ) ) )
+ .addClass( 'fancybox-is-hidden' )
+ .attr('id', 'fancybox-container-' + self.id)
+ .addClass( firstItemOpts.baseClass )
+ .data( 'FancyBox', self )
+ .prependTo( firstItemOpts.parentEl );
+
+ // Create object holding references to jQuery wrapped nodes
+ self.$refs = {
+ container : $container
+ };
+
+ [ 'bg', 'inner', 'infobar', 'toolbar', 'stage', 'caption' ].forEach(function(item) {
+ self.$refs[ item ] = $container.find( '.fancybox-' + item );
+ });
+
+ // Check for redundant elements
+ if ( !firstItemOpts.arrows || self.group.length < 2 ) {
+ $container.find('.fancybox-navigation').remove();
+ }
+
+ if ( !firstItemOpts.infobar ) {
+ self.$refs.infobar.remove();
+ }
+
+ if ( !firstItemOpts.toolbar ) {
+ self.$refs.toolbar.remove();
+ }
+
+ self.trigger( 'onInit' );
+
+ // Bring to front and enable events
+ self.activate();
+
+ // Build slides, load and reveal content
+ self.jumpTo( self.currIndex );
+ },
+
+
+ // Simple i18n support - replaces object keys found in template
+ // with corresponding values
+ // ============================================================
+
+ translate : function( obj, str ) {
+ var arr = obj.opts.i18n[ obj.opts.lang ];
+
+ return str.replace(/\{\{(\w+)\}\}/g, function(match, n) {
+ var value = arr[n];
+
+ if ( value === undefined ) {
+ return match;
+ }
+
+ return value;
+ });
+ },
+
+ // Create array of gally item objects
+ // Check if each object has valid type and content
+ // ===============================================
+
+ createGroup : function ( content ) {
+ var self = this;
+ var items = $.makeArray( content );
+
+ $.each(items, function( i, item ) {
+ var obj = {},
+ opts = {},
+ data = [],
+ $item,
+ type,
+ src,
+ srcParts;
+
+ // Step 1 - Make sure we have an object
+ // ====================================
+
+ if ( $.isPlainObject( item ) ) {
+
+ // We probably have manual usage here, something like
+ // $.fancybox.open( [ { src : "image.jpg", type : "image" } ] )
+
+ obj = item;
+ opts = item.opts || item;
+
+ } else if ( $.type( item ) === 'object' && $( item ).length ) {
+
+ // Here we propbably have jQuery collection returned by some selector
+
+ $item = $( item );
+ data = $item.data();
+
+ opts = 'options' in data ? data.options : {};
+ opts = $.type( opts ) === 'object' ? opts : {};
+
+ obj.src = 'src' in data ? data.src : ( opts.src || $item.attr( 'href' ) );
+
+ [ 'width', 'height', 'thumb', 'type', 'filter' ].forEach(function(item) {
+ if ( item in data ) {
+ opts[ item ] = data[ item ];
+ }
+ });
+
+ if ( 'srcset' in data ) {
+ opts.image = { srcset : data.srcset };
+ }
+
+ opts.$orig = $item;
+
+ if ( !obj.type && !obj.src ) {
+ obj.type = 'inline';
+ obj.src = item;
+ }
+
+ } else {
+
+ // Assume we have a simple html code, for example:
+ // $.fancybox.open( '<div><h1>Hi!</h1></div>' );
+
+ obj = {
+ type : 'html',
+ src : item + ''
+ };
+
+ }
+
+ // Each gallery object has full collection of options
+ obj.opts = $.extend( true, {}, self.opts, opts );
+
+ if ( $.fancybox.isMobile ) {
+ obj.opts = $.extend( true, {}, obj.opts, obj.opts.mobile );
+ }
+
+
+ // Step 2 - Make sure we have content type, if not - try to guess
+ // ==============================================================
+
+ type = obj.type || obj.opts.type;
+ src = obj.src || '';
+
+ if ( !type && src ) {
+ if ( src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i) ) {
+ type = 'image';
+
+ } else if ( src.match(/\.(pdf)((\?|#).*)?$/i) ) {
+ type = 'pdf';
+
+ } else if ( src.charAt(0) === '#' ) {
+ type = 'inline';
+ }
+ }
+
+ obj.type = type;
+
+
+ // Step 3 - Some adjustments
+ // =========================
+
+ obj.index = self.group.length;
+
+ // Check if $orig and $thumb objects exist
+ if ( obj.opts.$orig && !obj.opts.$orig.length ) {
+ delete obj.opts.$orig;
+ }
+
+ if ( !obj.opts.$thumb && obj.opts.$orig ) {
+ obj.opts.$thumb = obj.opts.$orig.find( 'img:first' );
+ }
+
+ if ( obj.opts.$thumb && !obj.opts.$thumb.length ) {
+ delete obj.opts.$thumb;
+ }
+
+ // Caption is a "special" option, it can be passed as a method
+ if ( $.type( obj.opts.caption ) === 'function' ) {
+ obj.opts.caption = obj.opts.caption.apply( item, [ self, obj ] );
+
+ } else if ( 'caption' in data ) {
+ obj.opts.caption = data.caption;
+ }
+
+ // Make sure we have caption as a string
+ obj.opts.caption = obj.opts.caption === undefined ? '' : obj.opts.caption + '';
+
+ // Check if url contains "filter" used to filter the content
+ // Example: "ajax.html #something"
+ if ( type === 'ajax' ) {
+ srcParts = src.split(/\s+/, 2);
+
+ if ( srcParts.length > 1 ) {
+ obj.src = srcParts.shift();
+
+ obj.opts.filter = srcParts.shift();
+ }
+ }
+
+ if ( obj.opts.smallBtn == 'auto' ) {
+
+ if ( $.inArray( type, ['html', 'inline', 'ajax'] ) > -1 ) {
+ obj.opts.toolbar = false;
+ obj.opts.smallBtn = true;
+
+ } else {
+ obj.opts.smallBtn = false;
+ }
+
+ }
+
+ // If the type is "pdf", then simply load file into iframe
+ if ( type === 'pdf' ) {
+ obj.type = 'iframe';
+
+ obj.opts.iframe.preload = false;
+ }
+
+ // Hide all buttons and disable interactivity for modal items
+ if ( obj.opts.modal ) {
+
+ obj.opts = $.extend(true, obj.opts, {
+ // Remove buttons
+ infobar : 0,
+ toolbar : 0,
+
+ smallBtn : 0,
+
+ // Disable keyboard navigation
+ keyboard : 0,
+
+ // Disable some modules
+ slideShow : 0,
+ fullScreen : 0,
+ thumbs : 0,
+ touch : 0,
+
+ // Disable click event handlers
+ clickContent : false,
+ clickSlide : false,
+ clickOutside : false,
+ dblclickContent : false,
+ dblclickSlide : false,
+ dblclickOutside : false
+ });
+
+ }
+
+ // Step 4 - Add processed object to group
+ // ======================================
+
+ self.group.push( obj );
+
+ });
+
+ },
+
+
+ // Attach an event handler functions for:
+ // - navigation buttons
+ // - browser scrolling, resizing;
+ // - focusing
+ // - keyboard
+ // - detect idle
+ // ======================================
+
+ addEvents : function() {
+ var self = this;
+
+ self.removeEvents();
+
+ // Make navigation elements clickable
+ self.$refs.container.on('click.fb-close', '[data-fancybox-close]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.close( e );
+
+ }).on( 'click.fb-prev touchend.fb-prev', '[data-fancybox-prev]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.previous();
+
+ }).on( 'click.fb-next touchend.fb-next', '[data-fancybox-next]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.next();
+
+ });
+
+
+ // Handle page scrolling and browser resizing
+ $W.on('orientationchange.fb resize.fb', function(e) {
+
+ if ( e && e.originalEvent && e.originalEvent.type === "resize" ) {
+
+ requestAFrame(function() {
+ self.update();
+ });
+
+ } else {
+
+ self.$refs.stage.hide();
+
+ setTimeout(function() {
+ self.$refs.stage.show();
+
+ self.update();
+ }, 500);
+
+ }
+
+ });
+
+ // Trap keyboard focus inside of the modal, so the user does not accidentally tab outside of the modal
+ // (a.k.a. "escaping the modal")
+ $D.on('focusin.fb', function(e) {
+ var instance = $.fancybox ? $.fancybox.getInstance() : null;
+
+ if ( instance.isClosing || !instance.current || !instance.current.opts.trapFocus || $( e.target ).hasClass( 'fancybox-container' ) || $( e.target ).is( document ) ) {
+ return;
+ }
+
+ if ( instance && $( e.target ).css( 'position' ) !== 'fixed' && !instance.$refs.container.has( e.target ).length ) {
+ e.stopPropagation();
+
+ instance.focus();
+
+ // Sometimes page gets scrolled, set it back
+ $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
+ }
+ });
+
+
+ // Enable keyboard navigation
+ $D.on('keydown.fb', function (e) {
+ var current = self.current,
+ keycode = e.keyCode || e.which;
+
+ if ( !current || !current.opts.keyboard ) {
+ return;
+ }
+
+ if ( $(e.target).is('input') || $(e.target).is('textarea') ) {
+ return;
+ }
+
+ // Backspace and Esc keys
+ if ( keycode === 8 || keycode === 27 ) {
+ e.preventDefault();
+
+ self.close( e );
+
+ return;
+ }
+
+ // Left arrow and Up arrow
+ if ( keycode === 37 || keycode === 38 ) {
+ e.preventDefault();
+
+ self.previous();
+
+ return;
+ }
+
+ // Righ arrow and Down arrow
+ if ( keycode === 39 || keycode === 40 ) {
+ e.preventDefault();
+
+ self.next();
+
+ return;
+ }
+
+ self.trigger('afterKeydown', e, keycode);
+ });
+
+
+ // Hide controls after some inactivity period
+ if ( self.group[ self.currIndex ].opts.idleTime ) {
+ self.idleSecondsCounter = 0;
+
+ $D.on('mousemove.fb-idle mouseenter.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle', function() {
+ self.idleSecondsCounter = 0;
+
+ if ( self.isIdle ) {
+ self.showControls();
+ }
+
+ self.isIdle = false;
+ });
+
+ self.idleInterval = window.setInterval(function() {
+
+ self.idleSecondsCounter++;
+
+ if ( self.idleSecondsCounter >= self.group[ self.currIndex ].opts.idleTime ) {
+ self.isIdle = true;
+ self.idleSecondsCounter = 0;
+
+ self.hideControls();
+ }
+
+ }, 1000);
+ }
+
+ },
+
+
+ // Remove events added by the core
+ // ===============================
+
+ removeEvents : function () {
+ var self = this;
+
+ $W.off( 'orientationchange.fb resize.fb' );
+ $D.off( 'focusin.fb keydown.fb .fb-idle' );
+
+ this.$refs.container.off( '.fb-close .fb-prev .fb-next' );
+
+ if ( self.idleInterval ) {
+ window.clearInterval( self.idleInterval );
+
+ self.idleInterval = null;
+ }
+ },
+
+
+ // Change to previous gallery item
+ // ===============================
+
+ previous : function( duration ) {
+ return this.jumpTo( this.currPos - 1, duration );
+ },
+
+
+ // Change to next gallery item
+ // ===========================
+
+ next : function( duration ) {
+ return this.jumpTo( this.currPos + 1, duration );
+ },
+
+
+ // Switch to selected gallery item
+ // ===============================
+
+ jumpTo : function ( pos, duration, slide ) {
+ var self = this,
+ firstRun,
+ loop,
+ current,
+ previous,
+ canvasWidth,
+ currentPos,
+ transitionProps;
+
+ var groupLen = self.group.length;
+
+ if ( self.isSliding || self.isClosing || ( self.isAnimating && self.firstRun ) ) {
+ return;
+ }
+
+ pos = parseInt( pos, 10 );
+ loop = self.current ? self.current.opts.loop : self.opts.loop;
+
+ if ( !loop && ( pos < 0 || pos >= groupLen ) ) {
+ return false;
+ }
+
+ firstRun = self.firstRun = ( self.firstRun === null );
+
+ if ( groupLen < 2 && !firstRun && !!self.isSliding ) {
+ return;
+ }
+
+ previous = self.current;
+
+ self.prevIndex = self.currIndex;
+ self.prevPos = self.currPos;
+
+ // Create slides
+ current = self.createSlide( pos );
+
+ if ( groupLen > 1 ) {
+ if ( loop || current.index > 0 ) {
+ self.createSlide( pos - 1 );
+ }
+
+ if ( loop || current.index < groupLen - 1 ) {
+ self.createSlide( pos + 1 );
+ }
+ }
+
+ self.current = current;
+ self.currIndex = current.index;
+ self.currPos = current.pos;
+
+ self.trigger( 'beforeShow', firstRun );
+
+ self.updateControls();
+
+ currentPos = $.fancybox.getTranslate( current.$slide );
+
+ current.isMoved = ( currentPos.left !== 0 || currentPos.top !== 0 ) && !current.$slide.hasClass( 'fancybox-animated' );
+ current.forcedDuration = undefined;
+
+ if ( $.isNumeric( duration ) ) {
+ current.forcedDuration = duration;
+ } else {
+ duration = current.opts[ firstRun ? 'animationDuration' : 'transitionDuration' ];
+ }
+
+ duration = parseInt( duration, 10 );
+
+ // Fresh start - reveal container, current slide and start loading content
+ if ( firstRun ) {
+
+ if ( current.opts.animationEffect && duration ) {
+ self.$refs.container.css( 'transition-duration', duration + 'ms' );
+ }
+
+ self.$refs.container.removeClass( 'fancybox-is-hidden' );
+
+ forceRedraw( self.$refs.container );
+
+ self.$refs.container.addClass( 'fancybox-is-open' );
+
+ // Make first slide visible (to display loading icon, if needed)
+ current.$slide.addClass( 'fancybox-slide--current' );
+
+ self.loadSlide( current );
+
+ self.preload();
+
+ return;
+ }
+
+ // Clean up
+ $.each(self.slides, function( index, slide ) {
+ $.fancybox.stop( slide.$slide );
+ });
+
+ // Make current that slide is visible even if content is still loading
+ current.$slide.removeClass( 'fancybox-slide--next fancybox-slide--previous' ).addClass( 'fancybox-slide--current' );
+
+ // If slides have been dragged, animate them to correct position
+ if ( current.isMoved ) {
+ canvasWidth = Math.round( current.$slide.width() );
+
+ $.each(self.slides, function( index, slide ) {
+ var pos = slide.pos - current.pos;
+
+ $.fancybox.animate( slide.$slide, {
+ top : 0,
+ left : ( pos * canvasWidth ) + ( pos * slide.opts.gutter )
+ }, duration, function() {
+
+ slide.$slide.removeAttr('style').removeClass( 'fancybox-slide--next fancybox-slide--previous' );
+
+ if ( slide.pos === self.currPos ) {
+ current.isMoved = false;
+
+ self.complete();
+ }
+ });
+ });
+
+ } else {
+ self.$refs.stage.children().removeAttr( 'style' );
+ }
+
+ // Start transition that reveals current content
+ // or wait when it will be loaded
+
+ if ( current.isLoaded ) {
+ self.revealContent( current );
+
+ } else {
+ self.loadSlide( current );
+ }
+
+ self.preload();
+
+ if ( previous.pos === current.pos ) {
+ return;
+ }
+
+ // Handle previous slide
+ // =====================
+
+ transitionProps = 'fancybox-slide--' + ( previous.pos > current.pos ? 'next' : 'previous' );
+
+ previous.$slide.removeClass( 'fancybox-slide--complete fancybox-slide--current fancybox-slide--next fancybox-slide--previous' );
+
+ previous.isComplete = false;
+
+ if ( !duration || ( !current.isMoved && !current.opts.transitionEffect ) ) {
+ return;
+ }
+
+ if ( current.isMoved ) {
+ previous.$slide.addClass( transitionProps );
+
+ } else {
+
+ transitionProps = 'fancybox-animated ' + transitionProps + ' fancybox-fx-' + current.opts.transitionEffect;
+
+ $.fancybox.animate( previous.$slide, transitionProps, duration, function() {
+ previous.$slide.removeClass( transitionProps ).removeAttr( 'style' );
+ });
+
+ }
+
+ },
+
+
+ // Create new "slide" element
+ // These are gallery items that are actually added to DOM
+ // =======================================================
+
+ createSlide : function( pos ) {
+
+ var self = this;
+ var $slide;
+ var index;
+
+ index = pos % self.group.length;
+ index = index < 0 ? self.group.length + index : index;
+
+ if ( !self.slides[ pos ] && self.group[ index ] ) {
+ $slide = $('<div class="fancybox-slide"></div>').appendTo( self.$refs.stage );
+
+ self.slides[ pos ] = $.extend( true, {}, self.group[ index ], {
+ pos : pos,
+ $slide : $slide,
+ isLoaded : false,
+ });
+
+ self.updateSlide( self.slides[ pos ] );
+ }
+
+ return self.slides[ pos ];
+ },
+
+
+ // Scale image to the actual size of the image
+ // ===========================================
+
+ scaleToActual : function( x, y, duration ) {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var imgPos, posX, posY, scaleX, scaleY;
+
+ var canvasWidth = parseInt( current.$slide.width(), 10 );
+ var canvasHeight = parseInt( current.$slide.height(), 10 );
+
+ var newImgWidth = current.width;
+ var newImgHeight = current.height;
+
+ if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating) {
+ return;
+ }
+
+ $.fancybox.stop( $what );
+
+ self.isAnimating = true;
+
+ x = x === undefined ? canvasWidth * 0.5 : x;
+ y = y === undefined ? canvasHeight * 0.5 : y;
+
+ imgPos = $.fancybox.getTranslate( $what );
+
+ scaleX = newImgWidth / imgPos.width;
+ scaleY = newImgHeight / imgPos.height;
+
+ // Get center position for original image
+ posX = ( canvasWidth * 0.5 - newImgWidth * 0.5 );
+ posY = ( canvasHeight * 0.5 - newImgHeight * 0.5 );
+
+ // Make sure image does not move away from edges
+ if ( newImgWidth > canvasWidth ) {
+ posX = imgPos.left * scaleX - ( ( x * scaleX ) - x );
+
+ if ( posX > 0 ) {
+ posX = 0;
+ }
+
+ if ( posX < canvasWidth - newImgWidth ) {
+ posX = canvasWidth - newImgWidth;
+ }
+ }
+
+ if ( newImgHeight > canvasHeight) {
+ posY = imgPos.top * scaleY - ( ( y * scaleY ) - y );
+
+ if ( posY > 0 ) {
+ posY = 0;
+ }
+
+ if ( posY < canvasHeight - newImgHeight ) {
+ posY = canvasHeight - newImgHeight;
+ }
+ }
+
+ self.updateCursor( newImgWidth, newImgHeight );
+
+ $.fancybox.animate( $what, {
+ top : posY,
+ left : posX,
+ scaleX : scaleX,
+ scaleY : scaleY
+ }, duration || 330, function() {
+ self.isAnimating = false;
+ });
+
+ // Stop slideshow
+ if ( self.SlideShow && self.SlideShow.isActive ) {
+ self.SlideShow.stop();
+ }
+ },
+
+
+ // Scale image to fit inside parent element
+ // ========================================
+
+ scaleToFit : function( duration ) {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+ var end;
+
+ if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating ) {
+ return;
+ }
+
+ $.fancybox.stop( $what );
+
+ self.isAnimating = true;
+
+ end = self.getFitPos( current );
+
+ self.updateCursor( end.width, end.height );
+
+ $.fancybox.animate( $what, {
+ top : end.top,
+ left : end.left,
+ scaleX : end.width / $what.width(),
+ scaleY : end.height / $what.height()
+ }, duration || 330, function() {
+ self.isAnimating = false;
+ });
+
+ },
+
+ // Calculate image size to fit inside viewport
+ // ===========================================
+
+ getFitPos : function( slide ) {
+ var self = this;
+ var $what = slide.$content;
+
+ var imgWidth = slide.width;
+ var imgHeight = slide.height;
+
+ var margin = slide.opts.margin;
+
+ var canvasWidth, canvasHeight, minRatio, width, height;
+
+ if ( !$what || !$what.length || ( !imgWidth && !imgHeight) ) {
+ return false;
+ }
+
+ // Convert "margin to CSS style: [ top, right, bottom, left ]
+ if ( $.type( margin ) === "number" ) {
+ margin = [ margin, margin ];
+ }
+
+ if ( margin.length == 2 ) {
+ margin = [ margin[0], margin[1], margin[0], margin[1] ];
+ }
+
+ if ( $W.width() < 800 ) {
+ margin = [ 0, 0, 0, 0 ];
+ }
+
+ // We can not use $slide width here, because it can have different diemensions while in transiton
+ canvasWidth = parseInt( self.$refs.stage.width(), 10 ) - ( margin[ 1 ] + margin[ 3 ] );
+ canvasHeight = parseInt( self.$refs.stage.height(), 10 ) - ( margin[ 0 ] + margin[ 2 ] );
+
+ minRatio = Math.min(1, canvasWidth / imgWidth, canvasHeight / imgHeight );
+
+ width = Math.floor( minRatio * imgWidth );
+ height = Math.floor( minRatio * imgHeight );
+
+ // Use floor rounding to make sure it really fits
+ return {
+ top : Math.floor( ( canvasHeight - height ) * 0.5 ) + margin[ 0 ],
+ left : Math.floor( ( canvasWidth - width ) * 0.5 ) + margin[ 3 ],
+ width : width,
+ height : height
+ };
+
+ },
+
+
+ // Update position and content of all slides
+ // =========================================
+
+ update : function() {
+
+ var self = this;
+
+ $.each( self.slides, function( key, slide ) {
+ self.updateSlide( slide );
+ });
+
+ },
+
+
+ // Update slide position and scale content to fit
+ // ==============================================
+
+ updateSlide : function( slide ) {
+
+ var self = this;
+ var $what = slide.$content;
+
+ if ( $what && ( slide.width || slide.height ) ) {
+ $.fancybox.stop( $what );
+
+ $.fancybox.setTranslate( $what, self.getFitPos( slide ) );
+
+ if ( slide.pos === self.currPos ) {
+ self.updateCursor();
+ }
+ }
+
+ slide.$slide.trigger( 'refresh' );
+
+ self.trigger( 'onUpdate', slide );
+
+ },
+
+ // Update cursor style depending if content can be zoomed
+ // ======================================================
+
+ updateCursor : function( nextWidth, nextHeight ) {
+
+ var self = this;
+ var isScaledDown;
+
+ var $container = self.$refs.container.removeClass('fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-drag fancybox-can-zoomOut');
+
+ if ( !self.current || self.isClosing ) {
+ return;
+ }
+
+ if ( self.isZoomable() ) {
+
+ $container.addClass( 'fancybox-is-zoomable' );
+
+ if ( nextWidth !== undefined && nextHeight !== undefined ) {
+ isScaledDown = nextWidth < self.current.width && nextHeight < self.current.height;
+
+ } else {
+ isScaledDown = self.isScaledDown();
+ }
+
+ if ( isScaledDown ) {
+
+ // If image is scaled down, then, obviously, it can be zoomed to full size
+ $container.addClass('fancybox-can-zoomIn');
+
+ } else {
+
+ if ( self.current.opts.touch ) {
+
+ // If image size ir largen than available available and touch module is not disable,
+ // then user can do panning
+ $container.addClass('fancybox-can-drag');
+
+ } else {
+ $container.addClass('fancybox-can-zoomOut');
+ }
+
+ }
+
+ } else if ( self.current.opts.touch ) {
+ $container.addClass('fancybox-can-drag');
+ }
+
+ },
+
+
+ // Check if current slide is zoomable
+ // ==================================
+
+ isZoomable : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var fitPos;
+
+ if ( !current || self.isClosing ) {
+ return;
+ }
+
+ // Assume that slide is zoomable if
+ // - image is loaded successfuly
+ // - click action is "zoom"
+ // - actual size of the image is smaller than available area
+ if ( current.type === 'image' && current.isLoaded && !current.hasError &&
+ ( current.opts.clickContent === 'zoom' || ( $.isFunction( current.opts.clickContent ) && current.opts.clickContent( current ) === "zoom" ) )
+ ) {
+
+ fitPos = self.getFitPos( current );
+
+ if ( current.width > fitPos.width || current.height > fitPos.height ) {
+ return true;
+ }
+
+ }
+
+ return false;
+
+ },
+
+
+ // Check if current image dimensions are smaller than actual
+ // =========================================================
+
+ isScaledDown : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var rez = false;
+
+ if ( $what ) {
+ rez = $.fancybox.getTranslate( $what );
+ rez = rez.width < current.width || rez.height < current.height;
+ }
+
+ return rez;
+
+ },
+
+
+ // Check if image dimensions exceed parent element
+ // ===============================================
+
+ canPan : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var rez = false;
+
+ if ( $what ) {
+ rez = self.getFitPos( current );
+ rez = Math.abs( $what.width() - rez.width ) > 1 || Math.abs( $what.height() - rez.height ) > 1;
+
+ }
+
+ return rez;
+
+ },
+
+
+ // Load content into the slide
+ // ===========================
+
+ loadSlide : function( slide ) {
+
+ var self = this, type, $slide;
+ var ajaxLoad;
+
+ if ( slide.isLoading ) {
+ return;
+ }
+
+ if ( slide.isLoaded ) {
+ return;
+ }
+
+ slide.isLoading = true;
+
+ self.trigger( 'beforeLoad', slide );
+
+ type = slide.type;
+ $slide = slide.$slide;
+
+ $slide
+ .off( 'refresh' )
+ .trigger( 'onReset' )
+ .addClass( 'fancybox-slide--' + ( type || 'unknown' ) )
+ .addClass( slide.opts.slideClass );
+
+ // Create content depending on the type
+
+ switch ( type ) {
+
+ case 'image':
+
+ self.setImage( slide );
+
+ break;
+
+ case 'iframe':
+
+ self.setIframe( slide );
+
+ break;
+
+ case 'html':
+
+ self.setContent( slide, slide.src || slide.content );
+
+ break;
+
+ case 'inline':
+
+ if ( $( slide.src ).length ) {
+ self.setContent( slide, $( slide.src ) );
+
+ } else {
+ self.setError( slide );
+ }
+
+ break;
+
+ case 'ajax':
+
+ self.showLoading( slide );
+
+ ajaxLoad = $.ajax( $.extend( {}, slide.opts.ajax.settings, {
+ url : slide.src,
+ success : function ( data, textStatus ) {
+
+ if ( textStatus === 'success' ) {
+ self.setContent( slide, data );
+ }
+
+ },
+ error : function ( jqXHR, textStatus ) {
+
+ if ( jqXHR && textStatus !== 'abort' ) {
+ self.setError( slide );
+ }
+
+ }
+ }));
+
+ $slide.one( 'onReset', function () {
+ ajaxLoad.abort();
+ });
+
+ break;
+
+ default:
+
+ self.setError( slide );
+
+ break;
+
+ }
+
+ return true;
+
+ },
+
+
+ // Use thumbnail image, if possible
+ // ================================
+
+ setImage : function( slide ) {
+
+ var self = this;
+ var srcset = slide.opts.image.srcset;
+
+ var found, temp, pxRatio, windowWidth;
+
+ // If we have "srcset", then we need to find matching "src" value.
+ // This is necessary, because when you set an src attribute, the browser will preload the image
+ // before any javascript or even CSS is applied.
+ if ( srcset ) {
+ pxRatio = window.devicePixelRatio || 1;
+ windowWidth = window.innerWidth * pxRatio;
+
+ temp = srcset.split(',').map(function ( el ) {
+ var ret = {};
+
+ el.trim().split(/\s+/).forEach(function ( el, i ) {
+ var value = parseInt( el.substring(0, el.length - 1), 10 );
+
+ if ( i === 0 ) {
+ return ( ret.url = el );
+ }
+
+ if ( value ) {
+ ret.value = value;
+ ret.postfix = el[ el.length - 1 ];
+ }
+
+ });
+
+ return ret;
+ });
+
+ // Sort by value
+ temp.sort(function (a, b) {
+ return a.value - b.value;
+ });
+
+ // Ok, now we have an array of all srcset values
+ for ( var j = 0; j < temp.length; j++ ) {
+ var el = temp[ j ];
+
+ if ( ( el.postfix === 'w' && el.value >= windowWidth ) || ( el.postfix === 'x' && el.value >= pxRatio ) ) {
+ found = el;
+ break;
+ }
+ }
+
+ // If not found, take the last one
+ if ( !found && temp.length ) {
+ found = temp[ temp.length - 1 ];
+ }
+
+ if ( found ) {
+ slide.src = found.url;
+
+ // If we have default width/height values, we can calculate height for matching source
+ if ( slide.width && slide.height && found.postfix == 'w' ) {
+ slide.height = ( slide.width / slide.height ) * found.value;
+ slide.width = found.value;
+ }
+ }
+ }
+
+ // This will be wrapper containing both ghost and actual image
+ slide.$content = $('<div class="fancybox-image-wrap"></div>')
+ .addClass( 'fancybox-is-hidden' )
+ .appendTo( slide.$slide );
+
+
+ // If we have a thumbnail, we can display it while actual image is loading
+ // Users will not stare at black screen and actual image will appear gradually
+ if ( slide.opts.preload !== false && slide.opts.width && slide.opts.height && ( slide.opts.thumb || slide.opts.$thumb ) ) {
+
+ slide.width = slide.opts.width;
+ slide.height = slide.opts.height;
+
+ slide.$ghost = $('<img />')
+ .one('error', function() {
+
+ $(this).remove();
+
+ slide.$ghost = null;
+
+ self.setBigImage( slide );
+
+ })
+ .one('load', function() {
+
+ self.afterLoad( slide );
+
+ self.setBigImage( slide );
+
+ })
+ .addClass( 'fancybox-image' )
+ .appendTo( slide.$content )
+ .attr( 'src', slide.opts.thumb || slide.opts.$thumb.attr( 'src' ) );
+
+ } else {
+
+ self.setBigImage( slide );
+
+ }
+
+ },
+
+
+ // Create full-size image
+ // ======================
+
+ setBigImage : function ( slide ) {
+ var self = this;
+ var $img = $('<img />');
+
+ slide.$image = $img
+ .one('error', function() {
+
+ self.setError( slide );
+
+ })
+ .one('load', function() {
+
+ // Clear timeout that checks if loading icon needs to be displayed
+ clearTimeout( slide.timouts );
+
+ slide.timouts = null;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ slide.width = this.naturalWidth;
+ slide.height = this.naturalHeight;
+
+ if ( slide.opts.image.srcset ) {
+ $img.attr( 'sizes', '100vw' ).attr( 'srcset', slide.opts.image.srcset );
+ }
+
+ self.hideLoading( slide );
+
+ if ( slide.$ghost ) {
+
+ slide.timouts = setTimeout(function() {
+ slide.timouts = null;
+
+ slide.$ghost.hide();
+
+ }, Math.min( 300, Math.max( 1000, slide.height / 1600 ) ) );
+
+ } else {
+ self.afterLoad( slide );
+ }
+
+ })
+ .addClass( 'fancybox-image' )
+ .attr('src', slide.src)
+ .appendTo( slide.$content );
+
+ if ( $img[0].complete ) {
+ $img.trigger( 'load' );
+
+ } else if( $img[0].error ) {
+ $img.trigger( 'error' );
+
+ } else {
+
+ slide.timouts = setTimeout(function() {
+ if ( !$img[0].complete && !slide.hasError ) {
+ self.showLoading( slide );
+ }
+
+ }, 100);
+
+ }
+
+ },
+
+
+ // Create iframe wrapper, iframe and bindings
+ // ==========================================
+
+ setIframe : function( slide ) {
+ var self = this,
+ opts = slide.opts.iframe,
+ $slide = slide.$slide,
+ $iframe;
+
+ slide.$content = $('<div class="fancybox-content' + ( opts.preload ? ' fancybox-is-hidden' : '' ) + '"></div>')
+ .css( opts.css )
+ .appendTo( $slide );
+
+ $iframe = $( opts.tpl.replace(/\{rnd\}/g, new Date().getTime()) )
+ .attr( opts.attr )
+ .appendTo( slide.$content );
+
+ if ( opts.preload ) {
+
+ self.showLoading( slide );
+
+ // Unfortunately, it is not always possible to determine if iframe is successfully loaded
+ // (due to browser security policy)
+
+ $iframe.on('load.fb error.fb', function(e) {
+ this.isReady = 1;
+
+ slide.$slide.trigger( 'refresh' );
+
+ self.afterLoad( slide );
+ });
+
+ // Recalculate iframe content size
+ // ===============================
+
+ $slide.on('refresh.fb', function() {
+ var $wrap = slide.$content,
+ $contents,
+ $body,
+ scrollWidth,
+ frameWidth,
+ frameHeight;
+
+ if ( $iframe[0].isReady !== 1 ) {
+ return;
+ }
+
+ // Check if content is accessible,
+ // it will fail if frame is not with the same origin
+
+ try {
+ $contents = $iframe.contents();
+ $body = $contents.find('body');
+
+ } catch (ignore) {}
+
+ // Calculate dimensions for the wrapper
+ if ( $body && $body.length && !( opts.css.width !== undefined && opts.css.height !== undefined ) ) {
+
+ scrollWidth = $iframe[0].contentWindow.document.documentElement.scrollWidth;
+
+ frameWidth = Math.ceil( $body.outerWidth(true) + ( $wrap.width() - scrollWidth ) );
+ frameHeight = Math.ceil( $body.outerHeight(true) );
+
+ // Resize wrapper to fit iframe content
+ $wrap.css({
+ 'width' : opts.css.width === undefined ? frameWidth + ( $wrap.outerWidth() - $wrap.innerWidth() ) : opts.css.width,
+ 'height' : opts.css.height === undefined ? frameHeight + ( $wrap.outerHeight() - $wrap.innerHeight() ) : opts.css.height
+ });
+
+ }
+
+ $wrap.removeClass( 'fancybox-is-hidden' );
+
+ });
+
+ } else {
+
+ this.afterLoad( slide );
+
+ }
+
+ $iframe.attr( 'src', slide.src );
+
+ if ( slide.opts.smallBtn === true ) {
+ slide.$content.prepend( self.translate( slide, slide.opts.btnTpl.smallBtn ) );
+ }
+
+ // Remove iframe if closing or changing gallery item
+ $slide.one( 'onReset', function () {
+
+ // This helps IE not to throw errors when closing
+ try {
+
+ $( this ).find( 'iframe' ).hide().attr( 'src', '//about:blank' );
+
+ } catch ( ignore ) {}
+
+ $( this ).empty();
+
+ slide.isLoaded = false;
+
+ });
+
+ },
+
+
+ // Wrap and append content to the slide
+ // ======================================
+
+ setContent : function ( slide, content ) {
+
+ var self = this;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ self.hideLoading( slide );
+
+ slide.$slide.empty();
+
+ if ( isQuery( content ) && content.parent().length ) {
+
+ // If content is a jQuery object, then it will be moved to the slide.
+ // The placeholder is created so we will know where to put it back.
+ // If user is navigating gallery fast, then the content might be already inside fancyBox
+ // =====================================================================================
+
+ // Make sure content is not already moved to fancyBox
+ content.parent( '.fancybox-slide--inline' ).trigger( 'onReset' );
+
+ // Create temporary element marking original place of the content
+ slide.$placeholder = $( '<div></div>' ).hide().insertAfter( content );
+
+ // Make sure content is visible
+ content.css('display', 'inline-block');
+
+ } else if ( !slide.hasError ) {
+
+ // If content is just a plain text, try to convert it to html
+ if ( $.type( content ) === 'string' ) {
+ content = $('<div>').append( $.trim( content ) ).contents();
+
+ // If we have text node, then add wrapping element to make vertical alignment work
+ if ( content[0].nodeType === 3 ) {
+ content = $('<div>').html( content );
+ }
+ }
+
+ // If "filter" option is provided, then filter content
+ if ( slide.opts.filter ) {
+ content = $('<div>').html( content ).find( slide.opts.filter );
+ }
+
+ }
+
+ slide.$slide.one('onReset', function () {
+
+ // Put content back
+ if ( slide.$placeholder ) {
+ slide.$placeholder.after( content.hide() ).remove();
+
+ slide.$placeholder = null;
+ }
+
+ // Remove custom close button
+ if ( slide.$smallBtn ) {
+ slide.$smallBtn.remove();
+
+ slide.$smallBtn = null;
+ }
+
+ // Remove content and mark slide as not loaded
+ if ( !slide.hasError ) {
+ $(this).empty();
+
+ slide.isLoaded = false;
+ }
+
+ });
+
+ slide.$content = $( content ).appendTo( slide.$slide );
+
+ if ( slide.opts.smallBtn && !slide.$smallBtn ) {
+ slide.$smallBtn = $( self.translate( slide, slide.opts.btnTpl.smallBtn ) ).appendTo( slide.$content );
+ }
+
+ this.afterLoad( slide );
+ },
+
+ // Display error message
+ // =====================
+
+ setError : function ( slide ) {
+
+ slide.hasError = true;
+
+ slide.$slide.removeClass( 'fancybox-slide--' + slide.type );
+
+ this.setContent( slide, this.translate( slide, slide.opts.errorTpl ) );
+
+ },
+
+
+ // Show loading icon inside the slide
+ // ==================================
+
+ showLoading : function( slide ) {
+
+ var self = this;
+
+ slide = slide || self.current;
+
+ if ( slide && !slide.$spinner ) {
+ slide.$spinner = $( self.opts.spinnerTpl ).appendTo( slide.$slide );
+ }
+
+ },
+
+ // Remove loading icon from the slide
+ // ==================================
+
+ hideLoading : function( slide ) {
+
+ var self = this;
+
+ slide = slide || self.current;
+
+ if ( slide && slide.$spinner ) {
+ slide.$spinner.remove();
+
+ delete slide.$spinner;
+ }
+
+ },
+
+
+ // Adjustments after slide content has been loaded
+ // ===============================================
+
+ afterLoad : function( slide ) {
+
+ var self = this;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ slide.isLoading = false;
+ slide.isLoaded = true;
+
+ self.trigger( 'afterLoad', slide );
+
+ self.hideLoading( slide );
+
+ if ( slide.opts.protect && slide.$content && !slide.hasError ) {
+
+ // Disable right click
+ slide.$content.on( 'contextmenu.fb', function( e ) {
+ if ( e.button == 2 ) {
+ e.preventDefault();
+ }
+
+ return true;
+ });
+
+ // Add fake element on top of the image
+ // This makes a bit harder for user to select image
+ if ( slide.type === 'image' ) {
+ $( '<div class="fancybox-spaceball"></div>' ).appendTo( slide.$content );
+ }
+
+ }
+
+ self.revealContent( slide );
+
+ },
+
+
+ // Make content visible
+ // This method is called right after content has been loaded or
+ // user navigates gallery and transition should start
+ // ============================================================
+
+ revealContent : function( slide ) {
+
+ var self = this;
+ var $slide = slide.$slide;
+
+ var effect, effectClassName, duration, opacity, end, start = false;
+
+ effect = slide.opts[ self.firstRun ? 'animationEffect' : 'transitionEffect' ];
+ duration = slide.opts[ self.firstRun ? 'animationDuration' : 'transitionDuration' ];
+
+ duration = parseInt( slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10 );
+
+ if ( slide.isMoved || slide.pos !== self.currPos || !duration ) {
+ effect = false;
+ }
+
+ // Check if can zoom
+ if ( effect === 'zoom' && !( slide.pos === self.currPos && duration && slide.type === 'image' && !slide.hasError && ( start = self.getThumbPos( slide ) ) ) ) {
+ effect = 'fade';
+ }
+
+
+ // Zoom animation
+ // ==============
+
+ if ( effect === 'zoom' ) {
+ end = self.getFitPos( slide );
+
+ end.scaleX = end.width / start.width;
+ end.scaleY = end.height / start.height;
+
+ delete end.width;
+ delete end.height;
+
+ // Check if we need to animate opacity
+ opacity = slide.opts.zoomOpacity;
+
+ if ( opacity == 'auto' ) {
+ opacity = Math.abs( slide.width / slide.height - start.width / start.height ) > 0.1;
+ }
+
+ if ( opacity ) {
+ start.opacity = 0.1;
+ end.opacity = 1;
+ }
+
+ // Draw image at start position
+ $.fancybox.setTranslate( slide.$content.removeClass( 'fancybox-is-hidden' ), start );
+
+ forceRedraw( slide.$content );
+
+ // Start animation
+ $.fancybox.animate( slide.$content, end, duration, function() {
+ self.complete();
+ });
+
+ return;
+ }
+
+
+ self.updateSlide( slide );
+
+
+ // Simply show content
+ // ===================
+
+ if ( !effect ) {
+ forceRedraw( $slide );
+
+ slide.$content.removeClass( 'fancybox-is-hidden' );
+
+ if ( slide.pos === self.currPos ) {
+ self.complete();
+ }
+
+ return;
+ }
+
+ $.fancybox.stop( $slide );
+
+ effectClassName = 'fancybox-animated fancybox-slide--' + ( slide.pos > self.prevPos ? 'next' : 'previous' ) + ' fancybox-fx-' + effect;
+
+ $slide.removeAttr( 'style' ).removeClass( 'fancybox-slide--current fancybox-slide--next fancybox-slide--previous' ).addClass( effectClassName );
+
+ slide.$content.removeClass( 'fancybox-is-hidden' );
+
+ //Force reflow for CSS3 transitions
+ forceRedraw( $slide );
+
+ $.fancybox.animate( $slide, 'fancybox-slide--current', duration, function(e) {
+ $slide.removeClass( effectClassName ).removeAttr( 'style' );
+
+ if ( slide.pos === self.currPos ) {
+ self.complete();
+ }
+
+ }, true);
+
+ },
+
+
+ // Check if we can and have to zoom from thumbnail
+ //================================================
+
+ getThumbPos : function( slide ) {
+
+ var self = this;
+ var rez = false;
+
+ // Check if element is inside the viewport by at least 1 pixel
+ var isElementVisible = function( $el ) {
+ var element = $el[0];
+
+ var elementRect = element.getBoundingClientRect();
+ var parentRects = [];
+
+ var visibleInAllParents;
+
+ while ( element.parentElement !== null ) {
+ if ( $(element.parentElement).css('overflow') === 'hidden' || $(element.parentElement).css('overflow') === 'auto' ) {
+ parentRects.push(element.parentElement.getBoundingClientRect());
+ }
+
+ element = element.parentElement;
+ }
+
+ visibleInAllParents = parentRects.every(function(parentRect){
+ var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
+ var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
+
+ return visiblePixelX > 0 && visiblePixelY > 0;
+ });
+
+ return visibleInAllParents &&
+ elementRect.bottom > 0 && elementRect.right > 0 &&
+ elementRect.left < $(window).width() && elementRect.top < $(window).height();
+ };
+
+ var $thumb = slide.opts.$thumb;
+ var thumbPos = $thumb ? $thumb.offset() : 0;
+ var slidePos;
+
+ if ( thumbPos && $thumb[0].ownerDocument === document && isElementVisible( $thumb ) ) {
+ slidePos = self.$refs.stage.offset();
+
+ rez = {
+ top : thumbPos.top - slidePos.top + parseFloat( $thumb.css( "border-top-width" ) || 0 ),
+ left : thumbPos.left - slidePos.left + parseFloat( $thumb.css( "border-left-width" ) || 0 ),
+ width : $thumb.width(),
+ height : $thumb.height(),
+ scaleX : 1,
+ scaleY : 1
+ };
+ }
+
+ return rez;
+ },
+
+
+ // Final adjustments after current gallery item is moved to position
+ // and it`s content is loaded
+ // ==================================================================
+
+ complete : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var slides = {};
+
+ if ( current.isMoved || !current.isLoaded || current.isComplete ) {
+ return;
+ }
+
+ current.isComplete = true;
+
+ current.$slide.siblings().trigger( 'onReset' );
+
+ // Trigger any CSS3 transiton inside the slide
+ forceRedraw( current.$slide );
+
+ current.$slide.addClass( 'fancybox-slide--complete' );
+
+ // Remove unnecessary slides
+ $.each( self.slides, function( key, slide ) {
+ if ( slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1 ) {
+ slides[ slide.pos ] = slide;
+
+ } else if ( slide ) {
+
+ $.fancybox.stop( slide.$slide );
+
+ slide.$slide.unbind().remove();
+ }
+ });
+
+ self.slides = slides;
+
+ self.updateCursor();
+
+ self.trigger( 'afterShow' );
+
+ // Try to focus on the first focusable element
+ if ( $( document.activeElement ).is( '[disabled]' ) || ( current.opts.autoFocus && !( current.type == 'image' || current.type === 'iframe' ) ) ) {
+ self.focus();
+ }
+
+ },
+
+
+ // Preload next and previous slides
+ // ================================
+
+ preload : function() {
+ var self = this;
+ var next, prev;
+
+ if ( self.group.length < 2 ) {
+ return;
+ }
+
+ next = self.slides[ self.currPos + 1 ];
+ prev = self.slides[ self.currPos - 1 ];
+
+ if ( next && next.type === 'image' ) {
+ self.loadSlide( next );
+ }
+
+ if ( prev && prev.type === 'image' ) {
+ self.loadSlide( prev );
+ }
+
+ },
+
+
+ // Try to find and focus on the first focusable element
+ // ====================================================
+
+ focus : function() {
+ var current = this.current;
+ var $el;
+
+ if ( this.isClosing ) {
+ return;
+ }
+
+ // Skip for images and iframes
+ $el = current && current.isComplete ? current.$slide.find('button,:input,[tabindex],a').filter(':not([disabled]):visible:first') : null;
+ $el = $el && $el.length ? $el : this.$refs.container;
+
+ $el.focus();
+ },
+
+
+ // Activates current instance - brings container to the front and enables keyboard,
+ // notifies other instances about deactivating
+ // =================================================================================
+
+ activate : function () {
+ var self = this;
+
+ // Deactivate all instances
+ $( '.fancybox-container' ).each(function () {
+ var instance = $(this).data( 'FancyBox' );
+
+ // Skip self and closing instances
+ if (instance && instance.uid !== self.uid && !instance.isClosing) {
+ instance.trigger( 'onDeactivate' );
+ }
+
+ });
+
+ if ( self.current ) {
+ if ( self.$refs.container.index() > 0 ) {
+ self.$refs.container.prependTo( document.body );
+ }
+
+ self.updateControls();
+ }
+
+ self.trigger( 'onActivate' );
+
+ self.addEvents();
+
+ },
+
+
+ // Start closing procedure
+ // This will start "zoom-out" animation if needed and clean everything up afterwards
+ // =================================================================================
+
+ close : function( e, d ) {
+
+ var self = this;
+ var current = self.current;
+
+ var effect, duration;
+ var $what, opacity, start, end;
+
+ var done = function() {
+ self.cleanUp( e );
+ };
+
+ if ( self.isClosing ) {
+ return false;
+ }
+
+ self.isClosing = true;
+
+ // If beforeClose callback prevents closing, make sure content is centered
+ if ( self.trigger( 'beforeClose', e ) === false ) {
+ self.isClosing = false;
+
+ requestAFrame(function() {
+ self.update();
+ });
+
+ return false;
+ }
+
+ // Remove all events
+ // If there are multiple instances, they will be set again by "activate" method
+ self.removeEvents();
+
+ if ( current.timouts ) {
+ clearTimeout( current.timouts );
+ }
+
+ $what = current.$content;
+ effect = current.opts.animationEffect;
+ duration = $.isNumeric( d ) ? d : ( effect ? current.opts.animationDuration : 0 );
+
+ // Remove other slides
+ current.$slide.off( transitionEnd ).removeClass( 'fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated' );
+
+ current.$slide.siblings().trigger( 'onReset' ).remove();
+
+ // Trigger animations
+ if ( duration ) {
+ self.$refs.container.removeClass( 'fancybox-is-open' ).addClass( 'fancybox-is-closing' );
+ }
+
+ // Clean up
+ self.hideLoading( current );
+
+ self.hideControls();
+
+ self.updateCursor();
+
+ // Check if possible to zoom-out
+ if ( effect === 'zoom' && !( e !== true && $what && duration && current.type === 'image' && !current.hasError && ( end = self.getThumbPos( current ) ) ) ) {
+ effect = 'fade';
+ }
+
+ if ( effect === 'zoom' ) {
+ $.fancybox.stop( $what );
+
+ start = $.fancybox.getTranslate( $what );
+
+ start.width = start.width * start.scaleX;
+ start.height = start.height * start.scaleY;
+
+ // Check if we need to animate opacity
+ opacity = current.opts.zoomOpacity;
+
+ if ( opacity == 'auto' ) {
+ opacity = Math.abs( current.width / current.height - end.width / end.height ) > 0.1;
+ }
+
+ if ( opacity ) {
+ end.opacity = 0;
+ }
+
+ start.scaleX = start.width / end.width;
+ start.scaleY = start.height / end.height;
+
+ start.width = end.width;
+ start.height = end.height;
+
+ $.fancybox.setTranslate( current.$content, start );
+
+ $.fancybox.animate( current.$content, end, duration, done );
+
+ return true;
+ }
+
+ if ( effect && duration ) {
+
+ // If skip animation
+ if ( e === true ) {
+ setTimeout( done, duration );
+
+ } else {
+ $.fancybox.animate( current.$slide.removeClass( 'fancybox-slide--current' ), 'fancybox-animated fancybox-slide--previous fancybox-fx-' + effect, duration, done );
+ }
+
+ } else {
+ done();
+ }
+
+ return true;
+ },
+
+
+ // Final adjustments after removing the instance
+ // =============================================
+
+ cleanUp : function( e ) {
+ var self = this,
+ instance;
+
+ self.current.$slide.trigger( 'onReset' );
+
+ self.$refs.container.empty().remove();
+
+ self.trigger( 'afterClose', e );
+
+ // Place back focus
+ if ( self.$lastFocus && !!self.current.opts.backFocus ) {
+ self.$lastFocus.focus();
+ }
+
+ self.current = null;
+
+ // Check if there are other instances
+ instance = $.fancybox.getInstance();
+
+ if ( instance ) {
+ instance.activate();
+
+ } else {
+
+ $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
+
+ $( 'html' ).removeClass( 'fancybox-enabled' );
+
+ $( '#fancybox-style-noscroll' ).remove();
+ }
+
+ },
+
+
+ // Call callback and trigger an event
+ // ==================================
+
+ trigger : function( name, slide ) {
+ var args = Array.prototype.slice.call(arguments, 1),
+ self = this,
+ obj = slide && slide.opts ? slide : self.current,
+ rez;
+
+ if ( obj ) {
+ args.unshift( obj );
+
+ } else {
+ obj = self;
+ }
+
+ args.unshift( self );
+
+ if ( $.isFunction( obj.opts[ name ] ) ) {
+ rez = obj.opts[ name ].apply( obj, args );
+ }
+
+ if ( rez === false ) {
+ return rez;
+ }
+
+ if ( name === 'afterClose' ) {
+ $D.trigger( name + '.fb', args );
+
+ } else {
+ self.$refs.container.trigger( name + '.fb', args );
+ }
+
+ },
+
+
+ // Update infobar values, navigation button states and reveal caption
+ // ==================================================================
+
+ updateControls : function ( force ) {
+
+ var self = this;
+
+ var current = self.current;
+ var index = current.index;
+ var opts = current.opts;
+ var caption = opts.caption;
+ var $caption = self.$refs.caption;
+
+ // Recalculate content dimensions
+ current.$slide.trigger( 'refresh' );
+
+ self.$caption = caption && caption.length ? $caption.html( caption ) : null;
+
+ if ( !self.isHiddenControls ) {
+ self.showControls();
+ }
+
+ // Update info and navigation elements
+ $('[data-fancybox-count]').html( self.group.length );
+ $('[data-fancybox-index]').html( index + 1 );
+
+ $('[data-fancybox-prev]').prop('disabled', ( !opts.loop && index <= 0 ) );
+ $('[data-fancybox-next]').prop('disabled', ( !opts.loop && index >= self.group.length - 1 ) );
+
+ },
+
+ // Hide toolbar and caption
+ // ========================
+
+ hideControls : function () {
+
+ this.isHiddenControls = true;
+
+ this.$refs.container.removeClass('fancybox-show-infobar fancybox-show-toolbar fancybox-show-caption fancybox-show-nav');
+
+ },
+
+ showControls : function() {
+
+ var self = this;
+ var opts = self.current ? self.current.opts : self.opts;
+ var $container = self.$refs.container;
+
+ self.isHiddenControls = false;
+ self.idleSecondsCounter = 0;
+
+ $container
+ .toggleClass('fancybox-show-toolbar', !!( opts.toolbar && opts.buttons ) )
+ .toggleClass('fancybox-show-infobar', !!( opts.infobar && self.group.length > 1 ) )
+ .toggleClass('fancybox-show-nav', !!( opts.arrows && self.group.length > 1 ) )
+ .toggleClass('fancybox-is-modal', !!opts.modal );
+
+ if ( self.$caption ) {
+ $container.addClass( 'fancybox-show-caption ');
+
+ } else {
+ $container.removeClass( 'fancybox-show-caption' );
+ }
+
+ },
+
+
+ // Toggle toolbar and caption
+ // ==========================
+
+ toggleControls : function() {
+
+ if ( this.isHiddenControls ) {
+ this.showControls();
+
+ } else {
+ this.hideControls();
+ }
+
+ },
+
+
+ });
+
+
+ $.fancybox = {
+
+ version : "3.1.24",
+ defaults : defaults,
+
+
+ // Get current instance and execute a command.
+ //
+ // Examples of usage:
+ //
+ // $instance = $.fancybox.getInstance();
+ // $.fancybox.getInstance().jumpTo( 1 );
+ // $.fancybox.getInstance( 'jumpTo', 1 );
+ // $.fancybox.getInstance( function() {
+ // console.info( this.currIndex );
+ // });
+ // ======================================================
+
+ getInstance : function ( command ) {
+ var instance = $('.fancybox-container:not(".fancybox-is-closing"):first').data( 'FancyBox' );
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ if ( instance instanceof FancyBox ) {
+
+ if ( $.type( command ) === 'string' ) {
+ instance[ command ].apply( instance, args );
+
+ } else if ( $.type( command ) === 'function' ) {
+ command.apply( instance, args );
+
+ }
+
+ return instance;
+ }
+
+ return false;
+
+ },
+
+
+ // Create new instance
+ // ===================
+
+ open : function ( items, opts, index ) {
+ return new FancyBox( items, opts, index );
+ },
+
+
+ // Close current or all instances
+ // ==============================
+
+ close : function ( all ) {
+ var instance = this.getInstance();
+
+ if ( instance ) {
+ instance.close();
+
+ // Try to find and close next instance
+
+ if ( all === true ) {
+ this.close();
+ }
+ }
+
+ },
+
+ // Close instances and unbind all events
+ // ==============================
+
+ destroy : function() {
+
+ this.close( true );
+
+ $D.off( 'click.fb-start' );
+
+ },
+
+
+ // Try to detect mobile devices
+ // ============================
+
+ isMobile : document.createTouch !== undefined && /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent),
+
+
+ // Detect if 'translate3d' support is available
+ // ============================================
+
+ use3d : (function() {
+ var div = document.createElement('div');
+
+ return window.getComputedStyle && window.getComputedStyle( div ).getPropertyValue('transform') && !(document.documentMode && document.documentMode < 11);
+ }()),
+
+
+ // Helper function to get current visual state of an element
+ // returns array[ top, left, horizontal-scale, vertical-scale, opacity ]
+ // =====================================================================
+
+ getTranslate : function( $el ) {
+ var matrix;
+
+ if ( !$el || !$el.length ) {
+ return false;
+ }
+
+ matrix = $el.eq( 0 ).css('transform');
+
+ if ( matrix && matrix.indexOf( 'matrix' ) !== -1 ) {
+ matrix = matrix.split('(')[1];
+ matrix = matrix.split(')')[0];
+ matrix = matrix.split(',');
+ } else {
+ matrix = [];
+ }
+
+ if ( matrix.length ) {
+
+ // If IE
+ if ( matrix.length > 10 ) {
+ matrix = [ matrix[13], matrix[12], matrix[0], matrix[5] ];
+
+ } else {
+ matrix = [ matrix[5], matrix[4], matrix[0], matrix[3]];
+ }
+
+ matrix = matrix.map(parseFloat);
+
+ } else {
+ matrix = [ 0, 0, 1, 1 ];
+
+ var transRegex = /\.*translate\((.*)px,(.*)px\)/i;
+ var transRez = transRegex.exec( $el.eq( 0 ).attr('style') );
+
+ if ( transRez ) {
+ matrix[ 0 ] = parseFloat( transRez[2] );
+ matrix[ 1 ] = parseFloat( transRez[1] );
+ }
+ }
+
+ return {
+ top : matrix[ 0 ],
+ left : matrix[ 1 ],
+ scaleX : matrix[ 2 ],
+ scaleY : matrix[ 3 ],
+ opacity : parseFloat( $el.css('opacity') ),
+ width : $el.width(),
+ height : $el.height()
+ };
+
+ },
+
+
+ // Shortcut for setting "translate3d" properties for element
+ // Can set be used to set opacity, too
+ // ========================================================
+
+ setTranslate : function( $el, props ) {
+ var str = '';
+ var css = {};
+
+ if ( !$el || !props ) {
+ return;
+ }
+
+ if ( props.left !== undefined || props.top !== undefined ) {
+ str = ( props.left === undefined ? $el.position().left : props.left ) + 'px, ' + ( props.top === undefined ? $el.position().top : props.top ) + 'px';
+
+ if ( this.use3d ) {
+ str = 'translate3d(' + str + ', 0px)';
+
+ } else {
+ str = 'translate(' + str + ')';
+ }
+ }
+
+ if ( props.scaleX !== undefined && props.scaleY !== undefined ) {
+ str = (str.length ? str + ' ' : '') + 'scale(' + props.scaleX + ', ' + props.scaleY + ')';
+ }
+
+ if ( str.length ) {
+ css.transform = str;
+ }
+
+ if ( props.opacity !== undefined ) {
+ css.opacity = props.opacity;
+ }
+
+ if ( props.width !== undefined ) {
+ css.width = props.width;
+ }
+
+ if ( props.height !== undefined ) {
+ css.height = props.height;
+ }
+
+ return $el.css( css );
+ },
+
+
+ // Simple CSS transition handler
+ // =============================
+
+ animate : function ( $el, to, duration, callback, leaveAnimationName ) {
+ var event = transitionEnd || 'transitionend';
+
+ if ( $.isFunction( duration ) ) {
+ callback = duration;
+ duration = null;
+ }
+
+ if ( !$.isPlainObject( to ) ) {
+ $el.removeAttr('style');
+ }
+
+ $el.on( event, function(e) {
+
+ // Skip events from child elements and z-index change
+ if ( e && e.originalEvent && ( !$el.is( e.originalEvent.target ) || e.originalEvent.propertyName == 'z-index' ) ) {
+ return;
+ }
+
+ $el.off( event );
+
+ if ( $.isPlainObject( to ) ) {
+
+ if ( to.scaleX !== undefined && to.scaleY !== undefined ) {
+ $el.css( 'transition-duration', '0ms' );
+
+ to.width = Math.round( $el.width() * to.scaleX );
+ to.height = Math.round( $el.height() * to.scaleY );
+
+ to.scaleX = 1;
+ to.scaleY = 1;
+
+ $.fancybox.setTranslate( $el, to );
+ }
+
+ } else if ( leaveAnimationName !== true ) {
+ $el.removeClass( to );
+ }
+
+ if ( $.isFunction( callback ) ) {
+ callback( e );
+ }
+
+ });
+
+ if ( $.isNumeric( duration ) ) {
+ $el.css( 'transition-duration', duration + 'ms' );
+ }
+
+ if ( $.isPlainObject( to ) ) {
+ $.fancybox.setTranslate( $el, to );
+
+ } else {
+ $el.addClass( to );
+ }
+
+ $el.data("timer", setTimeout(function() {
+ $el.trigger( 'transitionend' );
+ }, duration + 16));
+
+ },
+
+ stop : function( $el ) {
+ clearTimeout( $el.data("timer") );
+
+ $el.off( transitionEnd );
+ }
+
+ };
+
+
+ // Default click handler for "fancyboxed" links
+ // ============================================
+
+ function _run( e ) {
+ var target = e.currentTarget,
+ opts = e.data ? e.data.options : {},
+ items = opts.selector ? $( opts.selector ) : ( e.data ? e.data.items : [] ),
+ value = $(target).attr( 'data-fancybox' ) || '',
+ index = 0,
+ active = $.fancybox.getInstance();
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ // Avoid opening multiple times
+ if ( active && active.current.opts.$orig.is( target ) ) {
+ return;
+ }
+
+ // Get all related items and find index for clicked one
+ if ( value ) {
+ items = items.length ? items.filter( '[data-fancybox="' + value + '"]' ) : $( '[data-fancybox="' + value + '"]' );
+ index = items.index( target );
+
+ // Sometimes current item can not be found
+ // (for example, when slider clones items)
+ if ( index < 0 ) {
+ index = 0;
+ }
+
+ } else {
+ items = [ target ];
+ }
+
+ $.fancybox.open( items, opts, index );
+ }
+
+
+ // Create a jQuery plugin
+ // ======================
+
+ $.fn.fancybox = function (options) {
+ var selector;
+
+ options = options || {};
+ selector = options.selector || false;
+
+ if ( selector ) {
+
+ $( 'body' ).off( 'click.fb-start', selector ).on( 'click.fb-start', selector, {
+ options : options
+ }, _run );
+
+ } else {
+
+ this.off( 'click.fb-start' ).on( 'click.fb-start', {
+ items : this,
+ options : options
+ }, _run);
+
+ }
+
+ return this;
+ };
+
+
+ // Self initializing plugin
+ // ========================
+
+ $D.on( 'click.fb-start', '[data-fancybox]', _run );
+
+}( window, document, window.jQuery ));
+
+// ==========================================================================
+//
+// Media
+// Adds additional media type support
+//
+// ==========================================================================
+;(function ($) {
+
+ 'use strict';
+
+ // Formats matching url to final form
+
+ var format = function (url, rez, params) {
+ if ( !url ) {
+ return;
+ }
+
+ params = params || '';
+
+ if ( $.type(params) === "object" ) {
+ params = $.param(params, true);
+ }
+
+ $.each(rez, function (key, value) {
+ url = url.replace('$' + key, value || '');
+ });
+
+ if (params.length) {
+ url += (url.indexOf('?') > 0 ? '&' : '?') + params;
+ }
+
+ return url;
+ };
+
+ // Object containing properties for each media type
+
+ var defaults = {
+ youtube : {
+ matcher : /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
+ params : {
+ autoplay : 1,
+ autohide : 1,
+ fs : 1,
+ rel : 0,
+ hd : 1,
+ wmode : 'transparent',
+ enablejsapi : 1,
+ html5 : 1
+ },
+ paramPlace : 8,
+ type : 'iframe',
+ url : '//www.youtube.com/embed/$4',
+ thumb : '//img.youtube.com/vi/$4/hqdefault.jpg'
+ },
+
+ vimeo : {
+ matcher : /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,
+ params : {
+ autoplay : 1,
+ hd : 1,
+ show_title : 1,
+ show_byline : 1,
+ show_portrait : 0,
+ fullscreen : 1,
+ api : 1
+ },
+ paramPlace : 3,
+ type : 'iframe',
+ url : '//player.vimeo.com/video/$2'
+ },
+
+ metacafe : {
+ matcher : /metacafe.com\/watch\/(\d+)\/(.*)?/,
+ type : 'iframe',
+ url : '//www.metacafe.com/embed/$1/?ap=1'
+ },
+
+ dailymotion : {
+ matcher : /dailymotion.com\/video\/(.*)\/?(.*)/,
+ params : {
+ additionalInfos : 0,
+ autoStart : 1
+ },
+ type : 'iframe',
+ url : '//www.dailymotion.com/embed/video/$1'
+ },
+
+ vine : {
+ matcher : /vine.co\/v\/([a-zA-Z0-9\?\=\-]+)/,
+ type : 'iframe',
+ url : '//vine.co/v/$1/embed/simple'
+ },
+
+ instagram : {
+ matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
+ type : 'image',
+ url : '//$1/p/$2/media/?size=l'
+ },
+
+ // Examples:
+ // http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
+ // https://www.google.com/maps/@37.7852006,-122.4146355,14.65z
+ // https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572
+ gmap_place : {
+ matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,
+ type : 'iframe',
+ url : function (rez) {
+ return '//maps.google.' + rez[2] + '/?ll=' + ( rez[9] ? rez[9] + '&z=' + Math.floor( rez[10] ) + ( rez[12] ? rez[12].replace(/^\//, "&") : '' ) : rez[12] ) + '&output=' + ( rez[12] && rez[12].indexOf('layer=c') > 0 ? 'svembed' : 'embed' );
+ }
+ },
+
+ // Examples:
+ // https://www.google.com/maps/search/Empire+State+Building/
+ // https://www.google.com/maps/search/?api=1&query=centurylink+field
+ // https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393
+ gmap_search : {
+ matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,
+ type : 'iframe',
+ url : function (rez) {
+ return '//maps.google.' + rez[2] + '/maps?q=' + rez[5].replace('query=', 'q=').replace('api=1', '') + '&output=embed';
+ }
+ }
+ };
+
+ $(document).on('onInit.fb', function (e, instance) {
+
+ $.each(instance.group, function( i, item ) {
+
+ var url = item.src || '',
+ type = false,
+ media,
+ thumb,
+ rez,
+ params,
+ urlParams,
+ o,
+ provider;
+
+ // Skip items that already have content type
+ if ( item.type ) {
+ return;
+ }
+
+ media = $.extend( true, {}, defaults, item.opts.media );
+
+ // Look for any matching media type
+ $.each(media, function ( n, el ) {
+ rez = url.match(el.matcher);
+ o = {};
+ provider = n;
+
+ if (!rez) {
+ return;
+ }
+
+ type = el.type;
+
+ if ( el.paramPlace && rez[ el.paramPlace ] ) {
+ urlParams = rez[ el.paramPlace ];
+
+ if ( urlParams[ 0 ] == '?' ) {
+ urlParams = urlParams.substring(1);
+ }
+
+ urlParams = urlParams.split('&');
+
+ for ( var m = 0; m < urlParams.length; ++m ) {
+ var p = urlParams[ m ].split('=', 2);
+
+ if ( p.length == 2 ) {
+ o[ p[0] ] = decodeURIComponent( p[1].replace(/\+/g, " ") );
+ }
+ }
+ }
+
+ params = $.extend( true, {}, el.params, item.opts[ n ], o );
+
+ url = $.type(el.url) === "function" ? el.url.call(this, rez, params, item) : format(el.url, rez, params);
+ thumb = $.type(el.thumb) === "function" ? el.thumb.call(this, rez, params, item) : format(el.thumb, rez);
+
+ if ( provider === 'vimeo' ) {
+ url = url.replace('&%23', '#');
+ }
+
+ return false;
+ });
+
+ // If it is found, then change content type and update the url
+
+ if ( type ) {
+ item.src = url;
+ item.type = type;
+
+ if ( !item.opts.thumb && !( item.opts.$thumb && item.opts.$thumb.length ) ) {
+ item.opts.thumb = thumb;
+ }
+
+ if ( type === 'iframe' ) {
+ $.extend(true, item.opts, {
+ iframe : {
+ preload : false,
+ attr : {
+ scrolling : "no"
+ }
+ }
+ });
+
+ item.contentProvider = provider;
+
+ item.opts.slideClass += ' fancybox-slide--' + ( provider == 'gmap_place' || provider == 'gmap_search' ? 'map' : 'video' );
+ }
+
+ } else {
+
+ // If no content type is found, then set it to `image` as fallback
+ item.type = 'image';
+ }
+
+ });
+
+ });
+
+}(window.jQuery));
+
+// ==========================================================================
+//
+// Guestures
+// Adds touch guestures, handles click and tap events
+//
+// ==========================================================================
+;(function (window, document, $) {
+ 'use strict';
+
+ var requestAFrame = (function () {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ // if all else fails, use setTimeout
+ function (callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })();
+
+
+ var cancelAFrame = (function () {
+ return window.cancelAnimationFrame ||
+ window.webkitCancelAnimationFrame ||
+ window.mozCancelAnimationFrame ||
+ window.oCancelAnimationFrame ||
+ function (id) {
+ window.clearTimeout(id);
+ };
+ })();
+
+
+ var pointers = function( e ) {
+ var result = [];
+
+ e = e.originalEvent || e || window.e;
+ e = e.touches && e.touches.length ? e.touches : ( e.changedTouches && e.changedTouches.length ? e.changedTouches : [ e ] );
+
+ for ( var key in e ) {
+
+ if ( e[ key ].pageX ) {
+ result.push( { x : e[ key ].pageX, y : e[ key ].pageY } );
+
+ } else if ( e[ key ].clientX ) {
+ result.push( { x : e[ key ].clientX, y : e[ key ].clientY } );
+ }
+ }
+
+ return result;
+ };
+
+ var distance = function( point2, point1, what ) {
+ if ( !point1 || !point2 ) {
+ return 0;
+ }
+
+ if ( what === 'x' ) {
+ return point2.x - point1.x;
+
+ } else if ( what === 'y' ) {
+ return point2.y - point1.y;
+ }
+
+ return Math.sqrt( Math.pow( point2.x - point1.x, 2 ) + Math.pow( point2.y - point1.y, 2 ) );
+ };
+
+ var isClickable = function( $el ) {
+ if ( $el.is('a,button,input,select,textarea') || $.isFunction( $el.get(0).onclick ) ) {
+ return true;
+ }
+
+ // Check for attributes like data-fancybox-next or data-fancybox-close
+ for ( var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++ ) {
+ if ( atts[i].nodeName.substr(0, 14) === 'data-fancybox-' ) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ var hasScrollbars = function( el ) {
+ var overflowY = window.getComputedStyle( el )['overflow-y'];
+ var overflowX = window.getComputedStyle( el )['overflow-x'];
+
+ var vertical = (overflowY === 'scroll' || overflowY === 'auto') && el.scrollHeight > el.clientHeight;
+ var horizontal = (overflowX === 'scroll' || overflowX === 'auto') && el.scrollWidth > el.clientWidth;
+
+ return vertical || horizontal;
+ };
+
+ var isScrollable = function ( $el ) {
+ var rez = false;
+
+ while ( true ) {
+ rez = hasScrollbars( $el.get(0) );
+
+ if ( rez ) {
+ break;
+ }
+
+ $el = $el.parent();
+
+ if ( !$el.length || $el.hasClass( 'fancybox-stage' ) || $el.is( 'body' ) ) {
+ break;
+ }
+ }
+
+ return rez;
+ };
+
+
+ var Guestures = function ( instance ) {
+ var self = this;
+
+ self.instance = instance;
+
+ self.$bg = instance.$refs.bg;
+ self.$stage = instance.$refs.stage;
+ self.$container = instance.$refs.container;
+
+ self.destroy();
+
+ self.$container.on( 'touchstart.fb.touch mousedown.fb.touch', $.proxy(self, 'ontouchstart') );
+ };
+
+ Guestures.prototype.destroy = function() {
+ this.$container.off( '.fb.touch' );
+ };
+
+ Guestures.prototype.ontouchstart = function( e ) {
+ var self = this;
+
+ var $target = $( e.target );
+ var instance = self.instance;
+ var current = instance.current;
+ var $content = current.$content;
+
+ var isTouchDevice = ( e.type == 'touchstart' );
+
+ // Do not respond to both events
+ if ( isTouchDevice ) {
+ self.$container.off( 'mousedown.fb.touch' );
+ }
+
+ // Ignore clicks while zooming or closing
+ if ( !current || self.instance.isAnimating || self.instance.isClosing ) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ return;
+ }
+
+ // Ignore right click
+ if ( e.originalEvent && e.originalEvent.button == 2 ) {
+ return;
+ }
+
+ // Ignore taping on links, buttons, input elements
+ if ( !$target.length || isClickable( $target ) || isClickable( $target.parent() ) ) {
+ return;
+ }
+
+ // Ignore clicks on the scrollbar
+ if ( e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left ) {
+ return;
+ }
+
+ self.startPoints = pointers( e );
+
+ // Prevent zooming if already swiping
+ if ( !self.startPoints || ( self.startPoints.length > 1 && instance.isSliding ) ) {
+ return;
+ }
+
+ self.$target = $target;
+ self.$content = $content;
+ self.canTap = true;
+
+ $(document).off( '.fb.touch' );
+
+ $(document).on( isTouchDevice ? 'touchend.fb.touch touchcancel.fb.touch' : 'mouseup.fb.touch mouseleave.fb.touch', $.proxy(self, "ontouchend"));
+ $(document).on( isTouchDevice ? 'touchmove.fb.touch' : 'mousemove.fb.touch', $.proxy(self, "ontouchmove"));
+
+ e.stopPropagation();
+
+ if ( !(instance.current.opts.touch || instance.canPan() ) || !( $target.is( self.$stage ) || self.$stage.find( $target ).length ) ) {
+
+ // Prevent ghosting
+ if ( $target.is('img') ) {
+ e.preventDefault();
+ }
+
+ return;
+ }
+
+ if ( !( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) ) {
+ e.preventDefault();
+ }
+
+ self.canvasWidth = Math.round( current.$slide[0].clientWidth );
+ self.canvasHeight = Math.round( current.$slide[0].clientHeight );
+
+ self.startTime = new Date().getTime();
+ self.distanceX = self.distanceY = self.distance = 0;
+
+ self.isPanning = false;
+ self.isSwiping = false;
+ self.isZooming = false;
+
+ self.sliderStartPos = self.sliderLastPos || { top: 0, left: 0 };
+ self.contentStartPos = $.fancybox.getTranslate( self.$content );
+ self.contentLastPos = null;
+
+ if ( self.startPoints.length === 1 && !self.isZooming ) {
+ self.canTap = !instance.isSliding;
+
+ if ( current.type === 'image' && ( self.contentStartPos.width > self.canvasWidth + 1 || self.contentStartPos.height > self.canvasHeight + 1 ) ) {
+
+ $.fancybox.stop( self.$content );
+
+ self.$content.css( 'transition-duration', '0ms' );
+
+ self.isPanning = true;
+
+ } else {
+
+ self.isSwiping = true;
+ }
+
+ self.$container.addClass('fancybox-controls--isGrabbing');
+ }
+
+ if ( self.startPoints.length === 2 && !instance.isAnimating && !current.hasError && current.type === 'image' && ( current.isLoaded || current.$ghost ) ) {
+ self.isZooming = true;
+
+ self.isSwiping = false;
+ self.isPanning = false;
+
+ $.fancybox.stop( self.$content );
+
+ self.$content.css( 'transition-duration', '0ms' );
+
+ self.centerPointStartX = ( ( self.startPoints[0].x + self.startPoints[1].x ) * 0.5 ) - $(window).scrollLeft();
+ self.centerPointStartY = ( ( self.startPoints[0].y + self.startPoints[1].y ) * 0.5 ) - $(window).scrollTop();
+
+ self.percentageOfImageAtPinchPointX = ( self.centerPointStartX - self.contentStartPos.left ) / self.contentStartPos.width;
+ self.percentageOfImageAtPinchPointY = ( self.centerPointStartY - self.contentStartPos.top ) / self.contentStartPos.height;
+
+ self.startDistanceBetweenFingers = distance( self.startPoints[0], self.startPoints[1] );
+ }
+
+ };
+
+ Guestures.prototype.ontouchmove = function( e ) {
+
+ var self = this;
+
+ self.newPoints = pointers( e );
+
+ if ( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) {
+ e.stopPropagation();
+
+ self.canTap = false;
+
+ return;
+ }
+
+ if ( !( self.instance.current.opts.touch || self.instance.canPan() ) || !self.newPoints || !self.newPoints.length ) {
+ return;
+ }
+
+ self.distanceX = distance( self.newPoints[0], self.startPoints[0], 'x' );
+ self.distanceY = distance( self.newPoints[0], self.startPoints[0], 'y' );
+
+ self.distance = distance( self.newPoints[0], self.startPoints[0] );
+
+ // Skip false ontouchmove events (Chrome)
+ if ( self.distance > 0 ) {
+
+ if ( !( self.$target.is( self.$stage ) || self.$stage.find( self.$target ).length ) ) {
+ return;
+ }
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ if ( self.isSwiping ) {
+ self.onSwipe();
+
+ } else if ( self.isPanning ) {
+ self.onPan();
+
+ } else if ( self.isZooming ) {
+ self.onZoom();
+ }
+
+ }
+
+ };
+
+ Guestures.prototype.onSwipe = function() {
+
+ var self = this;
+
+ var swiping = self.isSwiping;
+ var left = self.sliderStartPos.left || 0;
+ var angle;
+
+ if ( swiping === true ) {
+
+ if ( Math.abs( self.distance ) > 10 ) {
+
+ self.canTap = false;
+
+ if ( self.instance.group.length < 2 && self.instance.opts.touch.vertical ) {
+ self.isSwiping = 'y';
+
+ } else if ( self.instance.isSliding || self.instance.opts.touch.vertical === false || ( self.instance.opts.touch.vertical === 'auto' && $( window ).width() > 800 ) ) {
+ self.isSwiping = 'x';
+
+ } else {
+ angle = Math.abs( Math.atan2( self.distanceY, self.distanceX ) * 180 / Math.PI );
+
+ self.isSwiping = ( angle > 45 && angle < 135 ) ? 'y' : 'x';
+ }
+
+ self.instance.isSliding = self.isSwiping;
+
+ // Reset points to avoid jumping, because we dropped first swipes to calculate the angle
+ self.startPoints = self.newPoints;
+
+ $.each(self.instance.slides, function( index, slide ) {
+ $.fancybox.stop( slide.$slide );
+
+ slide.$slide.css( 'transition-duration', '0ms' );
+
+ slide.inTransition = false;
+
+ if ( slide.pos === self.instance.current.pos ) {
+ self.sliderStartPos.left = $.fancybox.getTranslate( slide.$slide ).left;
+ }
+ });
+
+ //self.instance.current.isMoved = true;
+
+ // Stop slideshow
+ if ( self.instance.SlideShow && self.instance.SlideShow.isActive ) {
+ self.instance.SlideShow.stop();
+ }
+ }
+
+ } else {
+
+ if ( swiping == 'x' ) {
+
+ // Sticky edges
+ if ( self.distanceX > 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === 0 && !self.instance.current.opts.loop ) ) ) {
+ left = left + Math.pow( self.distanceX, 0.8 );
+
+ } else if ( self.distanceX < 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop ) ) ) {
+ left = left - Math.pow( -self.distanceX, 0.8 );
+
+ } else {
+ left = left + self.distanceX;
+ }
+
+ }
+
+ self.sliderLastPos = {
+ top : swiping == 'x' ? 0 : self.sliderStartPos.top + self.distanceY,
+ left : left
+ };
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+
+ if ( self.sliderLastPos ) {
+ $.each(self.instance.slides, function( index, slide ) {
+ var pos = slide.pos - self.instance.currPos;
+
+ $.fancybox.setTranslate( slide.$slide, {
+ top : self.sliderLastPos.top,
+ left : self.sliderLastPos.left + ( pos * self.canvasWidth ) + ( pos * slide.opts.gutter )
+ });
+ });
+
+ self.$container.addClass( 'fancybox-is-sliding' );
+ }
+
+ });
+
+ }
+
+ };
+
+ Guestures.prototype.onPan = function() {
+
+ var self = this;
+
+ var newOffsetX, newOffsetY, newPos;
+
+ self.canTap = false;
+
+ if ( self.contentStartPos.width > self.canvasWidth ) {
+ newOffsetX = self.contentStartPos.left + self.distanceX;
+
+ } else {
+ newOffsetX = self.contentStartPos.left;
+ }
+
+ newOffsetY = self.contentStartPos.top + self.distanceY;
+
+ newPos = self.limitMovement( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
+
+ newPos.scaleX = self.contentStartPos.scaleX;
+ newPos.scaleY = self.contentStartPos.scaleY;
+
+ self.contentLastPos = newPos;
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+ $.fancybox.setTranslate( self.$content, self.contentLastPos );
+ });
+ };
+
+ // Make panning sticky to the edges
+ Guestures.prototype.limitMovement = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
+
+ var self = this;
+
+ var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY;
+
+ var canvasWidth = self.canvasWidth;
+ var canvasHeight = self.canvasHeight;
+
+ var currentOffsetX = self.contentStartPos.left;
+ var currentOffsetY = self.contentStartPos.top;
+
+ var distanceX = self.distanceX;
+ var distanceY = self.distanceY;
+
+ // Slow down proportionally to traveled distance
+
+ minTranslateX = Math.max(0, canvasWidth * 0.5 - newWidth * 0.5 );
+ minTranslateY = Math.max(0, canvasHeight * 0.5 - newHeight * 0.5 );
+
+ maxTranslateX = Math.min( canvasWidth - newWidth, canvasWidth * 0.5 - newWidth * 0.5 );
+ maxTranslateY = Math.min( canvasHeight - newHeight, canvasHeight * 0.5 - newHeight * 0.5 );
+
+ if ( newWidth > canvasWidth ) {
+
+ // ->
+ if ( distanceX > 0 && newOffsetX > minTranslateX ) {
+ newOffsetX = minTranslateX - 1 + Math.pow( -minTranslateX + currentOffsetX + distanceX, 0.8 ) || 0;
+ }
+
+ // <-
+ if ( distanceX < 0 && newOffsetX < maxTranslateX ) {
+ newOffsetX = maxTranslateX + 1 - Math.pow( maxTranslateX - currentOffsetX - distanceX, 0.8 ) || 0;
+ }
+
+ }
+
+ if ( newHeight > canvasHeight ) {
+
+ // \/
+ if ( distanceY > 0 && newOffsetY > minTranslateY ) {
+ newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8 ) || 0;
+ }
+
+ // /\
+ if ( distanceY < 0 && newOffsetY < maxTranslateY ) {
+ newOffsetY = maxTranslateY + 1 - Math.pow ( maxTranslateY - currentOffsetY - distanceY, 0.8 ) || 0;
+ }
+
+ }
+
+ return {
+ top : newOffsetY,
+ left : newOffsetX
+ };
+
+ };
+
+
+ Guestures.prototype.limitPosition = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
+
+ var self = this;
+
+ var canvasWidth = self.canvasWidth;
+ var canvasHeight = self.canvasHeight;
+
+ if ( newWidth > canvasWidth ) {
+ newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;
+ newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;
+
+ } else {
+
+ // Center horizontally
+ newOffsetX = Math.max( 0, canvasWidth / 2 - newWidth / 2 );
+
+ }
+
+ if ( newHeight > canvasHeight ) {
+ newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;
+ newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;
+
+ } else {
+
+ // Center vertically
+ newOffsetY = Math.max( 0, canvasHeight / 2 - newHeight / 2 );
+
+ }
+
+ return {
+ top : newOffsetY,
+ left : newOffsetX
+ };
+
+ };
+
+ Guestures.prototype.onZoom = function() {
+
+ var self = this;
+
+ // Calculate current distance between points to get pinch ratio and new width and height
+
+ var currentWidth = self.contentStartPos.width;
+ var currentHeight = self.contentStartPos.height;
+
+ var currentOffsetX = self.contentStartPos.left;
+ var currentOffsetY = self.contentStartPos.top;
+
+ var endDistanceBetweenFingers = distance( self.newPoints[0], self.newPoints[1] );
+
+ var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;
+
+ var newWidth = Math.floor( currentWidth * pinchRatio );
+ var newHeight = Math.floor( currentHeight * pinchRatio );
+
+ // This is the translation due to pinch-zooming
+ var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX;
+ var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;
+
+ //Point between the two touches
+
+ var centerPointEndX = ((self.newPoints[0].x + self.newPoints[1].x) / 2) - $(window).scrollLeft();
+ var centerPointEndY = ((self.newPoints[0].y + self.newPoints[1].y) / 2) - $(window).scrollTop();
+
+ // And this is the translation due to translation of the centerpoint
+ // between the two fingers
+
+ var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;
+ var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;
+
+ // The new offset is the old/current one plus the total translation
+
+ var newOffsetX = currentOffsetX + ( translateFromZoomingX + translateFromTranslatingX );
+ var newOffsetY = currentOffsetY + ( translateFromZoomingY + translateFromTranslatingY );
+
+ var newPos = {
+ top : newOffsetY,
+ left : newOffsetX,
+ scaleX : self.contentStartPos.scaleX * pinchRatio,
+ scaleY : self.contentStartPos.scaleY * pinchRatio
+ };
+
+ self.canTap = false;
+
+ self.newWidth = newWidth;
+ self.newHeight = newHeight;
+
+ self.contentLastPos = newPos;
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+ $.fancybox.setTranslate( self.$content, self.contentLastPos );
+ });
+
+ };
+
+ Guestures.prototype.ontouchend = function( e ) {
+
+ var self = this;
+ var dMs = Math.max( (new Date().getTime() ) - self.startTime, 1);
+
+ var swiping = self.isSwiping;
+ var panning = self.isPanning;
+ var zooming = self.isZooming;
+
+ self.endPoints = pointers( e );
+
+ self.$container.removeClass( 'fancybox-controls--isGrabbing' );
+
+ $(document).off( '.fb.touch' );
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.isSwiping = false;
+ self.isPanning = false;
+ self.isZooming = false;
+
+ if ( self.canTap ) {
+ return self.onTap( e );
+ }
+
+ self.speed = 366;
+
+ // Speed in px/ms
+ self.velocityX = self.distanceX / dMs * 0.5;
+ self.velocityY = self.distanceY / dMs * 0.5;
+
+ self.speedX = Math.max( self.speed * 0.5, Math.min( self.speed * 1.5, ( 1 / Math.abs( self.velocityX ) ) * self.speed ) );
+
+ if ( panning ) {
+ self.endPanning();
+
+ } else if ( zooming ) {
+ self.endZooming();
+
+ } else {
+ self.endSwiping( swiping );
+ }
+
+ return;
+ };
+
+ Guestures.prototype.endSwiping = function( swiping ) {
+
+ var self = this;
+ var ret = false;
+
+ self.instance.isSliding = false;
+ self.sliderLastPos = null;
+
+ // Close if swiped vertically / navigate if horizontally
+ if ( swiping == 'y' && Math.abs( self.distanceY ) > 50 ) {
+
+ // Continue vertical movement
+ $.fancybox.animate( self.instance.current.$slide, {
+ top : self.sliderStartPos.top + self.distanceY + ( self.velocityY * 150 ),
+ opacity : 0
+ }, 150 );
+
+ ret = self.instance.close( true, 300 );
+
+ } else if ( swiping == 'x' && self.distanceX > 50 && self.instance.group.length > 1 ) {
+ ret = self.instance.previous( self.speedX );
+
+ } else if ( swiping == 'x' && self.distanceX < -50 && self.instance.group.length > 1 ) {
+ ret = self.instance.next( self.speedX );
+ }
+
+ if ( ret === false && ( swiping == 'x' || swiping == 'y' ) ) {
+ self.instance.jumpTo( self.instance.current.index, 150 );
+ }
+
+ self.$container.removeClass( 'fancybox-is-sliding' );
+
+ };
+
+ // Limit panning from edges
+ // ========================
+
+ Guestures.prototype.endPanning = function() {
+
+ var self = this;
+ var newOffsetX, newOffsetY, newPos;
+
+ if ( !self.contentLastPos ) {
+ return;
+ }
+
+ if ( self.instance.current.opts.touch.momentum === false ) {
+ newOffsetX = self.contentLastPos.left;
+ newOffsetY = self.contentLastPos.top;
+
+ } else {
+
+ // Continue movement
+ newOffsetX = self.contentLastPos.left + ( self.velocityX * self.speed );
+ newOffsetY = self.contentLastPos.top + ( self.velocityY * self.speed );
+ }
+
+ newPos = self.limitPosition( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
+
+ newPos.width = self.contentStartPos.width;
+ newPos.height = self.contentStartPos.height;
+
+ $.fancybox.animate( self.$content, newPos, 330 );
+ };
+
+
+ Guestures.prototype.endZooming = function() {
+
+ var self = this;
+
+ var current = self.instance.current;
+
+ var newOffsetX, newOffsetY, newPos, reset;
+
+ var newWidth = self.newWidth;
+ var newHeight = self.newHeight;
+
+ if ( !self.contentLastPos ) {
+ return;
+ }
+
+ newOffsetX = self.contentLastPos.left;
+ newOffsetY = self.contentLastPos.top;
+
+ reset = {
+ top : newOffsetY,
+ left : newOffsetX,
+ width : newWidth,
+ height : newHeight,
+ scaleX : 1,
+ scaleY : 1
+ };
+
+ // Reset scalex/scaleY values; this helps for perfomance and does not break animation
+ $.fancybox.setTranslate( self.$content, reset );
+
+ if ( newWidth < self.canvasWidth && newHeight < self.canvasHeight ) {
+ self.instance.scaleToFit( 150 );
+
+ } else if ( newWidth > current.width || newHeight > current.height ) {
+ self.instance.scaleToActual( self.centerPointStartX, self.centerPointStartY, 150 );
+
+ } else {
+
+ newPos = self.limitPosition( newOffsetX, newOffsetY, newWidth, newHeight );
+
+ // Switch from scale() to width/height or animation will not work correctly
+ $.fancybox.setTranslate( self.content, $.fancybox.getTranslate( self.$content ) );
+
+ $.fancybox.animate( self.$content, newPos, 150 );
+ }
+
+ };
+
+ Guestures.prototype.onTap = function(e) {
+ var self = this;
+ var $target = $( e.target );
+
+ var instance = self.instance;
+ var current = instance.current;
+
+ var endPoints = ( e && pointers( e ) ) || self.startPoints;
+
+ var tapX = endPoints[0] ? endPoints[0].x - self.$stage.offset().left : 0;
+ var tapY = endPoints[0] ? endPoints[0].y - self.$stage.offset().top : 0;
+
+ var where;
+
+ var process = function ( prefix ) {
+
+ var action = current.opts[ prefix ];
+
+ if ( $.isFunction( action ) ) {
+ action = action.apply( instance, [ current, e ] );
+ }
+
+ if ( !action) {
+ return;
+ }
+
+ switch ( action ) {
+
+ case "close" :
+
+ instance.close( self.startEvent );
+
+ break;
+
+ case "toggleControls" :
+
+ instance.toggleControls( true );
+
+ break;
+
+ case "next" :
+
+ instance.next();
+
+ break;
+
+ case "nextOrClose" :
+
+ if ( instance.group.length > 1 ) {
+ instance.next();
+
+ } else {
+ instance.close( self.startEvent );
+ }
+
+ break;
+
+ case "zoom" :
+
+ if ( current.type == 'image' && ( current.isLoaded || current.$ghost ) ) {
+
+ if ( instance.canPan() ) {
+ instance.scaleToFit();
+
+ } else if ( instance.isScaledDown() ) {
+ instance.scaleToActual( tapX, tapY );
+
+ } else if ( instance.group.length < 2 ) {
+ instance.close( self.startEvent );
+ }
+ }
+
+ break;
+ }
+
+ };
+
+ // Ignore right click
+ if ( e.originalEvent && e.originalEvent.button == 2 ) {
+ return;
+ }
+
+ // Skip if current slide is not in the center
+ if ( instance.isSliding ) {
+ return;
+ }
+
+ // Skip if clicked on the scrollbar
+ if ( tapX > $target[0].clientWidth + $target.offset().left ) {
+ return;
+ }
+
+ // Check where is clicked
+ if ( $target.is( '.fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container' ) ) {
+ where = 'Outside';
+
+ } else if ( $target.is( '.fancybox-slide' ) ) {
+ where = 'Slide';
+
+ } else if ( instance.current.$content && instance.current.$content.has( e.target ).length ) {
+ where = 'Content';
+
+ } else {
+ return;
+ }
+
+ // Check if this is a double tap
+ if ( self.tapped ) {
+
+ // Stop previously created single tap
+ clearTimeout( self.tapped );
+ self.tapped = null;
+
+ // Skip if distance between taps is too big
+ if ( Math.abs( tapX - self.tapX ) > 50 || Math.abs( tapY - self.tapY ) > 50 || instance.isSliding ) {
+ return this;
+ }
+
+ // OK, now we assume that this is a double-tap
+ process( 'dblclick' + where );
+
+ } else {
+
+ // Single tap will be processed if user has not clicked second time within 300ms
+ // or there is no need to wait for double-tap
+ self.tapX = tapX;
+ self.tapY = tapY;
+
+ if ( current.opts[ 'dblclick' + where ] && current.opts[ 'dblclick' + where ] !== current.opts[ 'click' + where ] ) {
+ self.tapped = setTimeout(function() {
+ self.tapped = null;
+
+ process( 'click' + where );
+
+ }, 300);
+
+ } else {
+ process( 'click' + where );
+ }
+
+ }
+
+ return this;
+ };
+
+ $(document).on('onActivate.fb', function (e, instance) {
+ if ( instance && !instance.Guestures ) {
+ instance.Guestures = new Guestures( instance );
+ }
+ });
+
+ $(document).on('beforeClose.fb', function (e, instance) {
+ if ( instance && instance.Guestures ) {
+ instance.Guestures.destroy();
+ }
+ });
+
+
+}(window, document, window.jQuery));
+
+// ==========================================================================
+//
+// SlideShow
+// Enables slideshow functionality
+//
+// Example of usage:
+// $.fancybox.getInstance().SlideShow.start()
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ var SlideShow = function( instance ) {
+ this.instance = instance;
+ this.init();
+ };
+
+ $.extend( SlideShow.prototype, {
+ timer : null,
+ isActive : false,
+ $button : null,
+ speed : 3000,
+
+ init : function() {
+ var self = this;
+
+ self.$button = self.instance.$refs.toolbar.find('[data-fancybox-play]').on('click', function() {
+ self.toggle();
+ });
+
+ if ( self.instance.group.length < 2 || !self.instance.group[ self.instance.currIndex ].opts.slideShow ) {
+ self.$button.hide();
+ }
+ },
+
+ set : function() {
+ var self = this;
+
+ // Check if reached last element
+ if ( self.instance && self.instance.current && (self.instance.current.opts.loop || self.instance.currIndex < self.instance.group.length - 1 )) {
+ self.timer = setTimeout(function() {
+ self.instance.next();
+
+ }, self.instance.current.opts.slideShow.speed || self.speed);
+
+ } else {
+ self.stop();
+ self.instance.idleSecondsCounter = 0;
+ self.instance.showControls();
+ }
+
+ },
+
+ clear : function() {
+ var self = this;
+
+ clearTimeout( self.timer );
+
+ self.timer = null;
+ },
+
+ start : function() {
+ var self = this;
+ var current = self.instance.current;
+
+ if ( self.instance && current && ( current.opts.loop || current.index < self.instance.group.length - 1 )) {
+
+ self.isActive = true;
+
+ self.$button
+ .attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_STOP )
+ .addClass( 'fancybox-button--pause' );
+
+ if ( current.isComplete ) {
+ self.set();
+ }
+ }
+ },
+
+ stop : function() {
+ var self = this;
+ var current = self.instance.current;
+
+ self.clear();
+
+ self.$button
+ .attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_START )
+ .removeClass( 'fancybox-button--pause' );
+
+ self.isActive = false;
+ },
+
+ toggle : function() {
+ var self = this;
+
+ if ( self.isActive ) {
+ self.stop();
+
+ } else {
+ self.start();
+ }
+ }
+
+ });
+
+ $(document).on({
+ 'onInit.fb' : function(e, instance) {
+ if ( instance && !instance.SlideShow ) {
+ instance.SlideShow = new SlideShow( instance );
+ }
+ },
+
+ 'beforeShow.fb' : function(e, instance, current, firstRun) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( firstRun ) {
+
+ if ( SlideShow && current.opts.slideShow.autoStart ) {
+ SlideShow.start();
+ }
+
+ } else if ( SlideShow && SlideShow.isActive ) {
+ SlideShow.clear();
+ }
+ },
+
+ 'afterShow.fb' : function(e, instance, current) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow && SlideShow.isActive ) {
+ SlideShow.set();
+ }
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+ var SlideShow = instance && instance.SlideShow;
+
+ // "P" or Spacebar
+ if ( SlideShow && current.opts.slideShow && ( keycode === 80 || keycode === 32 ) && !$(document.activeElement).is( 'button,a,input' ) ) {
+ keypress.preventDefault();
+
+ SlideShow.toggle();
+ }
+ },
+
+ 'beforeClose.fb onDeactivate.fb' : function(e, instance) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow ) {
+ SlideShow.stop();
+ }
+ }
+ });
+
+ // Page Visibility API to pause slideshow when window is not active
+ $(document).on("visibilitychange", function() {
+ var instance = $.fancybox.getInstance();
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow && SlideShow.isActive ) {
+ if ( document.hidden ) {
+ SlideShow.clear();
+
+ } else {
+ SlideShow.set();
+ }
+ }
+ });
+
+}(document, window.jQuery));
+
+// ==========================================================================
+//
+// FullScreen
+// Adds fullscreen functionality
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ // Collection of methods supported by user browser
+ var fn = (function () {
+
+ var fnMap = [
+ [
+ 'requestFullscreen',
+ 'exitFullscreen',
+ 'fullscreenElement',
+ 'fullscreenEnabled',
+ 'fullscreenchange',
+ 'fullscreenerror'
+ ],
+ // new WebKit
+ [
+ 'webkitRequestFullscreen',
+ 'webkitExitFullscreen',
+ 'webkitFullscreenElement',
+ 'webkitFullscreenEnabled',
+ 'webkitfullscreenchange',
+ 'webkitfullscreenerror'
+
+ ],
+ // old WebKit (Safari 5.1)
+ [
+ 'webkitRequestFullScreen',
+ 'webkitCancelFullScreen',
+ 'webkitCurrentFullScreenElement',
+ 'webkitCancelFullScreen',
+ 'webkitfullscreenchange',
+ 'webkitfullscreenerror'
+
+ ],
+ [
+ 'mozRequestFullScreen',
+ 'mozCancelFullScreen',
+ 'mozFullScreenElement',
+ 'mozFullScreenEnabled',
+ 'mozfullscreenchange',
+ 'mozfullscreenerror'
+ ],
+ [
+ 'msRequestFullscreen',
+ 'msExitFullscreen',
+ 'msFullscreenElement',
+ 'msFullscreenEnabled',
+ 'MSFullscreenChange',
+ 'MSFullscreenError'
+ ]
+ ];
+
+ var val;
+ var ret = {};
+ var i, j;
+
+ for ( i = 0; i < fnMap.length; i++ ) {
+ val = fnMap[ i ];
+
+ if ( val && val[ 1 ] in document ) {
+ for ( j = 0; j < val.length; j++ ) {
+ ret[ fnMap[ 0 ][ j ] ] = val[ j ];
+ }
+
+ return ret;
+ }
+ }
+
+ return false;
+ })();
+
+ // If browser does not have Full Screen API, then simply unset default button template and stop
+ if ( !fn ) {
+ $.fancybox.defaults.btnTpl.fullScreen = false;
+
+ return;
+ }
+
+ var FullScreen = {
+ request : function ( elem ) {
+
+ elem = elem || document.documentElement;
+
+ elem[ fn.requestFullscreen ]( elem.ALLOW_KEYBOARD_INPUT );
+
+ },
+ exit : function () {
+
+ document[ fn.exitFullscreen ]();
+
+ },
+ toggle : function ( elem ) {
+
+ elem = elem || document.documentElement;
+
+ if ( this.isFullscreen() ) {
+ this.exit();
+
+ } else {
+ this.request( elem );
+ }
+
+ },
+ isFullscreen : function() {
+
+ return Boolean( document[ fn.fullscreenElement ] );
+
+ },
+ enabled : function() {
+
+ return Boolean( document[ fn.fullscreenEnabled ] );
+
+ }
+ };
+
+ $(document).on({
+ 'onInit.fb' : function(e, instance) {
+ var $container;
+
+ var $button = instance.$refs.toolbar.find('[data-fancybox-fullscreen]');
+
+ if ( instance && !instance.FullScreen && instance.group[ instance.currIndex ].opts.fullScreen ) {
+ $container = instance.$refs.container;
+
+ $container.on('click.fb-fullscreen', '[data-fancybox-fullscreen]', function(e) {
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ FullScreen.toggle( $container[ 0 ] );
+
+ });
+
+ if ( instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true ) {
+ FullScreen.request( $container[ 0 ] );
+ }
+
+ // Expose API
+ instance.FullScreen = FullScreen;
+
+ } else {
+ $button.hide();
+ }
+
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+
+ // "P" or Spacebar
+ if ( instance && instance.FullScreen && keycode === 70 ) {
+ keypress.preventDefault();
+
+ instance.FullScreen.toggle( instance.$refs.container[ 0 ] );
+ }
+
+ },
+
+ 'beforeClose.fb' : function( instance ) {
+ if ( instance && instance.FullScreen ) {
+ FullScreen.exit();
+ }
+ }
+ });
+
+ $(document).on(fn.fullscreenchange, function() {
+ var instance = $.fancybox.getInstance();
+
+ // If image is zooming, then force to stop and reposition properly
+ if ( instance.current && instance.current.type === 'image' && instance.isAnimating ) {
+ instance.current.$content.css( 'transition', 'none' );
+
+ instance.isAnimating = false;
+
+ instance.update( true, true, 0 );
+ }
+
+ });
+
+}(document, window.jQuery));
+
+// ==========================================================================
+//
+// Thumbs
+// Displays thumbnails in a grid
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ var FancyThumbs = function( instance ) {
+ this.instance = instance;
+ this.init();
+ };
+
+ $.extend( FancyThumbs.prototype, {
+
+ $button : null,
+ $grid : null,
+ $list : null,
+ isVisible : false,
+
+ init : function() {
+ var self = this;
+
+ var first = self.instance.group[0],
+ second = self.instance.group[1];
+
+ self.$button = self.instance.$refs.toolbar.find( '[data-fancybox-thumbs]' );
+
+ if ( self.instance.group.length > 1 && self.instance.group[ self.instance.currIndex ].opts.thumbs && (
+ ( first.type == 'image' || first.opts.thumb || first.opts.$thumb ) &&
+ ( second.type == 'image' || second.opts.thumb || second.opts.$thumb )
+ )) {
+
+ self.$button.on('click', function() {
+ self.toggle();
+ });
+
+ self.isActive = true;
+
+ } else {
+ self.$button.hide();
+
+ self.isActive = false;
+ }
+
+ },
+
+ create : function() {
+ var instance = this.instance,
+ list,
+ src;
+
+ this.$grid = $('<div class="fancybox-thumbs"></div>').appendTo( instance.$refs.container );
+
+ list = '<ul>';
+
+ $.each(instance.group, function( i, item ) {
+
+ src = item.opts.thumb || ( item.opts.$thumb ? item.opts.$thumb.attr('src') : null );
+
+ if ( !src && item.type === 'image' ) {
+ src = item.src;
+ }
+
+ if ( src && src.length ) {
+ list += '<li data-index="' + i + '" tabindex="0" class="fancybox-thumbs-loading"><img data-src="' + src + '" /></li>';
+ }
+
+ });
+
+ list += '</ul>';
+
+ this.$list = $( list ).appendTo( this.$grid ).on('click', 'li', function() {
+ instance.jumpTo( $(this).data('index') );
+ });
+
+ this.$list.find('img').hide().one('load', function() {
+
+ var $parent = $(this).parent().removeClass('fancybox-thumbs-loading'),
+ thumbWidth = $parent.outerWidth(),
+ thumbHeight = $parent.outerHeight(),
+ width,
+ height,
+ widthRatio,
+ heightRatio;
+
+ width = this.naturalWidth || this.width;
+ height = this.naturalHeight || this.height;
+
+ //Calculate thumbnail width/height and center it
+
+ widthRatio = width / thumbWidth;
+ heightRatio = height / thumbHeight;
+
+ if (widthRatio >= 1 && heightRatio >= 1) {
+ if (widthRatio > heightRatio) {
+ width = width / heightRatio;
+ height = thumbHeight;
+
+ } else {
+ width = thumbWidth;
+ height = height / widthRatio;
+ }
+ }
+
+ $(this).css({
+ width : Math.floor(width),
+ height : Math.floor(height),
+ 'margin-top' : Math.min( 0, Math.floor(thumbHeight * 0.3 - height * 0.3 ) ),
+ 'margin-left' : Math.min( 0, Math.floor(thumbWidth * 0.5 - width * 0.5 ) )
+ }).show();
+
+ })
+ .each(function() {
+ this.src = $( this ).data( 'src' );
+ });
+
+ },
+
+ focus : function() {
+
+ if ( this.instance.current ) {
+ this.$list
+ .children()
+ .removeClass('fancybox-thumbs-active')
+ .filter('[data-index="' + this.instance.current.index + '"]')
+ .addClass('fancybox-thumbs-active')
+ .focus();
+ }
+
+ },
+
+ close : function() {
+ this.$grid.hide();
+ },
+
+ update : function() {
+
+ this.instance.$refs.container.toggleClass( 'fancybox-show-thumbs', this.isVisible );
+
+ if ( this.isVisible ) {
+
+ if ( !this.$grid ) {
+ this.create();
+ }
+
+ this.instance.trigger( 'onThumbsShow' );
+
+ this.focus();
+
+ } else if ( this.$grid ) {
+ this.instance.trigger( 'onThumbsHide' );
+ }
+
+ // Update content position
+ this.instance.update();
+
+ },
+
+ hide : function() {
+ this.isVisible = false;
+ this.update();
+ },
+
+ show : function() {
+ this.isVisible = true;
+ this.update();
+ },
+
+ toggle : function() {
+ this.isVisible = !this.isVisible;
+ this.update();
+ }
+
+ });
+
+ $(document).on({
+
+ 'onInit.fb' : function(e, instance) {
+ if ( instance && !instance.Thumbs ) {
+ instance.Thumbs = new FancyThumbs( instance );
+ }
+ },
+
+ 'beforeShow.fb' : function(e, instance, item, firstRun) {
+ var Thumbs = instance && instance.Thumbs;
+
+ if ( !Thumbs || !Thumbs.isActive ) {
+ return;
+ }
+
+ if ( item.modal ) {
+ Thumbs.$button.hide();
+
+ Thumbs.hide();
+
+ return;
+ }
+
+ if ( firstRun && instance.opts.thumbs.autoStart === true ) {
+ Thumbs.show();
+ }
+
+ if ( Thumbs.isVisible ) {
+ Thumbs.focus();
+ }
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+ var Thumbs = instance && instance.Thumbs;
+
+ // "G"
+ if ( Thumbs && Thumbs.isActive && keycode === 71 ) {
+ keypress.preventDefault();
+
+ Thumbs.toggle();
+ }
+ },
+
+ 'beforeClose.fb' : function( e, instance ) {
+ var Thumbs = instance && instance.Thumbs;
+
+ if ( Thumbs && Thumbs.isVisible && instance.opts.thumbs.hideOnClose !== false ) {
+ Thumbs.close();
+ }
+ }
+
+ });
+
+}(document, window.jQuery));
+
+// ==========================================================================
+//
+// Hash
+// Enables linking to each modal
+//
+// ==========================================================================
+;(function (document, window, $) {
+ 'use strict';
+
+ // Simple $.escapeSelector polyfill (for jQuery prior v3)
+ if ( !$.escapeSelector ) {
+ $.escapeSelector = function( sel ) {
+ var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
+ var fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ };
+
+ return ( sel + "" ).replace( rcssescape, fcssescape );
+ };
+ }
+
+ // Create new history entry only once
+ var shouldCreateHistory = true;
+
+ // Variable containing last hash value set by fancyBox
+ // It will be used to determine if fancyBox needs to close after hash change is detected
+ var currentHash = null;
+
+ // Throttling the history change
+ var timerID = null;
+
+ // Get info about gallery name and current index from url
+ function parseUrl() {
+ var hash = window.location.hash.substr( 1 );
+ var rez = hash.split( '-' );
+ var index = rez.length > 1 && /^\+?\d+$/.test( rez[ rez.length - 1 ] ) ? parseInt( rez.pop( -1 ), 10 ) || 1 : 1;
+ var gallery = rez.join( '-' );
+
+ // Index is starting from 1
+ if ( index < 1 ) {
+ index = 1;
+ }
+
+ return {
+ hash : hash,
+ index : index,
+ gallery : gallery
+ };
+ }
+
+ // Trigger click evnt on links to open new fancyBox instance
+ function triggerFromUrl( url ) {
+ var $el;
+
+ if ( url.gallery !== '' ) {
+
+ // If we can find element matching 'data-fancybox' atribute, then trigger click event for that ..
+ $el = $( "[data-fancybox='" + $.escapeSelector( url.gallery ) + "']" ).eq( url.index - 1 );
+
+ if ( !$el.length ) {
+ // .. if not, try finding element by ID
+ $el = $( "#" + $.escapeSelector( url.gallery ) + "" );
+ }
+
+ if ( $el.length ) {
+ shouldCreateHistory = false;
+
+ $el.trigger( 'click' );
+ }
+
+ }
+ }
+
+ // Get gallery name from current instance
+ function getGallery( instance ) {
+ var opts;
+
+ if ( !instance ) {
+ return false;
+ }
+
+ opts = instance.current ? instance.current.opts : instance.opts;
+
+ return opts.$orig ? opts.$orig.data( 'fancybox' ) : ( opts.hash || '' );
+ }
+
+ // Star when DOM becomes ready
+ $(function() {
+
+ // Small delay is used to allow other scripts to process "dom ready" event
+ setTimeout(function() {
+
+ // Check if this module is not disabled
+ if ( $.fancybox.defaults.hash === false ) {
+ return;
+ }
+
+ // Update hash when opening/closing fancyBox
+ $(document).on({
+ 'onInit.fb' : function( e, instance ) {
+ var url, gallery;
+
+ if ( instance.group[ instance.currIndex ].opts.hash === false ) {
+ return;
+ }
+
+ url = parseUrl();
+ gallery = getGallery( instance );
+
+ // Make sure gallery start index matches index from hash
+ if ( gallery && url.gallery && gallery == url.gallery ) {
+ instance.currIndex = url.index - 1;
+ }
+
+ },
+
+ 'beforeShow.fb' : function( e, instance, current ) {
+ var gallery;
+
+ if ( current.opts.hash === false ) {
+ return;
+ }
+
+ gallery = getGallery( instance );
+
+ // Update window hash
+ if ( gallery && gallery !== '' ) {
+
+ if ( window.location.hash.indexOf( gallery ) < 0 ) {
+ instance.opts.origHash = window.location.hash;
+ }
+
+ currentHash = gallery + ( instance.group.length > 1 ? '-' + ( current.index + 1 ) : '' );
+
+ if ( 'replaceState' in window.history ) {
+ if ( timerID ) {
+ clearTimeout( timerID );
+ }
+
+ timerID = setTimeout(function() {
+ window.history[ shouldCreateHistory ? 'pushState' : 'replaceState' ]( {} , document.title, window.location.pathname + window.location.search + '#' + currentHash );
+
+ timerID = null;
+
+ shouldCreateHistory = false;
+
+ }, 300);
+
+ } else {
+ window.location.hash = currentHash;
+ }
+
+ }
+
+ },
+
+ 'beforeClose.fb' : function( e, instance, current ) {
+ var gallery, origHash;
+
+ if ( timerID ) {
+ clearTimeout( timerID );
+ }
+
+ if ( current.opts.hash === false ) {
+ return;
+ }
+
+ gallery = getGallery( instance );
+ origHash = instance && instance.opts.origHash ? instance.opts.origHash : '';
+
+ // Remove hash from location bar
+ if ( gallery && gallery !== '' ) {
+
+ if ( 'replaceState' in history ) {
+ window.history.replaceState( {} , document.title, window.location.pathname + window.location.search + origHash );
+
+ } else {
+ window.location.hash = origHash;
+
+ // Keep original scroll position
+ $( window ).scrollTop( instance.scrollTop ).scrollLeft( instance.scrollLeft );
+ }
+ }
+
+ currentHash = null;
+ }
+ });
+
+ // Check if need to close after url has changed
+ $(window).on('hashchange.fb', function() {
+ var url = parseUrl();
+
+ if ( $.fancybox.getInstance() ) {
+ if ( currentHash && currentHash !== url.gallery + '-' + url.index && !( url.index === 1 && currentHash == url.gallery ) ) {
+ currentHash = null;
+
+ $.fancybox.close();
+
+ shouldCreateHistory = true;
+ }
+
+ } else if ( url.gallery !== '' ) {
+ triggerFromUrl( url );
+ }
+ });
+
+ // Check current hash and trigger click event on matching element to start fancyBox, if needed
+ triggerFromUrl( parseUrl() );
+
+ }, 50);
+
+ });
+
+
+}(document, window, window.jQuery));
--- /dev/null
+@charset "UTF-8";.fancybox-enabled{overflow:hidden}.fancybox-enabled body{overflow:visible;height:100%}.fancybox-is-hidden{position:absolute;top:-9999px;left:-9999px;visibility:hidden}.fancybox-container{position:fixed;top:0;left:0;width:100%;height:100%;z-index:99993;-webkit-tap-highlight-color:transparent;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0)}.fancybox-container~.fancybox-container{z-index:99992}.fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-stage{position:absolute;top:0;right:0;bottom:0;left:0}.fancybox-outer{overflow-y:auto;-webkit-overflow-scrolling:touch}.fancybox-bg{background:#1e1e1e;opacity:0;transition-duration:inherit;transition-property:opacity;transition-timing-function:cubic-bezier(.47,0,.74,.71)}.fancybox-is-open .fancybox-bg{opacity:.87;transition-timing-function:cubic-bezier(.22,.61,.36,1)}.fancybox-caption-wrap,.fancybox-infobar,.fancybox-toolbar{position:absolute;direction:ltr;z-index:99997;opacity:0;visibility:hidden;transition:opacity .25s,visibility 0s linear .25s;box-sizing:border-box}.fancybox-show-caption .fancybox-caption-wrap,.fancybox-show-infobar .fancybox-infobar,.fancybox-show-toolbar .fancybox-toolbar{opacity:1;visibility:visible;transition:opacity .25s,visibility 0s}.fancybox-infobar{top:0;left:50%;margin-left:-79px}.fancybox-infobar__body{display:inline-block;width:70px;line-height:44px;font-size:13px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;text-align:center;color:#ddd;background-color:rgba(30,30,30,.7);pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-font-smoothing:subpixel-antialiased}.fancybox-toolbar{top:0;right:0}.fancybox-stage{overflow:hidden;direction:ltr;z-index:99994;-webkit-transform:translateZ(0)}.fancybox-slide{position:absolute;top:0;left:0;width:100%;height:100%;margin:0;padding:0;overflow:auto;outline:none;white-space:normal;box-sizing:border-box;text-align:center;z-index:99994;-webkit-overflow-scrolling:touch;display:none;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.fancybox-slide:before{content:"";display:inline-block;vertical-align:middle;height:100%;width:0}.fancybox-is-sliding .fancybox-slide,.fancybox-slide--current,.fancybox-slide--next,.fancybox-slide--previous{display:block}.fancybox-slide--image{overflow:visible}.fancybox-slide--image:before{display:none}.fancybox-slide--video .fancybox-content,.fancybox-slide--video iframe{background:#000}.fancybox-slide--map .fancybox-content,.fancybox-slide--map iframe{background:#e5e3df}.fancybox-slide--next{z-index:99995}.fancybox-slide>*{display:inline-block;position:relative;padding:24px;margin:44px 0;border-width:0;vertical-align:middle;text-align:left;background-color:#fff;overflow:auto;box-sizing:border-box}.fancybox-slide .fancybox-image-wrap{position:absolute;top:0;left:0;margin:0;padding:0;border:0;z-index:99995;background:transparent;cursor:default;overflow:visible;-webkit-transform-origin:top left;transform-origin:top left;background-size:100% 100%;background-repeat:no-repeat;-webkit-backface-visibility:hidden;backface-visibility:hidden}.fancybox-can-zoomOut .fancybox-image-wrap{cursor:zoom-out}.fancybox-can-zoomIn .fancybox-image-wrap{cursor:zoom-in}.fancybox-can-drag .fancybox-image-wrap{cursor:-webkit-grab;cursor:grab}.fancybox-is-dragging .fancybox-image-wrap{cursor:-webkit-grabbing;cursor:grabbing}.fancybox-image,.fancybox-spaceball{position:absolute;top:0;left:0;width:100%;height:100%;margin:0;padding:0;border:0;max-width:none;max-height:none}.fancybox-spaceball{z-index:1}.fancybox-slide--iframe .fancybox-content{padding:0;width:80%;height:80%;max-width:calc(100% - 100px);max-height:calc(100% - 88px);overflow:visible;background:#fff}.fancybox-iframe{display:block;padding:0;border:0;height:100%}.fancybox-error,.fancybox-iframe{margin:0;width:100%;background:#fff}.fancybox-error{padding:40px;max-width:380px;cursor:default}.fancybox-error p{margin:0;padding:0;color:#444;font:16px/20px Helvetica Neue,Helvetica,Arial,sans-serif}.fancybox-close-small{position:absolute;top:0;right:0;width:44px;height:44px;padding:0;margin:0;border:0;border-radius:0;outline:none;background:transparent;z-index:10;cursor:pointer}.fancybox-close-small:after{content:"×";position:absolute;top:5px;right:5px;width:30px;height:30px;font:20px/30px Arial,Helvetica Neue,Helvetica,sans-serif;color:#888;font-weight:300;text-align:center;border-radius:50%;border-width:0;background:#fff;transition:background .25s;box-sizing:border-box;z-index:2}.fancybox-close-small:focus:after{outline:1px dotted #888}.fancybox-close-small:hover:after{color:#555;background:#eee}.fancybox-slide--iframe .fancybox-close-small{top:0;right:-44px}.fancybox-slide--iframe .fancybox-close-small:after{background:transparent;font-size:35px;color:#aaa}.fancybox-slide--iframe .fancybox-close-small:hover:after{color:#fff}.fancybox-caption-wrap{bottom:0;left:0;right:0;padding:60px 30px 0;background:linear-gradient(180deg,transparent 0,rgba(0,0,0,.1) 20%,rgba(0,0,0,.2) 40%,rgba(0,0,0,.6) 80%,rgba(0,0,0,.8));pointer-events:none}.fancybox-caption{padding:30px 0;border-top:1px solid hsla(0,0%,100%,.4);font-size:14px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;color:#fff;line-height:20px;-webkit-text-size-adjust:none}.fancybox-caption a,.fancybox-caption button,.fancybox-caption select{pointer-events:all}.fancybox-caption a{color:#fff;text-decoration:underline}.fancybox-button{display:inline-block;position:relative;margin:0;padding:0;border:0;width:44px;height:44px;line-height:44px;text-align:center;background:transparent;color:#ddd;border-radius:0;cursor:pointer;vertical-align:top;outline:none}.fancybox-button[disabled]{cursor:default;pointer-events:none}.fancybox-button,.fancybox-infobar__body{background:rgba(30,30,30,.6)}.fancybox-button:hover:not([disabled]){color:#fff;background:rgba(0,0,0,.8)}.fancybox-button:after,.fancybox-button:before{content:"";pointer-events:none;position:absolute;background-color:currentColor;color:currentColor;opacity:.9;box-sizing:border-box;display:inline-block}.fancybox-button[disabled]:after,.fancybox-button[disabled]:before{opacity:.3}.fancybox-button--left:after,.fancybox-button--right:after{top:18px;width:6px;height:6px;background:transparent;border-top:2px solid currentColor;border-right:2px solid currentColor}.fancybox-button--left:after{left:20px;-webkit-transform:rotate(-135deg);transform:rotate(-135deg)}.fancybox-button--right:after{right:20px;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.fancybox-button--left{border-bottom-left-radius:5px}.fancybox-button--right{border-bottom-right-radius:5px}.fancybox-button--close:after,.fancybox-button--close:before{content:"";display:inline-block;position:absolute;height:2px;width:16px;top:calc(50% - 1px);left:calc(50% - 8px)}.fancybox-button--close:before{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.fancybox-button--close:after{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.fancybox-arrow{position:absolute;top:50%;margin:-50px 0 0;height:100px;width:54px;padding:0;border:0;outline:none;background:none;cursor:pointer;z-index:99995;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition:opacity .25s}.fancybox-arrow:after{content:"";position:absolute;top:28px;width:44px;height:44px;background-color:rgba(30,30,30,.8);background-image:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjQ4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSI0OCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMTIgNGwtMS40MSAxLjQxTDE2LjE3IDExSDR2MmgxMi4xN2wtNS41OCA1LjU5TDEyIDIwbDgtOHoiLz48L3N2Zz4=);background-repeat:no-repeat;background-position:50%;background-size:24px 24px}.fancybox-arrow--right{right:0}.fancybox-arrow--left{left:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fancybox-arrow--left:after,.fancybox-arrow--right:after{left:0}.fancybox-show-nav .fancybox-arrow{opacity:.6}.fancybox-show-nav .fancybox-arrow[disabled]{opacity:.3}.fancybox-loading{border:6px solid hsla(0,0%,39%,.4);border-top:6px solid hsla(0,0%,100%,.6);border-radius:100%;height:50px;width:50px;-webkit-animation:a .8s infinite linear;animation:a .8s infinite linear;background:transparent;position:absolute;top:50%;left:50%;margin-top:-25px;margin-left:-25px;z-index:99999}@-webkit-keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fancybox-animated{transition-timing-function:cubic-bezier(0,0,.25,1)}.fancybox-fx-slide.fancybox-slide--previous{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);opacity:0}.fancybox-fx-slide.fancybox-slide--next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);opacity:0}.fancybox-fx-slide.fancybox-slide--current{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}.fancybox-fx-fade.fancybox-slide--next,.fancybox-fx-fade.fancybox-slide--previous{opacity:0;transition-timing-function:cubic-bezier(.19,1,.22,1)}.fancybox-fx-fade.fancybox-slide--current{opacity:1}.fancybox-fx-zoom-in-out.fancybox-slide--previous{-webkit-transform:scale3d(1.5,1.5,1.5);transform:scale3d(1.5,1.5,1.5);opacity:0}.fancybox-fx-zoom-in-out.fancybox-slide--next{-webkit-transform:scale3d(.5,.5,.5);transform:scale3d(.5,.5,.5);opacity:0}.fancybox-fx-zoom-in-out.fancybox-slide--current{-webkit-transform:scaleX(1);transform:scaleX(1);opacity:1}.fancybox-fx-rotate.fancybox-slide--previous{-webkit-transform:rotate(-1turn);transform:rotate(-1turn);opacity:0}.fancybox-fx-rotate.fancybox-slide--next{-webkit-transform:rotate(1turn);transform:rotate(1turn);opacity:0}.fancybox-fx-rotate.fancybox-slide--current{-webkit-transform:rotate(0deg);transform:rotate(0deg);opacity:1}.fancybox-fx-circular.fancybox-slide--previous{-webkit-transform:scale3d(0,0,0) translate3d(-100%,0,0);transform:scale3d(0,0,0) translate3d(-100%,0,0);opacity:0}.fancybox-fx-circular.fancybox-slide--next{-webkit-transform:scale3d(0,0,0) translate3d(100%,0,0);transform:scale3d(0,0,0) translate3d(100%,0,0);opacity:0}.fancybox-fx-circular.fancybox-slide--current{-webkit-transform:scaleX(1) translateZ(0);transform:scaleX(1) translateZ(0);opacity:1}.fancybox-fx-tube.fancybox-slide--previous{-webkit-transform:translate3d(-100%,0,0) scale(.1) skew(-10deg);transform:translate3d(-100%,0,0) scale(.1) skew(-10deg)}.fancybox-fx-tube.fancybox-slide--next{-webkit-transform:translate3d(100%,0,0) scale(.1) skew(10deg);transform:translate3d(100%,0,0) scale(.1) skew(10deg)}.fancybox-fx-tube.fancybox-slide--current{-webkit-transform:translateZ(0) scale(1);transform:translateZ(0) scale(1)}@media (max-width:800px){.fancybox-infobar{left:0;margin-left:0}.fancybox-button--left,.fancybox-button--right{display:none!important}.fancybox-caption{padding:20px 0;margin:0}}.fancybox-button--fullscreen:before{width:15px;height:11px;left:calc(50% - 7px);top:calc(50% - 6px);border:2px solid;background:none}.fancybox-button--pause:before,.fancybox-button--play:before{top:calc(50% - 6px);left:calc(50% - 4px);background:transparent}.fancybox-button--play:before{width:0;height:0;border-top:6px inset transparent;border-bottom:6px inset transparent;border-left:10px solid;border-radius:1px}.fancybox-button--pause:before{width:7px;height:11px;border-style:solid;border-width:0 2px}.fancybox-button--thumbs,.fancybox-thumbs{display:none}@media (min-width:800px){.fancybox-button--thumbs{display:inline-block}.fancybox-button--thumbs span{font-size:23px}.fancybox-button--thumbs:before{width:3px;height:3px;top:calc(50% - 2px);left:calc(50% - 2px);box-shadow:0 -4px 0,-4px -4px 0,4px -4px 0,inset 0 0 0 32px,-4px 0 0,4px 0 0,0 4px 0,-4px 4px 0,4px 4px 0}.fancybox-thumbs{position:absolute;top:0;right:0;bottom:0;left:auto;width:220px;margin:0;padding:5px 5px 0 0;background:#fff;word-break:normal;-webkit-tap-highlight-color:transparent;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;box-sizing:border-box;z-index:99995}.fancybox-show-thumbs .fancybox-thumbs{display:block}.fancybox-show-thumbs .fancybox-inner{right:220px}.fancybox-thumbs>ul{list-style:none;position:absolute;position:relative;width:100%;height:100%;margin:0;padding:0;overflow-x:hidden;overflow-y:auto;font-size:0}.fancybox-thumbs>ul>li{float:left;overflow:hidden;max-width:50%;padding:0;margin:0;width:105px;height:75px;position:relative;cursor:pointer;outline:none;border:5px solid transparent;border-top-width:0;border-right-width:0;-webkit-tap-highlight-color:transparent;-webkit-backface-visibility:hidden;backface-visibility:hidden;box-sizing:border-box}li.fancybox-thumbs-loading{background:rgba(0,0,0,.1)}.fancybox-thumbs>ul>li>img{position:absolute;top:0;left:0;min-width:100%;min-height:100%;max-width:none;max-height:none;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fancybox-thumbs>ul>li:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:2px;border:4px solid #4ea7f9;z-index:99991;opacity:0;transition:all .2s cubic-bezier(.25,.46,.45,.94)}.fancybox-thumbs>ul>li.fancybox-thumbs-active:before{opacity:1}}
\ No newline at end of file
--- /dev/null
+// ==================================================
+// fancyBox v3.1.24
+//
+// Licensed GPLv3 for open source use
+// or fancyBox Commercial License for commercial use
+//
+// http://fancyapps.com/fancybox/
+// Copyright 2017 fancyApps
+//
+// ==================================================
+!function(t,e,n,o){"use strict";function i(t){var e=t.currentTarget,o=t.data?t.data.options:{},i=o.selector?n(o.selector):t.data?t.data.items:[],a=n(e).attr("data-fancybox")||"",s=0,r=n.fancybox.getInstance();t.preventDefault(),t.stopPropagation(),r&&r.current.opts.$orig.is(e)||(a?(i=i.length?i.filter('[data-fancybox="'+a+'"]'):n('[data-fancybox="'+a+'"]'),s=i.index(e),s<0&&(s=0)):i=[e],n.fancybox.open(i,o,s))}if(n){if(n.fn.fancybox)return void n.error("fancyBox already initialized");var a={loop:!1,margin:[44,0],gutter:50,keyboard:!0,arrows:!0,infobar:!1,toolbar:!0,buttons:["slideShow","fullScreen","thumbs","close"],idleTime:4,smallBtn:"auto",protect:!1,modal:!1,image:{preload:"auto"},ajax:{settings:{data:{fancybox:!0}}},iframe:{tpl:'<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen allowtransparency="true" src=""></iframe>',preload:!0,css:{},attr:{scrolling:"auto"}},animationEffect:"zoom",animationDuration:366,zoomOpacity:"auto",transitionEffect:"fade",transitionDuration:366,slideClass:"",baseClass:"",baseTpl:'<div class="fancybox-container" role="dialog" tabindex="-1"><div class="fancybox-bg"></div><div class="fancybox-inner"><div class="fancybox-infobar"><button data-fancybox-prev title="{{PREV}}" class="fancybox-button fancybox-button--left"></button><div class="fancybox-infobar__body"><span data-fancybox-index></span> / <span data-fancybox-count></span></div><button data-fancybox-next title="{{NEXT}}" class="fancybox-button fancybox-button--right"></button></div><div class="fancybox-toolbar">{{BUTTONS}}</div><div class="fancybox-navigation"><button data-fancybox-prev title="{{PREV}}" class="fancybox-arrow fancybox-arrow--left" /><button data-fancybox-next title="{{NEXT}}" class="fancybox-arrow fancybox-arrow--right" /></div><div class="fancybox-stage"></div><div class="fancybox-caption-wrap"><div class="fancybox-caption"></div></div></div></div>',spinnerTpl:'<div class="fancybox-loading"></div>',errorTpl:'<div class="fancybox-error"><p>{{ERROR}}<p></div>',btnTpl:{slideShow:'<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}"></button>',fullScreen:'<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fullscreen" title="{{FULL_SCREEN}}"></button>',thumbs:'<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}"></button>',close:'<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}"></button>',smallBtn:'<button data-fancybox-close class="fancybox-close-small" title="{{CLOSE}}"></button>'},parentEl:"body",autoFocus:!0,backFocus:!0,trapFocus:!0,fullScreen:{autoStart:!1},touch:{vertical:!0,momentum:!0},hash:null,media:{},slideShow:{autoStart:!1,speed:4e3},thumbs:{autoStart:!1,hideOnClose:!0},onInit:n.noop,beforeLoad:n.noop,afterLoad:n.noop,beforeShow:n.noop,afterShow:n.noop,beforeClose:n.noop,afterClose:n.noop,onActivate:n.noop,onDeactivate:n.noop,clickContent:function(t,e){return"image"===t.type&&"zoom"},clickSlide:"close",clickOutside:"close",dblclickContent:!1,dblclickSlide:!1,dblclickOutside:!1,mobile:{clickContent:function(t,e){return"image"===t.type&&"toggleControls"},clickSlide:function(t,e){return"image"===t.type?"toggleControls":"close"},dblclickContent:function(t,e){return"image"===t.type&&"zoom"},dblclickSlide:function(t,e){return"image"===t.type&&"zoom"}},lang:"en",i18n:{en:{CLOSE:"Close",NEXT:"Next",PREV:"Previous",ERROR:"The requested content cannot be loaded. <br/> Please try again later.",PLAY_START:"Start slideshow",PLAY_STOP:"Pause slideshow",FULL_SCREEN:"Full screen",THUMBS:"Thumbnails"},de:{CLOSE:"Schliessen",NEXT:"Weiter",PREV:"Zurück",ERROR:"Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es später nochmal.",PLAY_START:"Diaschau starten",PLAY_STOP:"Diaschau beenden",FULL_SCREEN:"Vollbild",THUMBS:"Vorschaubilder"}}},s=n(t),r=n(e),c=0,l=function(t){return t&&t.hasOwnProperty&&t instanceof n},u=function(){return t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||function(e){return t.setTimeout(e,1e3/60)}}(),d=function(){var t,n=e.createElement("fakeelement"),i={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(t in i)if(n.style[t]!==o)return i[t]}(),f=function(t){return t&&t.length&&t[0].offsetHeight},h=function(t,o,i){var s=this;s.opts=n.extend(!0,{index:i},a,o||{}),o&&n.isArray(o.buttons)&&(s.opts.buttons=o.buttons),s.id=s.opts.id||++c,s.group=[],s.currIndex=parseInt(s.opts.index,10)||0,s.prevIndex=null,s.prevPos=null,s.currPos=0,s.firstRun=null,s.createGroup(t),s.group.length&&(s.$lastFocus=n(e.activeElement).blur(),s.slides={},s.init(t))};n.extend(h.prototype,{init:function(){var t,e,o,i=this,a=i.group[i.currIndex].opts;i.scrollTop=r.scrollTop(),i.scrollLeft=r.scrollLeft(),n.fancybox.getInstance()||n.fancybox.isMobile||"hidden"===n("body").css("overflow")||(t=n("body").width(),n("html").addClass("fancybox-enabled"),t=n("body").width()-t,t>1&&n("head").append('<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar, .fancybox-enabled body { margin-right: '+t+"px; }</style>")),o="",n.each(a.buttons,function(t,e){o+=a.btnTpl[e]||""}),e=n(i.translate(i,a.baseTpl.replace("{{BUTTONS}}",o))).addClass("fancybox-is-hidden").attr("id","fancybox-container-"+i.id).addClass(a.baseClass).data("FancyBox",i).prependTo(a.parentEl),i.$refs={container:e},["bg","inner","infobar","toolbar","stage","caption"].forEach(function(t){i.$refs[t]=e.find(".fancybox-"+t)}),(!a.arrows||i.group.length<2)&&e.find(".fancybox-navigation").remove(),a.infobar||i.$refs.infobar.remove(),a.toolbar||i.$refs.toolbar.remove(),i.trigger("onInit"),i.activate(),i.jumpTo(i.currIndex)},translate:function(t,e){var n=t.opts.i18n[t.opts.lang];return e.replace(/\{\{(\w+)\}\}/g,function(t,e){var i=n[e];return i===o?t:i})},createGroup:function(t){var e=this,i=n.makeArray(t);n.each(i,function(t,i){var a,s,r,c,l={},u={},d=[];n.isPlainObject(i)?(l=i,u=i.opts||i):"object"===n.type(i)&&n(i).length?(a=n(i),d=a.data(),u="options"in d?d.options:{},u="object"===n.type(u)?u:{},l.src="src"in d?d.src:u.src||a.attr("href"),["width","height","thumb","type","filter"].forEach(function(t){t in d&&(u[t]=d[t])}),"srcset"in d&&(u.image={srcset:d.srcset}),u.$orig=a,l.type||l.src||(l.type="inline",l.src=i)):l={type:"html",src:i+""},l.opts=n.extend(!0,{},e.opts,u),n.fancybox.isMobile&&(l.opts=n.extend(!0,{},l.opts,l.opts.mobile)),s=l.type||l.opts.type,r=l.src||"",!s&&r&&(r.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i)?s="image":r.match(/\.(pdf)((\?|#).*)?$/i)?s="pdf":"#"===r.charAt(0)&&(s="inline")),l.type=s,l.index=e.group.length,l.opts.$orig&&!l.opts.$orig.length&&delete l.opts.$orig,!l.opts.$thumb&&l.opts.$orig&&(l.opts.$thumb=l.opts.$orig.find("img:first")),l.opts.$thumb&&!l.opts.$thumb.length&&delete l.opts.$thumb,"function"===n.type(l.opts.caption)?l.opts.caption=l.opts.caption.apply(i,[e,l]):"caption"in d&&(l.opts.caption=d.caption),l.opts.caption=l.opts.caption===o?"":l.opts.caption+"","ajax"===s&&(c=r.split(/\s+/,2),c.length>1&&(l.src=c.shift(),l.opts.filter=c.shift())),"auto"==l.opts.smallBtn&&(n.inArray(s,["html","inline","ajax"])>-1?(l.opts.toolbar=!1,l.opts.smallBtn=!0):l.opts.smallBtn=!1),"pdf"===s&&(l.type="iframe",l.opts.iframe.preload=!1),l.opts.modal&&(l.opts=n.extend(!0,l.opts,{infobar:0,toolbar:0,smallBtn:0,keyboard:0,slideShow:0,fullScreen:0,thumbs:0,touch:0,clickContent:!1,clickSlide:!1,clickOutside:!1,dblclickContent:!1,dblclickSlide:!1,dblclickOutside:!1})),e.group.push(l)})},addEvents:function(){var o=this;o.removeEvents(),o.$refs.container.on("click.fb-close","[data-fancybox-close]",function(t){t.stopPropagation(),t.preventDefault(),o.close(t)}).on("click.fb-prev touchend.fb-prev","[data-fancybox-prev]",function(t){t.stopPropagation(),t.preventDefault(),o.previous()}).on("click.fb-next touchend.fb-next","[data-fancybox-next]",function(t){t.stopPropagation(),t.preventDefault(),o.next()}),s.on("orientationchange.fb resize.fb",function(t){t&&t.originalEvent&&"resize"===t.originalEvent.type?u(function(){o.update()}):(o.$refs.stage.hide(),setTimeout(function(){o.$refs.stage.show(),o.update()},500))}),r.on("focusin.fb",function(t){var i=n.fancybox?n.fancybox.getInstance():null;i.isClosing||!i.current||!i.current.opts.trapFocus||n(t.target).hasClass("fancybox-container")||n(t.target).is(e)||i&&"fixed"!==n(t.target).css("position")&&!i.$refs.container.has(t.target).length&&(t.stopPropagation(),i.focus(),s.scrollTop(o.scrollTop).scrollLeft(o.scrollLeft))}),r.on("keydown.fb",function(t){var e=o.current,i=t.keyCode||t.which;if(e&&e.opts.keyboard&&!n(t.target).is("input")&&!n(t.target).is("textarea"))return 8===i||27===i?(t.preventDefault(),void o.close(t)):37===i||38===i?(t.preventDefault(),void o.previous()):39===i||40===i?(t.preventDefault(),void o.next()):void o.trigger("afterKeydown",t,i)}),o.group[o.currIndex].opts.idleTime&&(o.idleSecondsCounter=0,r.on("mousemove.fb-idle mouseenter.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle",function(){o.idleSecondsCounter=0,o.isIdle&&o.showControls(),o.isIdle=!1}),o.idleInterval=t.setInterval(function(){o.idleSecondsCounter++,o.idleSecondsCounter>=o.group[o.currIndex].opts.idleTime&&(o.isIdle=!0,o.idleSecondsCounter=0,o.hideControls())},1e3))},removeEvents:function(){var e=this;s.off("orientationchange.fb resize.fb"),r.off("focusin.fb keydown.fb .fb-idle"),this.$refs.container.off(".fb-close .fb-prev .fb-next"),e.idleInterval&&(t.clearInterval(e.idleInterval),e.idleInterval=null)},previous:function(t){return this.jumpTo(this.currPos-1,t)},next:function(t){return this.jumpTo(this.currPos+1,t)},jumpTo:function(t,e,i){var a,s,r,c,l,u,d,h=this,p=h.group.length;if(!(h.isSliding||h.isClosing||h.isAnimating&&h.firstRun)){if(t=parseInt(t,10),s=h.current?h.current.opts.loop:h.opts.loop,!s&&(t<0||t>=p))return!1;if(a=h.firstRun=null===h.firstRun,!(p<2&&!a&&h.isSliding)){if(c=h.current,h.prevIndex=h.currIndex,h.prevPos=h.currPos,r=h.createSlide(t),p>1&&((s||r.index>0)&&h.createSlide(t-1),(s||r.index<p-1)&&h.createSlide(t+1)),h.current=r,h.currIndex=r.index,h.currPos=r.pos,h.trigger("beforeShow",a),h.updateControls(),u=n.fancybox.getTranslate(r.$slide),r.isMoved=(0!==u.left||0!==u.top)&&!r.$slide.hasClass("fancybox-animated"),r.forcedDuration=o,n.isNumeric(e)?r.forcedDuration=e:e=r.opts[a?"animationDuration":"transitionDuration"],e=parseInt(e,10),a)return r.opts.animationEffect&&e&&h.$refs.container.css("transition-duration",e+"ms"),h.$refs.container.removeClass("fancybox-is-hidden"),f(h.$refs.container),h.$refs.container.addClass("fancybox-is-open"),r.$slide.addClass("fancybox-slide--current"),h.loadSlide(r),void h.preload();n.each(h.slides,function(t,e){n.fancybox.stop(e.$slide)}),r.$slide.removeClass("fancybox-slide--next fancybox-slide--previous").addClass("fancybox-slide--current"),r.isMoved?(l=Math.round(r.$slide.width()),n.each(h.slides,function(t,o){var i=o.pos-r.pos;n.fancybox.animate(o.$slide,{top:0,left:i*l+i*o.opts.gutter},e,function(){o.$slide.removeAttr("style").removeClass("fancybox-slide--next fancybox-slide--previous"),o.pos===h.currPos&&(r.isMoved=!1,h.complete())})})):h.$refs.stage.children().removeAttr("style"),r.isLoaded?h.revealContent(r):h.loadSlide(r),h.preload(),c.pos!==r.pos&&(d="fancybox-slide--"+(c.pos>r.pos?"next":"previous"),c.$slide.removeClass("fancybox-slide--complete fancybox-slide--current fancybox-slide--next fancybox-slide--previous"),c.isComplete=!1,e&&(r.isMoved||r.opts.transitionEffect)&&(r.isMoved?c.$slide.addClass(d):(d="fancybox-animated "+d+" fancybox-fx-"+r.opts.transitionEffect,n.fancybox.animate(c.$slide,d,e,function(){c.$slide.removeClass(d).removeAttr("style")}))))}}},createSlide:function(t){var e,o,i=this;return o=t%i.group.length,o=o<0?i.group.length+o:o,!i.slides[t]&&i.group[o]&&(e=n('<div class="fancybox-slide"></div>').appendTo(i.$refs.stage),i.slides[t]=n.extend(!0,{},i.group[o],{pos:t,$slide:e,isLoaded:!1}),i.updateSlide(i.slides[t])),i.slides[t]},scaleToActual:function(t,e,i){var a,s,r,c,l,u=this,d=u.current,f=d.$content,h=parseInt(d.$slide.width(),10),p=parseInt(d.$slide.height(),10),g=d.width,b=d.height;"image"!=d.type||d.hasError||!f||u.isAnimating||(n.fancybox.stop(f),u.isAnimating=!0,t=t===o?.5*h:t,e=e===o?.5*p:e,a=n.fancybox.getTranslate(f),c=g/a.width,l=b/a.height,s=.5*h-.5*g,r=.5*p-.5*b,g>h&&(s=a.left*c-(t*c-t),s>0&&(s=0),s<h-g&&(s=h-g)),b>p&&(r=a.top*l-(e*l-e),r>0&&(r=0),r<p-b&&(r=p-b)),u.updateCursor(g,b),n.fancybox.animate(f,{top:r,left:s,scaleX:c,scaleY:l},i||330,function(){u.isAnimating=!1}),u.SlideShow&&u.SlideShow.isActive&&u.SlideShow.stop())},scaleToFit:function(t){var e,o=this,i=o.current,a=i.$content;"image"!=i.type||i.hasError||!a||o.isAnimating||(n.fancybox.stop(a),o.isAnimating=!0,e=o.getFitPos(i),o.updateCursor(e.width,e.height),n.fancybox.animate(a,{top:e.top,left:e.left,scaleX:e.width/a.width(),scaleY:e.height/a.height()},t||330,function(){o.isAnimating=!1}))},getFitPos:function(t){var e,o,i,a,r,c=this,l=t.$content,u=t.width,d=t.height,f=t.opts.margin;return!(!l||!l.length||!u&&!d)&&("number"===n.type(f)&&(f=[f,f]),2==f.length&&(f=[f[0],f[1],f[0],f[1]]),s.width()<800&&(f=[0,0,0,0]),e=parseInt(c.$refs.stage.width(),10)-(f[1]+f[3]),o=parseInt(c.$refs.stage.height(),10)-(f[0]+f[2]),i=Math.min(1,e/u,o/d),a=Math.floor(i*u),r=Math.floor(i*d),{top:Math.floor(.5*(o-r))+f[0],left:Math.floor(.5*(e-a))+f[3],width:a,height:r})},update:function(){var t=this;n.each(t.slides,function(e,n){t.updateSlide(n)})},updateSlide:function(t){var e=this,o=t.$content;o&&(t.width||t.height)&&(n.fancybox.stop(o),n.fancybox.setTranslate(o,e.getFitPos(t)),t.pos===e.currPos&&e.updateCursor()),t.$slide.trigger("refresh"),e.trigger("onUpdate",t)},updateCursor:function(t,e){var n,i=this,a=i.$refs.container.removeClass("fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-drag fancybox-can-zoomOut");i.current&&!i.isClosing&&(i.isZoomable()?(a.addClass("fancybox-is-zoomable"),n=t!==o&&e!==o?t<i.current.width&&e<i.current.height:i.isScaledDown(),n?a.addClass("fancybox-can-zoomIn"):i.current.opts.touch?a.addClass("fancybox-can-drag"):a.addClass("fancybox-can-zoomOut")):i.current.opts.touch&&a.addClass("fancybox-can-drag"))},isZoomable:function(){var t,e=this,o=e.current;if(o&&!e.isClosing)return!!("image"===o.type&&o.isLoaded&&!o.hasError&&("zoom"===o.opts.clickContent||n.isFunction(o.opts.clickContent)&&"zoom"===o.opts.clickContent(o))&&(t=e.getFitPos(o),o.width>t.width||o.height>t.height))},isScaledDown:function(){var t=this,e=t.current,o=e.$content,i=!1;return o&&(i=n.fancybox.getTranslate(o),i=i.width<e.width||i.height<e.height),i},canPan:function(){var t=this,e=t.current,n=e.$content,o=!1;return n&&(o=t.getFitPos(e),o=Math.abs(n.width()-o.width)>1||Math.abs(n.height()-o.height)>1),o},loadSlide:function(t){var e,o,i,a=this;if(!t.isLoading&&!t.isLoaded){switch(t.isLoading=!0,a.trigger("beforeLoad",t),e=t.type,o=t.$slide,o.off("refresh").trigger("onReset").addClass("fancybox-slide--"+(e||"unknown")).addClass(t.opts.slideClass),e){case"image":a.setImage(t);break;case"iframe":a.setIframe(t);break;case"html":a.setContent(t,t.src||t.content);break;case"inline":n(t.src).length?a.setContent(t,n(t.src)):a.setError(t);break;case"ajax":a.showLoading(t),i=n.ajax(n.extend({},t.opts.ajax.settings,{url:t.src,success:function(e,n){"success"===n&&a.setContent(t,e)},error:function(e,n){e&&"abort"!==n&&a.setError(t)}})),o.one("onReset",function(){i.abort()});break;default:a.setError(t)}return!0}},setImage:function(e){var o,i,a,s,r=this,c=e.opts.image.srcset;if(c){a=t.devicePixelRatio||1,s=t.innerWidth*a,i=c.split(",").map(function(t){var e={};return t.trim().split(/\s+/).forEach(function(t,n){var o=parseInt(t.substring(0,t.length-1),10);return 0===n?e.url=t:void(o&&(e.value=o,e.postfix=t[t.length-1]))}),e}),i.sort(function(t,e){return t.value-e.value});for(var l=0;l<i.length;l++){var u=i[l];if("w"===u.postfix&&u.value>=s||"x"===u.postfix&&u.value>=a){o=u;break}}!o&&i.length&&(o=i[i.length-1]),o&&(e.src=o.url,e.width&&e.height&&"w"==o.postfix&&(e.height=e.width/e.height*o.value,e.width=o.value))}e.$content=n('<div class="fancybox-image-wrap"></div>').addClass("fancybox-is-hidden").appendTo(e.$slide),e.opts.preload!==!1&&e.opts.width&&e.opts.height&&(e.opts.thumb||e.opts.$thumb)?(e.width=e.opts.width,e.height=e.opts.height,e.$ghost=n("<img />").one("error",function(){n(this).remove(),e.$ghost=null,r.setBigImage(e)}).one("load",function(){r.afterLoad(e),r.setBigImage(e)}).addClass("fancybox-image").appendTo(e.$content).attr("src",e.opts.thumb||e.opts.$thumb.attr("src"))):r.setBigImage(e)},setBigImage:function(t){var e=this,o=n("<img />");t.$image=o.one("error",function(){e.setError(t)}).one("load",function(){clearTimeout(t.timouts),t.timouts=null,e.isClosing||(t.width=this.naturalWidth,t.height=this.naturalHeight,t.opts.image.srcset&&o.attr("sizes","100vw").attr("srcset",t.opts.image.srcset),e.hideLoading(t),t.$ghost?t.timouts=setTimeout(function(){t.timouts=null,t.$ghost.hide()},Math.min(300,Math.max(1e3,t.height/1600))):e.afterLoad(t))}).addClass("fancybox-image").attr("src",t.src).appendTo(t.$content),o[0].complete?o.trigger("load"):o[0].error?o.trigger("error"):t.timouts=setTimeout(function(){o[0].complete||t.hasError||e.showLoading(t)},100)},setIframe:function(t){var e,i=this,a=t.opts.iframe,s=t.$slide;t.$content=n('<div class="fancybox-content'+(a.preload?" fancybox-is-hidden":"")+'"></div>').css(a.css).appendTo(s),e=n(a.tpl.replace(/\{rnd\}/g,(new Date).getTime())).attr(a.attr).appendTo(t.$content),a.preload?(i.showLoading(t),e.on("load.fb error.fb",function(e){this.isReady=1,t.$slide.trigger("refresh"),i.afterLoad(t)}),s.on("refresh.fb",function(){var n,i,s,r,c,l=t.$content;if(1===e[0].isReady){try{n=e.contents(),i=n.find("body")}catch(t){}i&&i.length&&(a.css.width===o||a.css.height===o)&&(s=e[0].contentWindow.document.documentElement.scrollWidth,r=Math.ceil(i.outerWidth(!0)+(l.width()-s)),c=Math.ceil(i.outerHeight(!0)),l.css({width:a.css.width===o?r+(l.outerWidth()-l.innerWidth()):a.css.width,height:a.css.height===o?c+(l.outerHeight()-l.innerHeight()):a.css.height})),l.removeClass("fancybox-is-hidden")}})):this.afterLoad(t),e.attr("src",t.src),t.opts.smallBtn===!0&&t.$content.prepend(i.translate(t,t.opts.btnTpl.smallBtn)),s.one("onReset",function(){try{n(this).find("iframe").hide().attr("src","//about:blank")}catch(t){}n(this).empty(),t.isLoaded=!1})},setContent:function(t,e){var o=this;o.isClosing||(o.hideLoading(t),t.$slide.empty(),l(e)&&e.parent().length?(e.parent(".fancybox-slide--inline").trigger("onReset"),t.$placeholder=n("<div></div>").hide().insertAfter(e),e.css("display","inline-block")):t.hasError||("string"===n.type(e)&&(e=n("<div>").append(n.trim(e)).contents(),3===e[0].nodeType&&(e=n("<div>").html(e))),t.opts.filter&&(e=n("<div>").html(e).find(t.opts.filter))),t.$slide.one("onReset",function(){t.$placeholder&&(t.$placeholder.after(e.hide()).remove(),t.$placeholder=null),t.$smallBtn&&(t.$smallBtn.remove(),t.$smallBtn=null),t.hasError||(n(this).empty(),t.isLoaded=!1)}),t.$content=n(e).appendTo(t.$slide),t.opts.smallBtn&&!t.$smallBtn&&(t.$smallBtn=n(o.translate(t,t.opts.btnTpl.smallBtn)).appendTo(t.$content)),this.afterLoad(t))},setError:function(t){t.hasError=!0,t.$slide.removeClass("fancybox-slide--"+t.type),this.setContent(t,this.translate(t,t.opts.errorTpl))},showLoading:function(t){var e=this;t=t||e.current,t&&!t.$spinner&&(t.$spinner=n(e.opts.spinnerTpl).appendTo(t.$slide))},hideLoading:function(t){var e=this;t=t||e.current,t&&t.$spinner&&(t.$spinner.remove(),delete t.$spinner)},afterLoad:function(t){var e=this;e.isClosing||(t.isLoading=!1,t.isLoaded=!0,e.trigger("afterLoad",t),e.hideLoading(t),t.opts.protect&&t.$content&&!t.hasError&&(t.$content.on("contextmenu.fb",function(t){return 2==t.button&&t.preventDefault(),!0}),"image"===t.type&&n('<div class="fancybox-spaceball"></div>').appendTo(t.$content)),e.revealContent(t))},revealContent:function(t){var e,i,a,s,r,c=this,l=t.$slide,u=!1;return e=t.opts[c.firstRun?"animationEffect":"transitionEffect"],a=t.opts[c.firstRun?"animationDuration":"transitionDuration"],a=parseInt(t.forcedDuration===o?a:t.forcedDuration,10),!t.isMoved&&t.pos===c.currPos&&a||(e=!1),"zoom"!==e||t.pos===c.currPos&&a&&"image"===t.type&&!t.hasError&&(u=c.getThumbPos(t))||(e="fade"),"zoom"===e?(r=c.getFitPos(t),r.scaleX=r.width/u.width,r.scaleY=r.height/u.height,delete r.width,delete r.height,s=t.opts.zoomOpacity,"auto"==s&&(s=Math.abs(t.width/t.height-u.width/u.height)>.1),s&&(u.opacity=.1,r.opacity=1),n.fancybox.setTranslate(t.$content.removeClass("fancybox-is-hidden"),u),f(t.$content),void n.fancybox.animate(t.$content,r,a,function(){c.complete()})):(c.updateSlide(t),e?(n.fancybox.stop(l),i="fancybox-animated fancybox-slide--"+(t.pos>c.prevPos?"next":"previous")+" fancybox-fx-"+e,l.removeAttr("style").removeClass("fancybox-slide--current fancybox-slide--next fancybox-slide--previous").addClass(i),t.$content.removeClass("fancybox-is-hidden"),f(l),void n.fancybox.animate(l,"fancybox-slide--current",a,function(e){l.removeClass(i).removeAttr("style"),t.pos===c.currPos&&c.complete()},!0)):(f(l),t.$content.removeClass("fancybox-is-hidden"),void(t.pos===c.currPos&&c.complete())))},getThumbPos:function(o){var i,a=this,s=!1,r=function(e){for(var o,i=e[0],a=i.getBoundingClientRect(),s=[];null!==i.parentElement;)"hidden"!==n(i.parentElement).css("overflow")&&"auto"!==n(i.parentElement).css("overflow")||s.push(i.parentElement.getBoundingClientRect()),i=i.parentElement;return o=s.every(function(t){var e=Math.min(a.right,t.right)-Math.max(a.left,t.left),n=Math.min(a.bottom,t.bottom)-Math.max(a.top,t.top);return e>0&&n>0}),o&&a.bottom>0&&a.right>0&&a.left<n(t).width()&&a.top<n(t).height()},c=o.opts.$thumb,l=c?c.offset():0;return l&&c[0].ownerDocument===e&&r(c)&&(i=a.$refs.stage.offset(),s={top:l.top-i.top+parseFloat(c.css("border-top-width")||0),left:l.left-i.left+parseFloat(c.css("border-left-width")||0),width:c.width(),height:c.height(),scaleX:1,scaleY:1}),s},complete:function(){var t=this,o=t.current,i={};o.isMoved||!o.isLoaded||o.isComplete||(o.isComplete=!0,o.$slide.siblings().trigger("onReset"),f(o.$slide),o.$slide.addClass("fancybox-slide--complete"),n.each(t.slides,function(e,o){o.pos>=t.currPos-1&&o.pos<=t.currPos+1?i[o.pos]=o:o&&(n.fancybox.stop(o.$slide),o.$slide.unbind().remove())}),t.slides=i,t.updateCursor(),t.trigger("afterShow"),(n(e.activeElement).is("[disabled]")||o.opts.autoFocus&&"image"!=o.type&&"iframe"!==o.type)&&t.focus())},preload:function(){var t,e,n=this;n.group.length<2||(t=n.slides[n.currPos+1],e=n.slides[n.currPos-1],t&&"image"===t.type&&n.loadSlide(t),e&&"image"===e.type&&n.loadSlide(e))},focus:function(){var t,e=this.current;this.isClosing||(t=e&&e.isComplete?e.$slide.find("button,:input,[tabindex],a").filter(":not([disabled]):visible:first"):null,t=t&&t.length?t:this.$refs.container,t.focus())},activate:function(){var t=this;n(".fancybox-container").each(function(){var e=n(this).data("FancyBox");e&&e.uid!==t.uid&&!e.isClosing&&e.trigger("onDeactivate")}),t.current&&(t.$refs.container.index()>0&&t.$refs.container.prependTo(e.body),t.updateControls()),t.trigger("onActivate"),t.addEvents()},close:function(t,e){var o,i,a,s,r,c,l=this,f=l.current,h=function(){l.cleanUp(t)};return!l.isClosing&&(l.isClosing=!0,l.trigger("beforeClose",t)===!1?(l.isClosing=!1,u(function(){l.update()}),!1):(l.removeEvents(),f.timouts&&clearTimeout(f.timouts),a=f.$content,o=f.opts.animationEffect,i=n.isNumeric(e)?e:o?f.opts.animationDuration:0,f.$slide.off(d).removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated"),f.$slide.siblings().trigger("onReset").remove(),i&&l.$refs.container.removeClass("fancybox-is-open").addClass("fancybox-is-closing"),l.hideLoading(f),l.hideControls(),l.updateCursor(),"zoom"!==o||t!==!0&&a&&i&&"image"===f.type&&!f.hasError&&(c=l.getThumbPos(f))||(o="fade"),"zoom"===o?(n.fancybox.stop(a),r=n.fancybox.getTranslate(a),r.width=r.width*r.scaleX,r.height=r.height*r.scaleY,s=f.opts.zoomOpacity,"auto"==s&&(s=Math.abs(f.width/f.height-c.width/c.height)>.1),s&&(c.opacity=0),r.scaleX=r.width/c.width,r.scaleY=r.height/c.height,r.width=c.width,r.height=c.height,n.fancybox.setTranslate(f.$content,r),n.fancybox.animate(f.$content,c,i,h),!0):(o&&i?t===!0?setTimeout(h,i):n.fancybox.animate(f.$slide.removeClass("fancybox-slide--current"),"fancybox-animated fancybox-slide--previous fancybox-fx-"+o,i,h):h(),!0)))},cleanUp:function(t){var e,o=this;o.current.$slide.trigger("onReset"),o.$refs.container.empty().remove(),o.trigger("afterClose",t),o.$lastFocus&&o.current.opts.backFocus&&o.$lastFocus.focus(),o.current=null,e=n.fancybox.getInstance(),e?e.activate():(s.scrollTop(o.scrollTop).scrollLeft(o.scrollLeft),n("html").removeClass("fancybox-enabled"),n("#fancybox-style-noscroll").remove())},trigger:function(t,e){var o,i=Array.prototype.slice.call(arguments,1),a=this,s=e&&e.opts?e:a.current;return s?i.unshift(s):s=a,i.unshift(a),n.isFunction(s.opts[t])&&(o=s.opts[t].apply(s,i)),o===!1?o:void("afterClose"===t?r.trigger(t+".fb",i):a.$refs.container.trigger(t+".fb",i))},updateControls:function(t){var e=this,o=e.current,i=o.index,a=o.opts,s=a.caption,r=e.$refs.caption;o.$slide.trigger("refresh"),e.$caption=s&&s.length?r.html(s):null,e.isHiddenControls||e.showControls(),n("[data-fancybox-count]").html(e.group.length),n("[data-fancybox-index]").html(i+1),n("[data-fancybox-prev]").prop("disabled",!a.loop&&i<=0),n("[data-fancybox-next]").prop("disabled",!a.loop&&i>=e.group.length-1)},hideControls:function(){this.isHiddenControls=!0,this.$refs.container.removeClass("fancybox-show-infobar fancybox-show-toolbar fancybox-show-caption fancybox-show-nav")},showControls:function(){var t=this,e=t.current?t.current.opts:t.opts,n=t.$refs.container;t.isHiddenControls=!1,t.idleSecondsCounter=0,n.toggleClass("fancybox-show-toolbar",!(!e.toolbar||!e.buttons)).toggleClass("fancybox-show-infobar",!!(e.infobar&&t.group.length>1)).toggleClass("fancybox-show-nav",!!(e.arrows&&t.group.length>1)).toggleClass("fancybox-is-modal",!!e.modal),t.$caption?n.addClass("fancybox-show-caption "):n.removeClass("fancybox-show-caption")},toggleControls:function(){this.isHiddenControls?this.showControls():this.hideControls()}}),n.fancybox={version:"3.1.24",defaults:a,getInstance:function(t){var e=n('.fancybox-container:not(".fancybox-is-closing"):first').data("FancyBox"),o=Array.prototype.slice.call(arguments,1);return e instanceof h&&("string"===n.type(t)?e[t].apply(e,o):"function"===n.type(t)&&t.apply(e,o),e)},open:function(t,e,n){return new h(t,e,n)},close:function(t){var e=this.getInstance();e&&(e.close(),t===!0&&this.close())},destroy:function(){this.close(!0),r.off("click.fb-start")},isMobile:e.createTouch!==o&&/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent),use3d:function(){var n=e.createElement("div");return t.getComputedStyle&&t.getComputedStyle(n).getPropertyValue("transform")&&!(e.documentMode&&e.documentMode<11)}(),getTranslate:function(t){var e;if(!t||!t.length)return!1;if(e=t.eq(0).css("transform"),e&&e.indexOf("matrix")!==-1?(e=e.split("(")[1],e=e.split(")")[0],e=e.split(",")):e=[],e.length)e=e.length>10?[e[13],e[12],e[0],e[5]]:[e[5],e[4],e[0],e[3]],e=e.map(parseFloat);else{e=[0,0,1,1];var n=/\.*translate\((.*)px,(.*)px\)/i,o=n.exec(t.eq(0).attr("style"));o&&(e[0]=parseFloat(o[2]),e[1]=parseFloat(o[1]))}return{top:e[0],left:e[1],scaleX:e[2],scaleY:e[3],opacity:parseFloat(t.css("opacity")),width:t.width(),height:t.height()}},setTranslate:function(t,e){var n="",i={};if(t&&e)return e.left===o&&e.top===o||(n=(e.left===o?t.position().left:e.left)+"px, "+(e.top===o?t.position().top:e.top)+"px",n=this.use3d?"translate3d("+n+", 0px)":"translate("+n+")"),e.scaleX!==o&&e.scaleY!==o&&(n=(n.length?n+" ":"")+"scale("+e.scaleX+", "+e.scaleY+")"),n.length&&(i.transform=n),e.opacity!==o&&(i.opacity=e.opacity),e.width!==o&&(i.width=e.width),e.height!==o&&(i.height=e.height),t.css(i)},animate:function(t,e,i,a,s){var r=d||"transitionend";n.isFunction(i)&&(a=i,i=null),n.isPlainObject(e)||t.removeAttr("style"),t.on(r,function(i){(!i||!i.originalEvent||t.is(i.originalEvent.target)&&"z-index"!=i.originalEvent.propertyName)&&(t.off(r),n.isPlainObject(e)?e.scaleX!==o&&e.scaleY!==o&&(t.css("transition-duration","0ms"),e.width=Math.round(t.width()*e.scaleX),e.height=Math.round(t.height()*e.scaleY),e.scaleX=1,e.scaleY=1,n.fancybox.setTranslate(t,e)):s!==!0&&t.removeClass(e),n.isFunction(a)&&a(i))}),n.isNumeric(i)&&t.css("transition-duration",i+"ms"),n.isPlainObject(e)?n.fancybox.setTranslate(t,e):t.addClass(e),t.data("timer",setTimeout(function(){t.trigger("transitionend")},i+16))},stop:function(t){clearTimeout(t.data("timer")),t.off(d)}},n.fn.fancybox=function(t){var e;return t=t||{},e=t.selector||!1,e?n("body").off("click.fb-start",e).on("click.fb-start",e,{options:t},i):this.off("click.fb-start").on("click.fb-start",{items:this,options:t},i),this},r.on("click.fb-start","[data-fancybox]",i)}}(window,document,window.jQuery),function(t){"use strict";var e=function(e,n,o){if(e)return o=o||"","object"===t.type(o)&&(o=t.param(o,!0)),t.each(n,function(t,n){e=e.replace("$"+t,n||"")}),o.length&&(e+=(e.indexOf("?")>0?"&":"?")+o),e},n={youtube:{matcher:/(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,params:{autoplay:1,autohide:1,fs:1,rel:0,hd:1,wmode:"transparent",enablejsapi:1,html5:1},paramPlace:8,type:"iframe",url:"//www.youtube.com/embed/$4",thumb:"//img.youtube.com/vi/$4/hqdefault.jpg"},vimeo:{matcher:/^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,params:{autoplay:1,hd:1,show_title:1,show_byline:1,show_portrait:0,fullscreen:1,api:1},paramPlace:3,type:"iframe",url:"//player.vimeo.com/video/$2"},metacafe:{matcher:/metacafe.com\/watch\/(\d+)\/(.*)?/,type:"iframe",url:"//www.metacafe.com/embed/$1/?ap=1"},dailymotion:{matcher:/dailymotion.com\/video\/(.*)\/?(.*)/,params:{additionalInfos:0,autoStart:1},type:"iframe",url:"//www.dailymotion.com/embed/video/$1"},vine:{matcher:/vine.co\/v\/([a-zA-Z0-9\?\=\-]+)/,type:"iframe",url:"//vine.co/v/$1/embed/simple"},instagram:{matcher:/(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,type:"image",url:"//$1/p/$2/media/?size=l"},gmap_place:{matcher:/(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,type:"iframe",url:function(t){return"//maps.google."+t[2]+"/?ll="+(t[9]?t[9]+"&z="+Math.floor(t[10])+(t[12]?t[12].replace(/^\//,"&"):""):t[12])+"&output="+(t[12]&&t[12].indexOf("layer=c")>0?"svembed":"embed")}},gmap_search:{matcher:/(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,type:"iframe",url:function(t){return"//maps.google."+t[2]+"/maps?q="+t[5].replace("query=","q=").replace("api=1","")+"&output=embed"}}};t(document).on("onInit.fb",function(o,i){t.each(i.group,function(o,i){var a,s,r,c,l,u,d,f=i.src||"",h=!1;i.type||(a=t.extend(!0,{},n,i.opts.media),t.each(a,function(n,o){if(r=f.match(o.matcher),u={},d=n,r){if(h=o.type,o.paramPlace&&r[o.paramPlace]){l=r[o.paramPlace],"?"==l[0]&&(l=l.substring(1)),l=l.split("&");for(var a=0;a<l.length;++a){var p=l[a].split("=",2);2==p.length&&(u[p[0]]=decodeURIComponent(p[1].replace(/\+/g," ")))}}return c=t.extend(!0,{},o.params,i.opts[n],u),f="function"===t.type(o.url)?o.url.call(this,r,c,i):e(o.url,r,c),s="function"===t.type(o.thumb)?o.thumb.call(this,r,c,i):e(o.thumb,r),"vimeo"===d&&(f=f.replace("&%23","#")),!1}}),h?(i.src=f,i.type=h,i.opts.thumb||i.opts.$thumb&&i.opts.$thumb.length||(i.opts.thumb=s),"iframe"===h&&(t.extend(!0,i.opts,{iframe:{preload:!1,attr:{scrolling:"no"}}}),i.contentProvider=d,
+i.opts.slideClass+=" fancybox-slide--"+("gmap_place"==d||"gmap_search"==d?"map":"video"))):i.type="image")})})}(window.jQuery),function(t,e,n){"use strict";var o=function(){return t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.oRequestAnimationFrame||function(e){return t.setTimeout(e,1e3/60)}}(),i=function(){return t.cancelAnimationFrame||t.webkitCancelAnimationFrame||t.mozCancelAnimationFrame||t.oCancelAnimationFrame||function(e){t.clearTimeout(e)}}(),a=function(e){var n=[];e=e.originalEvent||e||t.e,e=e.touches&&e.touches.length?e.touches:e.changedTouches&&e.changedTouches.length?e.changedTouches:[e];for(var o in e)e[o].pageX?n.push({x:e[o].pageX,y:e[o].pageY}):e[o].clientX&&n.push({x:e[o].clientX,y:e[o].clientY});return n},s=function(t,e,n){return e&&t?"x"===n?t.x-e.x:"y"===n?t.y-e.y:Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2)):0},r=function(t){if(t.is("a,button,input,select,textarea")||n.isFunction(t.get(0).onclick))return!0;for(var e=0,o=t[0].attributes,i=o.length;e<i;e++)if("data-fancybox-"===o[e].nodeName.substr(0,14))return!0;return!1},c=function(e){var n=t.getComputedStyle(e)["overflow-y"],o=t.getComputedStyle(e)["overflow-x"],i=("scroll"===n||"auto"===n)&&e.scrollHeight>e.clientHeight,a=("scroll"===o||"auto"===o)&&e.scrollWidth>e.clientWidth;return i||a},l=function(t){for(var e=!1;;){if(e=c(t.get(0)))break;if(t=t.parent(),!t.length||t.hasClass("fancybox-stage")||t.is("body"))break}return e},u=function(t){var e=this;e.instance=t,e.$bg=t.$refs.bg,e.$stage=t.$refs.stage,e.$container=t.$refs.container,e.destroy(),e.$container.on("touchstart.fb.touch mousedown.fb.touch",n.proxy(e,"ontouchstart"))};u.prototype.destroy=function(){this.$container.off(".fb.touch")},u.prototype.ontouchstart=function(o){var i=this,c=n(o.target),u=i.instance,d=u.current,f=d.$content,h="touchstart"==o.type;if(h&&i.$container.off("mousedown.fb.touch"),!d||i.instance.isAnimating||i.instance.isClosing)return o.stopPropagation(),void o.preventDefault();if((!o.originalEvent||2!=o.originalEvent.button)&&c.length&&!r(c)&&!r(c.parent())&&!(o.originalEvent.clientX>c[0].clientWidth+c.offset().left)&&(i.startPoints=a(o),i.startPoints&&!(i.startPoints.length>1&&u.isSliding))){if(i.$target=c,i.$content=f,i.canTap=!0,n(e).off(".fb.touch"),n(e).on(h?"touchend.fb.touch touchcancel.fb.touch":"mouseup.fb.touch mouseleave.fb.touch",n.proxy(i,"ontouchend")),n(e).on(h?"touchmove.fb.touch":"mousemove.fb.touch",n.proxy(i,"ontouchmove")),o.stopPropagation(),!u.current.opts.touch&&!u.canPan()||!c.is(i.$stage)&&!i.$stage.find(c).length)return void(c.is("img")&&o.preventDefault());n.fancybox.isMobile&&(l(i.$target)||l(i.$target.parent()))||o.preventDefault(),i.canvasWidth=Math.round(d.$slide[0].clientWidth),i.canvasHeight=Math.round(d.$slide[0].clientHeight),i.startTime=(new Date).getTime(),i.distanceX=i.distanceY=i.distance=0,i.isPanning=!1,i.isSwiping=!1,i.isZooming=!1,i.sliderStartPos=i.sliderLastPos||{top:0,left:0},i.contentStartPos=n.fancybox.getTranslate(i.$content),i.contentLastPos=null,1!==i.startPoints.length||i.isZooming||(i.canTap=!u.isSliding,"image"===d.type&&(i.contentStartPos.width>i.canvasWidth+1||i.contentStartPos.height>i.canvasHeight+1)?(n.fancybox.stop(i.$content),i.$content.css("transition-duration","0ms"),i.isPanning=!0):i.isSwiping=!0,i.$container.addClass("fancybox-controls--isGrabbing")),2!==i.startPoints.length||u.isAnimating||d.hasError||"image"!==d.type||!d.isLoaded&&!d.$ghost||(i.isZooming=!0,i.isSwiping=!1,i.isPanning=!1,n.fancybox.stop(i.$content),i.$content.css("transition-duration","0ms"),i.centerPointStartX=.5*(i.startPoints[0].x+i.startPoints[1].x)-n(t).scrollLeft(),i.centerPointStartY=.5*(i.startPoints[0].y+i.startPoints[1].y)-n(t).scrollTop(),i.percentageOfImageAtPinchPointX=(i.centerPointStartX-i.contentStartPos.left)/i.contentStartPos.width,i.percentageOfImageAtPinchPointY=(i.centerPointStartY-i.contentStartPos.top)/i.contentStartPos.height,i.startDistanceBetweenFingers=s(i.startPoints[0],i.startPoints[1]))}},u.prototype.ontouchmove=function(t){var e=this;if(e.newPoints=a(t),n.fancybox.isMobile&&(l(e.$target)||l(e.$target.parent())))return t.stopPropagation(),void(e.canTap=!1);if((e.instance.current.opts.touch||e.instance.canPan())&&e.newPoints&&e.newPoints.length&&(e.distanceX=s(e.newPoints[0],e.startPoints[0],"x"),e.distanceY=s(e.newPoints[0],e.startPoints[0],"y"),e.distance=s(e.newPoints[0],e.startPoints[0]),e.distance>0)){if(!e.$target.is(e.$stage)&&!e.$stage.find(e.$target).length)return;t.stopPropagation(),t.preventDefault(),e.isSwiping?e.onSwipe():e.isPanning?e.onPan():e.isZooming&&e.onZoom()}},u.prototype.onSwipe=function(){var e,a=this,s=a.isSwiping,r=a.sliderStartPos.left||0;s===!0?Math.abs(a.distance)>10&&(a.canTap=!1,a.instance.group.length<2&&a.instance.opts.touch.vertical?a.isSwiping="y":a.instance.isSliding||a.instance.opts.touch.vertical===!1||"auto"===a.instance.opts.touch.vertical&&n(t).width()>800?a.isSwiping="x":(e=Math.abs(180*Math.atan2(a.distanceY,a.distanceX)/Math.PI),a.isSwiping=e>45&&e<135?"y":"x"),a.instance.isSliding=a.isSwiping,a.startPoints=a.newPoints,n.each(a.instance.slides,function(t,e){n.fancybox.stop(e.$slide),e.$slide.css("transition-duration","0ms"),e.inTransition=!1,e.pos===a.instance.current.pos&&(a.sliderStartPos.left=n.fancybox.getTranslate(e.$slide).left)}),a.instance.SlideShow&&a.instance.SlideShow.isActive&&a.instance.SlideShow.stop()):("x"==s&&(a.distanceX>0&&(a.instance.group.length<2||0===a.instance.current.index&&!a.instance.current.opts.loop)?r+=Math.pow(a.distanceX,.8):a.distanceX<0&&(a.instance.group.length<2||a.instance.current.index===a.instance.group.length-1&&!a.instance.current.opts.loop)?r-=Math.pow(-a.distanceX,.8):r+=a.distanceX),a.sliderLastPos={top:"x"==s?0:a.sliderStartPos.top+a.distanceY,left:r},a.requestId&&(i(a.requestId),a.requestId=null),a.requestId=o(function(){a.sliderLastPos&&(n.each(a.instance.slides,function(t,e){var o=e.pos-a.instance.currPos;n.fancybox.setTranslate(e.$slide,{top:a.sliderLastPos.top,left:a.sliderLastPos.left+o*a.canvasWidth+o*e.opts.gutter})}),a.$container.addClass("fancybox-is-sliding"))}))},u.prototype.onPan=function(){var t,e,a,s=this;s.canTap=!1,t=s.contentStartPos.width>s.canvasWidth?s.contentStartPos.left+s.distanceX:s.contentStartPos.left,e=s.contentStartPos.top+s.distanceY,a=s.limitMovement(t,e,s.contentStartPos.width,s.contentStartPos.height),a.scaleX=s.contentStartPos.scaleX,a.scaleY=s.contentStartPos.scaleY,s.contentLastPos=a,s.requestId&&(i(s.requestId),s.requestId=null),s.requestId=o(function(){n.fancybox.setTranslate(s.$content,s.contentLastPos)})},u.prototype.limitMovement=function(t,e,n,o){var i,a,s,r,c=this,l=c.canvasWidth,u=c.canvasHeight,d=c.contentStartPos.left,f=c.contentStartPos.top,h=c.distanceX,p=c.distanceY;return i=Math.max(0,.5*l-.5*n),a=Math.max(0,.5*u-.5*o),s=Math.min(l-n,.5*l-.5*n),r=Math.min(u-o,.5*u-.5*o),n>l&&(h>0&&t>i&&(t=i-1+Math.pow(-i+d+h,.8)||0),h<0&&t<s&&(t=s+1-Math.pow(s-d-h,.8)||0)),o>u&&(p>0&&e>a&&(e=a-1+Math.pow(-a+f+p,.8)||0),p<0&&e<r&&(e=r+1-Math.pow(r-f-p,.8)||0)),{top:e,left:t}},u.prototype.limitPosition=function(t,e,n,o){var i=this,a=i.canvasWidth,s=i.canvasHeight;return n>a?(t=t>0?0:t,t=t<a-n?a-n:t):t=Math.max(0,a/2-n/2),o>s?(e=e>0?0:e,e=e<s-o?s-o:e):e=Math.max(0,s/2-o/2),{top:e,left:t}},u.prototype.onZoom=function(){var e=this,a=e.contentStartPos.width,r=e.contentStartPos.height,c=e.contentStartPos.left,l=e.contentStartPos.top,u=s(e.newPoints[0],e.newPoints[1]),d=u/e.startDistanceBetweenFingers,f=Math.floor(a*d),h=Math.floor(r*d),p=(a-f)*e.percentageOfImageAtPinchPointX,g=(r-h)*e.percentageOfImageAtPinchPointY,b=(e.newPoints[0].x+e.newPoints[1].x)/2-n(t).scrollLeft(),m=(e.newPoints[0].y+e.newPoints[1].y)/2-n(t).scrollTop(),y=b-e.centerPointStartX,v=m-e.centerPointStartY,x=c+(p+y),w=l+(g+v),$={top:w,left:x,scaleX:e.contentStartPos.scaleX*d,scaleY:e.contentStartPos.scaleY*d};e.canTap=!1,e.newWidth=f,e.newHeight=h,e.contentLastPos=$,e.requestId&&(i(e.requestId),e.requestId=null),e.requestId=o(function(){n.fancybox.setTranslate(e.$content,e.contentLastPos)})},u.prototype.ontouchend=function(t){var o=this,s=Math.max((new Date).getTime()-o.startTime,1),r=o.isSwiping,c=o.isPanning,l=o.isZooming;return o.endPoints=a(t),o.$container.removeClass("fancybox-controls--isGrabbing"),n(e).off(".fb.touch"),o.requestId&&(i(o.requestId),o.requestId=null),o.isSwiping=!1,o.isPanning=!1,o.isZooming=!1,o.canTap?o.onTap(t):(o.speed=366,o.velocityX=o.distanceX/s*.5,o.velocityY=o.distanceY/s*.5,o.speedX=Math.max(.5*o.speed,Math.min(1.5*o.speed,1/Math.abs(o.velocityX)*o.speed)),void(c?o.endPanning():l?o.endZooming():o.endSwiping(r)))},u.prototype.endSwiping=function(t){var e=this,o=!1;e.instance.isSliding=!1,e.sliderLastPos=null,"y"==t&&Math.abs(e.distanceY)>50?(n.fancybox.animate(e.instance.current.$slide,{top:e.sliderStartPos.top+e.distanceY+150*e.velocityY,opacity:0},150),o=e.instance.close(!0,300)):"x"==t&&e.distanceX>50&&e.instance.group.length>1?o=e.instance.previous(e.speedX):"x"==t&&e.distanceX<-50&&e.instance.group.length>1&&(o=e.instance.next(e.speedX)),o!==!1||"x"!=t&&"y"!=t||e.instance.jumpTo(e.instance.current.index,150),e.$container.removeClass("fancybox-is-sliding")},u.prototype.endPanning=function(){var t,e,o,i=this;i.contentLastPos&&(i.instance.current.opts.touch.momentum===!1?(t=i.contentLastPos.left,e=i.contentLastPos.top):(t=i.contentLastPos.left+i.velocityX*i.speed,e=i.contentLastPos.top+i.velocityY*i.speed),o=i.limitPosition(t,e,i.contentStartPos.width,i.contentStartPos.height),o.width=i.contentStartPos.width,o.height=i.contentStartPos.height,n.fancybox.animate(i.$content,o,330))},u.prototype.endZooming=function(){var t,e,o,i,a=this,s=a.instance.current,r=a.newWidth,c=a.newHeight;a.contentLastPos&&(t=a.contentLastPos.left,e=a.contentLastPos.top,i={top:e,left:t,width:r,height:c,scaleX:1,scaleY:1},n.fancybox.setTranslate(a.$content,i),r<a.canvasWidth&&c<a.canvasHeight?a.instance.scaleToFit(150):r>s.width||c>s.height?a.instance.scaleToActual(a.centerPointStartX,a.centerPointStartY,150):(o=a.limitPosition(t,e,r,c),n.fancybox.setTranslate(a.content,n.fancybox.getTranslate(a.$content)),n.fancybox.animate(a.$content,o,150)))},u.prototype.onTap=function(t){var e,o=this,i=n(t.target),s=o.instance,r=s.current,c=t&&a(t)||o.startPoints,l=c[0]?c[0].x-o.$stage.offset().left:0,u=c[0]?c[0].y-o.$stage.offset().top:0,d=function(e){var i=r.opts[e];if(n.isFunction(i)&&(i=i.apply(s,[r,t])),i)switch(i){case"close":s.close(o.startEvent);break;case"toggleControls":s.toggleControls(!0);break;case"next":s.next();break;case"nextOrClose":s.group.length>1?s.next():s.close(o.startEvent);break;case"zoom":"image"==r.type&&(r.isLoaded||r.$ghost)&&(s.canPan()?s.scaleToFit():s.isScaledDown()?s.scaleToActual(l,u):s.group.length<2&&s.close(o.startEvent))}};if(!(t.originalEvent&&2==t.originalEvent.button||s.isSliding||l>i[0].clientWidth+i.offset().left)){if(i.is(".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container"))e="Outside";else if(i.is(".fancybox-slide"))e="Slide";else{if(!s.current.$content||!s.current.$content.has(t.target).length)return;e="Content"}if(o.tapped){if(clearTimeout(o.tapped),o.tapped=null,Math.abs(l-o.tapX)>50||Math.abs(u-o.tapY)>50||s.isSliding)return this;d("dblclick"+e)}else o.tapX=l,o.tapY=u,r.opts["dblclick"+e]&&r.opts["dblclick"+e]!==r.opts["click"+e]?o.tapped=setTimeout(function(){o.tapped=null,d("click"+e)},300):d("click"+e);return this}},n(e).on("onActivate.fb",function(t,e){e&&!e.Guestures&&(e.Guestures=new u(e))}),n(e).on("beforeClose.fb",function(t,e){e&&e.Guestures&&e.Guestures.destroy()})}(window,document,window.jQuery),function(t,e){"use strict";var n=function(t){this.instance=t,this.init()};e.extend(n.prototype,{timer:null,isActive:!1,$button:null,speed:3e3,init:function(){var t=this;t.$button=t.instance.$refs.toolbar.find("[data-fancybox-play]").on("click",function(){t.toggle()}),(t.instance.group.length<2||!t.instance.group[t.instance.currIndex].opts.slideShow)&&t.$button.hide()},set:function(){var t=this;t.instance&&t.instance.current&&(t.instance.current.opts.loop||t.instance.currIndex<t.instance.group.length-1)?t.timer=setTimeout(function(){t.instance.next()},t.instance.current.opts.slideShow.speed||t.speed):(t.stop(),t.instance.idleSecondsCounter=0,t.instance.showControls())},clear:function(){var t=this;clearTimeout(t.timer),t.timer=null},start:function(){var t=this,e=t.instance.current;t.instance&&e&&(e.opts.loop||e.index<t.instance.group.length-1)&&(t.isActive=!0,t.$button.attr("title",e.opts.i18n[e.opts.lang].PLAY_STOP).addClass("fancybox-button--pause"),e.isComplete&&t.set())},stop:function(){var t=this,e=t.instance.current;t.clear(),t.$button.attr("title",e.opts.i18n[e.opts.lang].PLAY_START).removeClass("fancybox-button--pause"),t.isActive=!1},toggle:function(){var t=this;t.isActive?t.stop():t.start()}}),e(t).on({"onInit.fb":function(t,e){e&&!e.SlideShow&&(e.SlideShow=new n(e))},"beforeShow.fb":function(t,e,n,o){var i=e&&e.SlideShow;o?i&&n.opts.slideShow.autoStart&&i.start():i&&i.isActive&&i.clear()},"afterShow.fb":function(t,e,n){var o=e&&e.SlideShow;o&&o.isActive&&o.set()},"afterKeydown.fb":function(n,o,i,a,s){var r=o&&o.SlideShow;!r||!i.opts.slideShow||80!==s&&32!==s||e(t.activeElement).is("button,a,input")||(a.preventDefault(),r.toggle())},"beforeClose.fb onDeactivate.fb":function(t,e){var n=e&&e.SlideShow;n&&n.stop()}}),e(t).on("visibilitychange",function(){var n=e.fancybox.getInstance(),o=n&&n.SlideShow;o&&o.isActive&&(t.hidden?o.clear():o.set())})}(document,window.jQuery),function(t,e){"use strict";var n=function(){var e,n,o,i=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],a={};for(n=0;n<i.length;n++)if(e=i[n],e&&e[1]in t){for(o=0;o<e.length;o++)a[i[0][o]]=e[o];return a}return!1}();if(!n)return void(e.fancybox.defaults.btnTpl.fullScreen=!1);var o={request:function(e){e=e||t.documentElement,e[n.requestFullscreen](e.ALLOW_KEYBOARD_INPUT)},exit:function(){t[n.exitFullscreen]()},toggle:function(e){e=e||t.documentElement,this.isFullscreen()?this.exit():this.request(e)},isFullscreen:function(){return Boolean(t[n.fullscreenElement])},enabled:function(){return Boolean(t[n.fullscreenEnabled])}};e(t).on({"onInit.fb":function(t,e){var n,i=e.$refs.toolbar.find("[data-fancybox-fullscreen]");e&&!e.FullScreen&&e.group[e.currIndex].opts.fullScreen?(n=e.$refs.container,n.on("click.fb-fullscreen","[data-fancybox-fullscreen]",function(t){t.stopPropagation(),t.preventDefault(),o.toggle(n[0])}),e.opts.fullScreen&&e.opts.fullScreen.autoStart===!0&&o.request(n[0]),e.FullScreen=o):i.hide()},"afterKeydown.fb":function(t,e,n,o,i){e&&e.FullScreen&&70===i&&(o.preventDefault(),e.FullScreen.toggle(e.$refs.container[0]))},"beforeClose.fb":function(t){t&&t.FullScreen&&o.exit()}}),e(t).on(n.fullscreenchange,function(){var t=e.fancybox.getInstance();t.current&&"image"===t.current.type&&t.isAnimating&&(t.current.$content.css("transition","none"),t.isAnimating=!1,t.update(!0,!0,0))})}(document,window.jQuery),function(t,e){"use strict";var n=function(t){this.instance=t,this.init()};e.extend(n.prototype,{$button:null,$grid:null,$list:null,isVisible:!1,init:function(){var t=this,e=t.instance.group[0],n=t.instance.group[1];t.$button=t.instance.$refs.toolbar.find("[data-fancybox-thumbs]"),t.instance.group.length>1&&t.instance.group[t.instance.currIndex].opts.thumbs&&("image"==e.type||e.opts.thumb||e.opts.$thumb)&&("image"==n.type||n.opts.thumb||n.opts.$thumb)?(t.$button.on("click",function(){t.toggle()}),t.isActive=!0):(t.$button.hide(),t.isActive=!1)},create:function(){var t,n,o=this.instance;this.$grid=e('<div class="fancybox-thumbs"></div>').appendTo(o.$refs.container),t="<ul>",e.each(o.group,function(e,o){n=o.opts.thumb||(o.opts.$thumb?o.opts.$thumb.attr("src"):null),n||"image"!==o.type||(n=o.src),n&&n.length&&(t+='<li data-index="'+e+'" tabindex="0" class="fancybox-thumbs-loading"><img data-src="'+n+'" /></li>')}),t+="</ul>",this.$list=e(t).appendTo(this.$grid).on("click","li",function(){o.jumpTo(e(this).data("index"))}),this.$list.find("img").hide().one("load",function(){var t,n,o,i,a=e(this).parent().removeClass("fancybox-thumbs-loading"),s=a.outerWidth(),r=a.outerHeight();t=this.naturalWidth||this.width,n=this.naturalHeight||this.height,o=t/s,i=n/r,o>=1&&i>=1&&(o>i?(t/=i,n=r):(t=s,n/=o)),e(this).css({width:Math.floor(t),height:Math.floor(n),"margin-top":Math.min(0,Math.floor(.3*r-.3*n)),"margin-left":Math.min(0,Math.floor(.5*s-.5*t))}).show()}).each(function(){this.src=e(this).data("src")})},focus:function(){this.instance.current&&this.$list.children().removeClass("fancybox-thumbs-active").filter('[data-index="'+this.instance.current.index+'"]').addClass("fancybox-thumbs-active").focus()},close:function(){this.$grid.hide()},update:function(){this.instance.$refs.container.toggleClass("fancybox-show-thumbs",this.isVisible),this.isVisible?(this.$grid||this.create(),this.instance.trigger("onThumbsShow"),this.focus()):this.$grid&&this.instance.trigger("onThumbsHide"),this.instance.update()},hide:function(){this.isVisible=!1,this.update()},show:function(){this.isVisible=!0,this.update()},toggle:function(){this.isVisible=!this.isVisible,this.update()}}),e(t).on({"onInit.fb":function(t,e){e&&!e.Thumbs&&(e.Thumbs=new n(e))},"beforeShow.fb":function(t,e,n,o){var i=e&&e.Thumbs;if(i&&i.isActive){if(n.modal)return i.$button.hide(),void i.hide();o&&e.opts.thumbs.autoStart===!0&&i.show(),i.isVisible&&i.focus()}},"afterKeydown.fb":function(t,e,n,o,i){var a=e&&e.Thumbs;a&&a.isActive&&71===i&&(o.preventDefault(),a.toggle())},"beforeClose.fb":function(t,e){var n=e&&e.Thumbs;n&&n.isVisible&&e.opts.thumbs.hideOnClose!==!1&&n.close()}})}(document,window.jQuery),function(t,e,n){"use strict";function o(){var t=e.location.hash.substr(1),n=t.split("-"),o=n.length>1&&/^\+?\d+$/.test(n[n.length-1])?parseInt(n.pop(-1),10)||1:1,i=n.join("-");return o<1&&(o=1),{hash:t,index:o,gallery:i}}function i(t){var e;""!==t.gallery&&(e=n("[data-fancybox='"+n.escapeSelector(t.gallery)+"']").eq(t.index-1),e.length||(e=n("#"+n.escapeSelector(t.gallery))),e.length&&(s=!1,e.trigger("click")))}function a(t){var e;return!!t&&(e=t.current?t.current.opts:t.opts,e.$orig?e.$orig.data("fancybox"):e.hash||"")}n.escapeSelector||(n.escapeSelector=function(t){var e=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,n=function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t};return(t+"").replace(e,n)});var s=!0,r=null,c=null;n(function(){setTimeout(function(){n.fancybox.defaults.hash!==!1&&(n(t).on({"onInit.fb":function(t,e){var n,i;e.group[e.currIndex].opts.hash!==!1&&(n=o(),i=a(e),i&&n.gallery&&i==n.gallery&&(e.currIndex=n.index-1))},"beforeShow.fb":function(n,o,i){var l;i.opts.hash!==!1&&(l=a(o),l&&""!==l&&(e.location.hash.indexOf(l)<0&&(o.opts.origHash=e.location.hash),r=l+(o.group.length>1?"-"+(i.index+1):""),"replaceState"in e.history?(c&&clearTimeout(c),c=setTimeout(function(){e.history[s?"pushState":"replaceState"]({},t.title,e.location.pathname+e.location.search+"#"+r),c=null,s=!1},300)):e.location.hash=r))},"beforeClose.fb":function(o,i,s){var l,u;c&&clearTimeout(c),s.opts.hash!==!1&&(l=a(i),u=i&&i.opts.origHash?i.opts.origHash:"",l&&""!==l&&("replaceState"in history?e.history.replaceState({},t.title,e.location.pathname+e.location.search+u):(e.location.hash=u,n(e).scrollTop(i.scrollTop).scrollLeft(i.scrollLeft))),r=null)}}),n(e).on("hashchange.fb",function(){var t=o();n.fancybox.getInstance()?!r||r===t.gallery+"-"+t.index||1===t.index&&r==t.gallery||(r=null,n.fancybox.close(),s=!0):""!==t.gallery&&i(t)}),i(o()))},50)})}(document,window,window.jQuery);
\ No newline at end of file
--- /dev/null
+<!doctype html>
+<html>
+<head>
+ <title>fancyBox - touch enabled, responsive and fully customizable lightbox script</title>
+
+ <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+
+ <link href="https://fonts.googleapis.com/css?family=Montserrat:400,700|Open+Sans:400,700" rel="stylesheet" />
+
+ <script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
+
+ <style>
+ /* Reset */
+
+ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+ }
+
+ html {
+ box-sizing: border-box;
+ }
+
+ *, *:before, *:after {
+ box-sizing: inherit;
+ }
+
+ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
+ display: block;
+ }
+
+ table {
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
+
+ /* Common styling */
+
+ body {
+ -webkit-text-size-adjust: none;
+ font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ line-height: 1.6;
+ color: #333;
+ }
+
+ h1, h2, h3 {
+ font-family: 'Montserrat', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ font-weight: 700;
+ color: #333;
+ }
+
+ a {
+ color: #FF6666;
+ text-decoration: none;
+ }
+
+ a:hover {
+ text-decoration: underline;
+ }
+
+ a.active {
+ font-weight: bold;
+ }
+
+ h1, h2, h3 {
+ font-family: 'Montserrat', sans-serif;
+ font-weight: 700;
+ color: #333;
+ }
+
+ h1 {
+ font-size: 2.5em;
+ font-weight: bold;
+ letter-spacing: -1px;
+ }
+
+ h1 a:hover {
+ text-decoration: none;
+ }
+
+ h2 {
+ margin: 3em 0 1em 0;
+ padding-bottom: 0.25em;
+ font-size: 2em;
+ border-bottom: 1px solid #eee;
+ }
+
+ h2:first-of-type {
+ margin-top: 0;
+ }
+
+ h3 {
+ margin-top: 2em;
+ font-size: 1.25em;
+ }
+
+ h4 {
+ margin-top: 1em;
+ font-weight: bold;
+ font-size: 1em;
+ }
+
+ .important {
+ color: #fff;
+ background: #FF6666;
+ display: inline-block;
+ padding: 0 10px;
+ border-radius: 5px;
+ }
+
+ b {
+ font-weight: 700;
+ }
+
+ p {
+ margin: 0.5em 0 1.5em 0;
+ }
+
+ p:last-child {
+ margin-bottom: 0;
+ }
+
+ ul {
+ padding-left: 2em;
+ margin: 0.5em 0 1.5em 0;
+ }
+
+ pre, code, .demo {
+ font-family: Consolas,"Liberation Mono",Courier,monospace;
+ }
+
+ pre, code {
+ background: #F4F5F6;
+ color: #66676E;
+ }
+
+ pre {
+ padding: 1em;
+ margin-bottom: 1.5em;
+ overflow: auto;
+ min-height: 56px;
+ max-height: 70vh;
+ -moz-tab-size: 4;
+ tab-size: 4;
+ }
+
+ code {
+ padding: 2px 5px;
+ }
+
+ pre code {
+ padding: 0;
+ }
+
+ .demo {
+ margin-top: -1em;
+ text-align: right;
+ }
+
+
+ /* Layout */
+
+ header {
+ position: relative;
+ padding: 6em 0 6em 0;
+ margin-bottom: 3em;
+ background: #FF6666;
+ color: #fff;
+ text-align: right;
+ }
+
+ header:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 100%;
+ height: 500px;
+ background: #fff;
+ -webkit-transform-origin: right;
+ -ms-transform-origin: right;
+ transform-origin: right;
+ -webkit-transform: skewY(2deg);
+ -ms-transform: skewY(2deg);
+ transform: skewY(2deg);
+ }
+
+ .content {
+ position: relative;
+ max-width: 1020px;
+ margin: 0 auto;
+ padding: 0 50px;
+ }
+
+ section .content {
+ padding-left: 250px;
+ }
+
+ footer .content {
+ padding: 6em 50px 3em 240px;
+ }
+
+ aside {
+ position: absolute;
+ top: 0;
+ left : 50px;
+ width: 200px;
+ }
+
+ /* Header */
+
+ header h1, header h1 a {
+ color: #fff;
+ }
+
+ header ul {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+
+ header ul li {
+ display: inline-block;
+ margin-right: 0.5em;
+ }
+
+ header ul li a {
+ font-size: 1.125em;
+ color: #fff;
+ }
+
+ /* Sidebar */
+
+ aside ul {
+ position: relative;;
+ top: 0;
+ list-style: none;
+ padding: 1.5em 0;
+ margin: 0;
+ }
+
+ aside ul ul {
+ padding: 0 0 0.5em 1.5em;
+ font-size: 90%;
+ }
+
+ @media all and (max-width: 800px) {
+
+ aside {
+ position: relative;
+ left: 0;
+ }
+
+ .content {
+ padding: 0 25px;
+ }
+
+ section .content,
+ footer .content {
+ padding-left: 25px;
+ }
+
+ }
+
+ </style>
+</head>
+<body>
+
+ <header>
+ <div class="content">
+ <h1><a href="http://fancyapps.com/fancybox/3/">fancyBox3</a> Documentation</h1>
+
+ <ul>
+ <li><a href="http://fancyapps.com/fancybox/3/">Homepage</a></li>
+ <li><a href="http://fancyapps.com/fancybox/3/docs/">Documentation</a></li>
+ <li><a href="http://fancyapps.com/store/">Store</a></li>
+ <li><a href="https://github.com/fancyapps/fancybox">Github</a></li>
+ </ul>
+ </div>
+ </header>
+
+ <section>
+ <div class="content">
+
+ <aside>
+ <ul class="sticky">
+ <li><a href="#introduction">Introduction</a></li>
+ <li><a href="#setup">Setup</a></li>
+ <li><a href="#usage">How to Use</a></li>
+ <li>
+ <a href="#media_types">Media types</a>
+
+ <ul>
+ <li><a href="#images">Images</a></li>
+ <li><a href="#inline">Inline</a></li>
+ <li><a href="#ajax">Ajax</a></li>
+ <li><a href="#iframe">Iframe</a></li>
+ </ul>
+ </li>
+ <li><a href="#embedding">Embedding</a></li>
+ <li><a href="#options">Options</a></li>
+ <li><a href="#api">Api</a></li>
+ <li><a href="#modules">Modules</a></li>
+ <li><a href="#faq">FAQ</a></li>
+ </ul>
+ </aside>
+<!--
+
+ Introduction
+ =====
+
+-->
+ <h2 id="introduction">Introduction</h2>
+
+ <p>
+ fancyBox is a JavaScript library used to present images, videos and any html content in an elegant way.
+ It has all features you would expect - touch enabled, responsive and fully customizable.
+ <p>
+
+ </p>
+
+ <h3>
+ Dependencies
+ </h3>
+
+ <p>
+ jQuery 3+ is preferred, but fancyBox works with jQuery 1.9.1+ and jQuery 2+
+ </p>
+
+ <h3>Compatibility</h3>
+
+ <p>
+ fancyBox includes support for touch gestures and even supports pinch gestures for zooming.
+ It is perfectly suited for both mobile and desktop browsers.
+ </p>
+
+ <p>
+ fancyBox has been tested in following browsers/devices:
+ </p>
+
+ <ul>
+ <li>Chrome</li>
+ <li>Firefox</li>
+ <li>IE10/11</li>
+ <li>Edge</li>
+ <li>iOS Safari</li>
+ <li>Nexus 7 Chrome</li>
+ </ul>
+<!--
+
+ Setup
+ =====
+
+-->
+ <h2 id="setup">Setup</h2>
+
+ <p>
+ You can install fancyBox by linking <code>.css</code> and <code>.js</code> to your html file.
+
+ Make sure you also load the jQuery library.
+ Below is a basic HTML template to use as an example:
+ </p>
+
+ <pre><!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>My page</title>
+
+ <!-- CSS -->
+ <link rel="stylesheet" type="text/css" href="jquery.fancybox.min.css">
+</head>
+<body>
+
+ <!-- Your HTML content goes here -->
+
+ <!-- JS -->
+ <script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
+ <script src="jquery.fancybox.min.js"></script>
+</body>
+</html>
+</pre>
+
+ <h4 class="important">Important</h4>
+
+ <ul>
+ <li>Make sure you add the jQuery library first</li>
+ <li>If you already have jQuery on your page, you shouldn't include it second time</li>
+ <li>Do not include both fancybox.js and fancybox.min.js files</li>
+ <li>
+ Some functionality (ajax, iframes, etc) will not work when you're opening local files on your computer,
+ the code must be running on a web server
+ </li>
+ </ul>
+
+ <h3>Download fancyBox</h3>
+
+ <p>
+ You can download the latest version of fancyBox on <a href="https://github.com/fancyapps/fancybox" target="_blank">GitHub</a>.
+ <br />
+ Or just link directly to fancyBox files on cdnjs - <a href="https://cdnjs.com/libraries/fancybox" target="_blank">https://cdnjs.com/libraries/fancybox</a>.
+ </p>
+
+
+ <h3>Package Managers</h3>
+
+ <p>
+ fancyBox can also be installed via Bower or npm.
+ </p>
+
+<pre><code># Bower
+bower install fancybox --save
+
+# NPM
+npm install @fancyapps/fancybox --save
+</code></pre>
+
+
+<!--
+
+ How To Use
+ ==========
+
+-->
+ <h2 id="usage">How to Use</h2>
+
+ <h3>Initialize with data attributes</h3>
+
+ <p>
+ The most basic way to use fancyBox is by adding the <code>data-fancybox</code> attribute to a link.
+ A caption can be added using the <code>data-caption</code> attribute. Example:
+ </p>
+
+ <pre><a href="image.jpg" data-fancybox data-caption="My caption">
+ <img src="thumbnail.jpg" alt="" />
+</a></pre>
+
+ <p>
+ If you choose this method, default settings will be applied.
+ See <a href="#options">Options</a> section for examples how to customize by changing defaults or using <code>data-options</code> attribute.
+ </p>
+
+ <h3>Initialize with JavaScript</h3>
+
+ <p>
+ Select elements with a jQuery selector and call the <code>fancybox</code> method:
+ </p>
+
+ <pre><code><script type="text/javascript">
+ $("[data-fancybox]").fancybox({
+ // Options will go here
+ });
+</script></code></pre>
+
+
+ <p>
+ Using this method, click event handler is attached only to the currently selected elements.
+ <br />
+ To attach click event listener for elements that exist now or in the future, use <code>selector</code> option. Example:
+ </p>
+
+ <pre><code>$().fancybox({
+ selector : '[data-fancybox="images"]',
+ loop : true
+});</code></pre>
+
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/gWvorB?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <h3>Manual calling of fancyBox</h3>
+
+ <p>
+ fancyBox can be activated at any point within Javascript and therefore does not necessarily need a trigger element.
+
+ Example of displaying a simple message:
+ </p>
+
+ <pre><code>$.fancybox.open('<div class="message"><h2>Hello!</h2><p>You are awesome!</p></div>');</code></pre>
+
+ <p>
+ See <a href="#api">API</a> section for more information and examples.
+ </p>
+
+ <h3>Grouping</h3>
+
+ <p>
+ If you have a group of items, you can use the same attribute <code>data-fancybox</code> value for each of them to create a gallery.
+ Each group should have a unique value:
+ </p>
+
+<pre><a href="image_1.jpg" data-fancybox="group" data-caption="Caption #1">
+ <img src="thumbnail_1.jpg" alt="" />
+</a>
+
+<a href="image_2.jpg" data-fancybox="group" data-caption="Caption #2">
+ <img src="thumbnail_2.jpg" alt="" />
+</a>
+</pre>
+
+
+<h4 class="important">Important</h4>
+
+<p>
+ fancyBox attempts to automatically detect the type of content based on the given url.
+
+ If it cannot be detected, the type can also be set manually using <code>data-type</code> attribute:
+
+ <pre><a href="images.php?id=123" data-type="image" data-caption="Caption">
+ Show image
+</a></pre>
+</p>
+
+
+
+<!--
+
+ Examples
+ =========
+
+-->
+ <h2 id="media_types">Media types</h2>
+
+
+ <h3 id="images">Images</h3>
+
+ <p>
+ The standard way of using fancyBox is with a number of thumbnail images that link to larger images:
+ </p>
+
+ <pre><code><a href="image.jpg" data-fancybox="images" data-caption="My caption">
+ <img src="thumbnail.jpg" alt="" />
+</a></code></pre>
+
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/WjVXyx?editors=1000" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <p>
+ By default, fancyBox fully preloads an image before displaying it.
+ You can choose to display the image right away.
+ It will render and show the full size image while the data is being received.
+ To do so, some attributes are necessary:
+ </p>
+
+ <ul>
+ <li><code>data-width</code> - the real width of the image</li>
+ <li><code>data-height</code> - the real height of the image</li>
+ </ul>
+
+ <pre><code><a href="image.jpg" data-fancybox="images" data-width="2048" data-height="1365">
+ <img src="thumbnail.jpg" />
+</a></code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/JNgggo?editors=1000" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <p>
+ fancyBox supports "scrset" so I can display different images based on viewport width. You can use this to improve download times for mobile users and over time save bandwidth.
+ Example:
+ </p>
+
+ <pre><code><a href="medium.jpg" data-fancybox="images" data-srcset="large.jpg 1600w, medium.jpg 1200w, small.jpg 640w">
+ <img src="thumbnail.jpg" />
+</a></code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/YQKKYx?editors=1000" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <p>
+ It is also possible to protect images from downloading by right-click.
+ While this does not protect from truly determined users, it should discourage the vast majority from ripping off your files.
+ </p>
+
+ <pre><code>$('[data-fancybox]').fancybox({
+ protect: true
+});</code></pre>
+
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/jwNNZJ" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <h3 id="inline">Inline HTML</h3>
+
+ <p>
+ For inline content, create a hidden element with unique id:
+ </p>
+
+ <pre><code><div style="display: none;" id="hidden-content">
+ <h2>Hello</h2>
+ <p>You are awesome.</p>
+</div></code></pre>
+
+ <p>
+ And then simply create a link having <code>data-src</code> attribute that matches ID of the element you want to open (preceded by a hash mark (#); in this example - <code>#hidden-content</code>):
+ </p>
+
+ <pre><code><a data-fancybox data-src="#hidden-content" href="javascript:;">
+ Hidden div
+</a></code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/NjXbXw" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <p>
+ The script will append small close button (if you have not disabled by <code>smallBtn:false</code>)
+ and will not apply any styles except for centering. Therefore you can easily set custom dimensions using CSS.
+ </p>
+
+ <h3 id="ajax">Ajax</h3>
+
+ <p>
+ To load content via AJAX, you need to add a <code>data-type="ajax"</code> attribute to your link:
+ </p>
+
+ <pre><code><a data-fancybox data-type="ajax" data-src="my_page.com/path/to/ajax/" href="javascript:;">
+ AJAX content
+</a></code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/RgbwrY?editors=1100" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <p>
+ Additionally it is possible to define a selector with the <code>data-filter</code> attribute to show only a part of the response. The selector can be any string, that is a valid jQuery selector:
+ </p>
+
+ <pre><code><a data-fancybox data-type="ajax" data-src="my_page.com/path/to/ajax/" data-filter="#two" href="javascript:;">
+ AJAX content
+</a>
+</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/xrKxXp?editors=1100" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <h3 id="iframe">Iframe</h3>
+
+ <p>
+ If the content can be shown on a page, and placement in an iframe is not blocked by script or security configuration of that page,
+ it can be presented in a fancyBox:
+ </p>
+
+ <pre><code><a data-fancybox data-type="iframe" data-src="http://codepen.io/fancyapps/full/jyEGGG/" href="javascript:;">
+ Webpage
+</a>
+
+<a data-fancybox data-type="iframe" data-src="https://mozilla.github.io/pdf.js/web/viewer.html" href="javascript:;">
+ Sample PDF
+</a>
+</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/LLPYXg?editors=1000" target="_blank">View demo on CodePen</a>
+ </p>
+
+
+ <p>
+ To access and control fancyBox in parent window from inside an iframe:
+ </p>
+
+ <pre><code>// Adjust iframe height according to the contents
+parent.jQuery.fancybox.getInstance().update();
+
+// Close current fancyBox instance
+parent.jQuery.fancybox.getInstance().close();</code></pre>
+
+
+ <p>
+ Iframe dimensions can be controlled by CSS:
+ </p>
+
+ <pre><code>.fancybox-slide--iframe .fancybox-content {
+ width : 800px;
+ height : 600px;
+ max-width : 80%;
+ max-height : 80%;
+ margin: 0;
+}</code></pre>
+
+
+ <p>
+ These CSS rules can be overridden by JS, if needed:
+ </p>
+
+ <pre><code>$("[data-fancybox]").fancybox({
+ iframe : {
+ css : {
+ width : '600px'
+ }
+ }
+});</code></pre>
+
+
+ <p>
+ If you have not disabled iframe preloading (using <code>preload</code> option), then the script will atempt to
+ calculate content dimensions and will adjust width/height of iframe to fit with content in it.
+ Keep in mind, that due to <a href="https://en.wikipedia.org/wiki/Same-origin_policy" target="_blank">same origin policy</a>,
+ there are some limitations.
+ </p>
+
+ <p>
+ This example will disable iframe preloading and will display small close button next to iframe instead of the toolbar:
+ </p>
+
+ <pre><code>$('[data-fancybox]').fancybox({
+ toolbar : false,
+ smallBtn : true,
+ iframe : {
+ preload : false
+ }
+})
+</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/eRzwye?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+
+<!--
+
+ Embedding
+ =======
+
+-->
+ <h2 id="embedding">Embedding</h2>
+
+ <p>
+ Supported sites can be used with fancyBox by just providing the page URL:
+ </p>
+
+ <pre><code><a data-fancybox href="https://www.youtube.com/watch?v=_sI_Ps7JSEk">
+ YouTube video
+</a>
+
+<a data-fancybox href="https://vimeo.com/191947042">
+ Vimeo video
+</a>
+
+<a data-fancybox href="https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572">
+ Google Map
+</a>
+
+<a data-fancybox href="https://www.instagram.com/p/BNXYW8-goPI/?taken-by=jamesrelfdyer" data-caption="<span title=&quot;Edited&quot;>balloon rides at dawn ✨🎈<br>was such a magical experience floating over napa valley as the golden light hit the hills.<br><a href=&quot;https://www.instagram.com/jamesrelfdyer/&quot;>@jamesrelfdyer</a></span>">
+ Instagram photo
+</a></code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/pwzvvr?editors=1000" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <h3>Video dimensions</h3>
+
+ <p>
+ Resize video display with the following CSS:
+ </p>
+
+ <pre><code>.fancybox-slide--video .fancybox-content {
+ width : 800px;
+ height : 600px;
+ max-width : 80%;
+ max-height : 80%;
+}</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/zzOrBL?editors=1100" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <p>
+ Obviously, you can choose any size you like, any combination with <code>min</code>/<code>max</code> values.
+ <br />
+ Aspect ratio lock for videos is not implemented yet, but if you wish, <a href="https://codepen.io/fancyapps/pen/NgKNRz?editors=1010" target="_blank">you can use this snippet</a>.
+ </p>
+
+
+
+ <h3>Video parameters</h3>
+
+ <p>
+ Controlling a video via URL parameters:
+ </p>
+
+ <pre><code><a data-fancybox href="https://www.youtube.com/watch?v=_sI_Ps7JSEk&amp;autoplay=1&amp;rel=0&amp;controls=0&amp;showinfo=0">
+ YouTube video - hide controls and info
+</a>
+
+<a data-fancybox href="https://vimeo.com/191947042?color=f00">
+ Vimeo video - custom color
+</a></code></pre>
+ <p class="demo">
+ <a href="http://codepen.io/fancyapps/pen/mRVNyO?editors=1000" target="_blank">View demo on CodePen</a>
+ </p>
+
+
+ <p>
+ Via JavaScript:
+ </p>
+
+ <pre><code>$('[data-fancybox]').fancybox({
+ youtube : {
+ controls : 0,
+ showinfo : 0
+ },
+ vimeo : {
+ color : 'f00'
+ }
+});</code></pre>
+ <p class="demo">
+ <a href="http://codepen.io/fancyapps/pen/Qdyeyr?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+<!--
+
+ Options
+ =======
+
+-->
+ <h2 id="options">Options</h2>
+
+ <p>
+ Quick reference for all default options as defined in the source:
+ </p>
+
+ <pre>defaults = {
+
+ // Enable infinite gallery navigation
+ loop : false,
+
+ // Space around image, ignored if zoomed-in or viewport smaller than 800px
+ margin : [44, 0],
+
+ // Horizontal space between slides
+ gutter : 50,
+
+ // Enable keyboard navigation
+ keyboard : true,
+
+ // Should display navigation arrows at the screen edges
+ arrows : true,
+
+ // Should display infobar (counter and arrows at the top)
+ infobar : false,
+
+ // Should display toolbar (buttons at the top)
+ toolbar : true,
+
+ // What buttons should appear in the top right corner.
+ // Buttons will be created using templates from `btnTpl` option
+ // and they will be placed into toolbar (class="fancybox-toolbar"` element)
+ buttons : [
+ 'slideShow',
+ 'fullScreen',
+ 'thumbs',
+ 'close'
+ ],
+
+ // Detect "idle" time in seconds
+ idleTime : 4,
+
+ // Should display buttons at top right corner of the content
+ // If 'auto' - they will be created for content having type 'html', 'inline' or 'ajax'
+ // Use template from `btnTpl.smallBtn` for customization
+ smallBtn : 'auto',
+
+ // Disable right-click and use simple image protection for images
+ protect : false,
+
+ // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
+ modal : false,
+
+ image : {
+
+ // Wait for images to load before displaying
+ // Requires predefined image dimensions
+ // If 'auto' - will zoom in thumbnail if 'width' and 'height' attributes are found
+ preload : "auto",
+
+ },
+
+ ajax : {
+
+ // Object containing settings for ajax request
+ settings : {
+
+ // This helps to indicate that request comes from the modal
+ // Feel free to change naming
+ data : {
+ fancybox : true
+ }
+ }
+
+ },
+
+ iframe : {
+
+ // Iframe template
+ tpl : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen allowtransparency="true" src=""></iframe>',
+
+ // Preload iframe before displaying it
+ // This allows to calculate iframe content width and height
+ // (note: Due to "Same Origin Policy", you can't get cross domain data).
+ preload : true,
+
+ // Custom CSS styling for iframe wrapping element
+ // You can use this to set custom iframe dimensions
+ css : {},
+
+ // Iframe tag attributes
+ attr : {
+ scrolling : 'auto'
+ }
+
+ },
+
+ // Open/close animation type
+ // Possible values:
+ // false - disable
+ // "zoom" - zoom images from/to thumbnail
+ // "fade"
+ // "zoom-in-out"
+ //
+ animationEffect : "zoom",
+
+ // Duration in ms for open/close animation
+ animationDuration : 366,
+
+ // Should image change opacity while zooming
+ // If opacity is 'auto', then opacity will be changed if image and thumbnail have different aspect ratios
+ zoomOpacity : 'auto',
+
+ // Transition effect between slides
+ //
+ // Possible values:
+ // false - disable
+ // "fade'
+ // "slide'
+ // "circular'
+ // "tube'
+ // "zoom-in-out'
+ // "rotate'
+ //
+ transitionEffect : "fade",
+
+ // Duration in ms for transition animation
+ transitionDuration : 366,
+
+ // Custom CSS class for slide element
+ slideClass : '',
+
+ // Custom CSS class for layout
+ baseClass : '',
+
+ // Base template for layout
+ baseTpl :
+ '<div class="fancybox-container" role="dialog" tabindex="-1">' +
+ '<div class="fancybox-bg"></div>' +
+ '<div class="fancybox-inner">' +
+ '<div class="fancybox-infobar">' +
+ '<button data-fancybox-prev title="{{PREV}}" class="fancybox-button fancybox-button--left"></button>' +
+ '<div class="fancybox-infobar__body">' +
+ '<span data-fancybox-index></span>&nbsp;/&nbsp;<span data-fancybox-count></span>' +
+ '</div>' +
+ '<button data-fancybox-next title="{{NEXT}}" class="fancybox-button fancybox-button--right"></button>' +
+ '</div>' +
+ '<div class="fancybox-toolbar">' +
+ '{{BUTTONS}}' +
+ '</div>' +
+ '<div class="fancybox-navigation">' +
+ '<button data-fancybox-prev title="{{PREV}}" class="fancybox-arrow fancybox-arrow--left" />' +
+ '<button data-fancybox-next title="{{NEXT}}" class="fancybox-arrow fancybox-arrow--right" />' +
+ '</div>' +
+ '<div class="fancybox-stage"></div>' +
+ '<div class="fancybox-caption-wrap">' +
+ '<div class="fancybox-caption"></div>' +
+ '</div>' +
+ '</div>' +
+ '</div>',
+
+ // Loading indicator template
+ spinnerTpl : '<div class="fancybox-loading"></div>',
+
+ // Error message template
+ errorTpl : '<div class="fancybox-error"><p>{{ERROR}}<p></div>',
+
+ btnTpl : {
+ slideShow : '<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}"></button>',
+ fullScreen : '<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fullscreen" title="{{FULL_SCREEN}}"></button>',
+ thumbs : '<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}"></button>',
+ close : '<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}"></button>',
+
+ // This small close button will be appended to your html/inline/ajax content by default,
+ // if "smallBtn" option is not set to false
+ smallBtn : '<button data-fancybox-close class="fancybox-close-small" title="{{CLOSE}}"></button>'
+ },
+
+ // Container is injected into this element
+ parentEl : 'body',
+
+
+ // Focus handling
+ // ==============
+
+ // Try to focus on the first focusable element after opening
+ autoFocus : true,
+
+ // Put focus back to active element after closing
+ backFocus : true,
+
+ // Do not let user to focus on element outside modal content
+ trapFocus : true,
+
+
+ // Module specific options
+ // =======================
+
+ fullScreen : {
+ autoStart : false,
+ },
+
+ touch : {
+ vertical : true, // Allow to drag content vertically
+ momentum : true // Continue movement after releasing mouse/touch when panning
+ },
+
+ // Hash value when initializing manually,
+ // set `false` to disable hash change
+ hash : null,
+
+ // Customize or add new media types
+ // Example:
+ /*
+ media : {
+ youtube : {
+ params : {
+ autoplay : 0
+ }
+ }
+ }
+ */
+ media : {},
+
+ slideShow : {
+ autoStart : false,
+ speed : 4000
+ },
+
+ thumbs : {
+ autoStart : false, // Display thumbnails on opening
+ hideOnClose : true // Hide thumbnail grid when closing animation starts
+ },
+
+ // Callbacks
+ //==========
+
+ // See Documentation/API/Events for more information
+ // Example:
+ /*
+ afterShow: function( instance, current ) {
+ console.info( 'Clicked element:' );
+ console.info( current.opts.$orig );
+ }
+ */
+
+ onInit : $.noop, // When instance has been initialized
+
+ beforeLoad : $.noop, // Before the content of a slide is being loaded
+ afterLoad : $.noop, // When the content of a slide is done loading
+
+ beforeShow : $.noop, // Before open animation starts
+ afterShow : $.noop, // When content is done loading and animating
+
+ beforeClose : $.noop, // Before the instance attempts to close. Return false to cancel the close.
+ afterClose : $.noop, // After instance has been closed
+
+ onActivate : $.noop, // When instance is brought to front
+ onDeactivate : $.noop, // When other instance has been activated
+
+
+ // Interaction
+ // ===========
+
+ // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
+ // each option can be string or method that returns value.
+ //
+ // Possible values:
+ // "close" - close instance
+ // "next" - move to next gallery item
+ // "nextOrClose" - move to next gallery item or close if gallery has only one item
+ // "toggleControls" - show/hide controls
+ // "zoom" - zoom image (if loaded)
+ // false - do nothing
+
+ // Clicked on the content
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+
+ // Clicked on the slide
+ clickSlide : 'close',
+
+ // Clicked on the background (backdrop) element
+ clickOutside : 'close',
+
+ // Same as previous two, but for double click
+ dblclickContent : false,
+ dblclickSlide : false,
+ dblclickOutside : false,
+
+
+ // Custom options when mobile device is detected
+ // =============================================
+
+ mobile : {
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : false;
+ },
+ clickSlide : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : "close";
+ },
+ dblclickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+ dblclickSlide : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ }
+ },
+
+
+ // Internationalization
+ // ============
+
+ lang : 'en',
+ i18n : {
+ 'en' : {
+ CLOSE : 'Close',
+ NEXT : 'Next',
+ PREV : 'Previous',
+ ERROR : 'The requested content cannot be loaded. <br/> Please try again later.',
+ PLAY_START : 'Start slideshow',
+ PLAY_STOP : 'Pause slideshow',
+ FULL_SCREEN : 'Full screen',
+ THUMBS : 'Thumbnails'
+ },
+ 'de' : {
+ CLOSE : 'Schliessen',
+ NEXT : 'Weiter',
+ PREV : 'Zurück',
+ ERROR : 'Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es später nochmal.',
+ PLAY_START : 'Diaschau starten',
+ PLAY_STOP : 'Diaschau beenden',
+ FULL_SCREEN : 'Vollbild',
+ THUMBS : 'Vorschaubilder'
+ }
+ }
+
+}
+</pre>
+
+
+ <p>
+ Set instance options by passing a valid object to <code>fancybox()</code> method:
+ </p>
+
+ <pre><code>$("[data-fancybox]").fancybox({
+ thumbs : {
+ autoStart : true
+ }
+});</code></pre>
+
+
+ <p>
+ Plugin options / defaults are exposed in <code>$.fancybox.defaults</code> namespace so you can easily adjust them globally:
+
+ </p>
+
+ <pre><code>$.fancybox.defaults.animationEffect = "fade";</code></pre>
+
+ <p>
+ Custom options for each element individually can be set by adding a <code>data-options</code>
+ attribute to the element.
+
+ This attribute should contain the properly formatted JSON object:
+ </p>
+
+ <pre><code><a data-fancybox data-options='{"caption" : "My caption", "src" : "https://codepen.io/about/", "type" : "iframe"}' href="javascript:;" class="btn">
+ Open external page
+</a>
+</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/vZxLyb?editors=1000" target="_blank">View demo on CodePen</a>
+ </p>
+
+
+
+<!--
+
+API
+===
+
+-->
+ <h2 id="api">API</h2>
+
+ <p>
+ The fancyBox API offers a couple of methods to control fancyBox.
+
+ This gives you the ability to extend the plugin and to integrate it with other web application components.
+ </p>
+
+ <h3 id="core_methods">Core methods</h3>
+
+ <p>
+ Core methods are methods which affect/handle instances:
+ </p>
+
+
+ <pre><code>// Close only the currently active or all fancyBox instances
+$.fancybox.close( all );
+
+// Open the fancyBox right away
+$.fancybox.open( items, opts, index );
+</code></pre>
+
+
+ <p>
+ Gallery items can be collection of jQuery objects or array containing plain objects. This can be used, for example, to create content filter.
+ </p>
+
+ <pre><code>var $links = $('.fancybox');
+
+$links.on('click', function() {
+
+ $.fancybox.open( $links, {
+ // Custom options
+ }, $links.index( this ) );
+
+ return false;
+});</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/YQKPYX?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+
+
+ <p>
+ When creating group objects manually, each item should follow this pattern:
+ </p>
+
+ <pre><code>{
+ src : '' // Source of the content
+ type : '' // Content type: image|inline|ajax|iframe|html (optional)
+ opts : {} // Object containing item options (optional)
+}
+</code></pre>
+
+
+ <p>
+ Example of opening image gallery:
+ </p>
+
+ <pre><code>$.fancybox.open([
+ {
+ src : '1_b.jpg',
+ opts : {
+ caption : 'First caption'
+ }
+ },
+ {
+ src : '2_b.jpg',
+ opts : {
+ caption : 'Second caption'
+ }
+ }
+], {
+ loop : false
+});</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/GEKgjp?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <p>
+ It is also possible to pass only one object. Example of opening inline content:
+ </p>
+
+ <pre><code>$.fancybox.open({
+ src : '#hidden-content',
+ type : 'inline',
+ opts : {
+ afterShow : function( instance, current ) {
+ console.info( 'done!' );
+ }
+ }
+});
+</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/ZyzYXR?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <p>
+ If you wish to display some html content (for example, a message), then you can use a simpler syntax.
+ It is advised to use a wrapper around your content.
+ </p>
+
+ <pre><code>$.fancybox.open('<div class="message"><h2>Hello!</h2><p>You are awesome!</p></div>');</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/QgLbQY" target="_blank">View demo on CodePen</a>
+ </p>
+
+
+
+ <h3 id="instance_methods">Instance methods</h3>
+
+ <p>
+ In order to use these methods, you need an instance of the plugin's object.
+ </p>
+
+ <pre><code>var instance = $.fancybox.open(
+ // Your content and options
+);</code></pre>
+
+ <p>
+ Get reference to currently active instance:
+ </p>
+
+ <pre><code>var instance = $.fancybox.getInstance();</code></pre>
+
+ <p>
+ The first argument of the callback is reference to instance:
+ </p>
+
+ <pre><code>$("[data-fancybox]").fancybox({
+ afterShow : function( instance, current ) {
+ console.info( instance );
+ }
+});</code></pre>
+ <p>
+ Once you have a reference to fancyBox instance the following methods are available:
+ </p>
+
+
+ <pre><code>// Go to next gallery item
+instance.next( duration );
+
+// Go to previous gallery item
+instance.previous( duration );
+
+// Switch to selected gallery item
+instance.jumpTo( index, duration );
+
+// Check if current image dimensions are smaller than actual
+instance.isScaledDown();
+
+// Scale image to the actual size of the image
+instance.scaleToActual( x, y, duration );
+
+// Check if image dimensions exceed parent element
+instance.canPan();
+
+// Scale image to fit inside parent element
+instance.scaleToFit( duration );
+
+// Update position and content of all slides
+instance.update();
+
+// Update slide position and scale content to fit
+instance.updateSlide( slide );
+
+// Update infobar values, navigation button states and reveal caption
+instance.updateControls( force );
+
+// Load custom content into the slide
+instance.setContent( slide, content );
+
+// Show loading icon inside the slide
+instance.showLoading( slide );
+
+// Remove loading icon from the slide
+instance.hideLoading( slide );
+
+// Try to find and focus on the first focusable element
+instance.focus();
+
+// Activates current instance, brings it to the front
+instance.activate();
+
+// Close instance
+instance.close();
+</code></pre>
+
+
+ <p>
+ You can also do something like this:
+ </p>
+
+ <pre><code>$.fancybox.getInstance().jumpTo(1);</code></pre>
+
+ <p>
+ or simply:
+ </p>
+
+ <pre><code>$.fancybox.getInstance('jumpTo', 1);</code></pre>
+
+
+
+
+ <h3 id="events">Events</h3>
+
+ <p>
+ fancyBox fires several events:
+ </p>
+
+ <pre><code>beforeLoad : Before the content of a slide is being loaded
+afterLoad : When the content of a slide is done loading
+
+beforeShow : Before open animation starts
+afterShow : When content is done loading and animating
+
+beforeClose : Before the instance attempts to close. Return false to cancel the close.
+afterClose : After instance has been closed
+
+onInit : When instance has been initialized
+onActivate : When instance is brought to front
+onDeactivate : When other instance has been activated</code></pre>
+
+
+ <p>
+ Event callbacks can be set as function properties of the options object passed to fancyBox initialization function:
+ </p>
+
+ <pre><code><script type="text/javascript">
+ $("[data-fancybox]").fancybox({
+ afterShow: function( instance, slide ) {
+
+ // Tip: Each event passes useful information within the event object:
+
+ // Object containing references to interface elements
+ // (background, buttons, caption, etc)
+ // console.info( instance.$refs );
+
+ // Current slide options
+ // console.info( slide.opts );
+
+ // Clicked element
+ // console.info( slide.opts.$orig );
+
+ // Reference to DOM element of the slide
+ // console.info( slide.$slide );
+
+ }
+ });
+</script></code></pre>
+
+ <p>
+ Each callback receives two parameters - current fancyBox instance and current gallery object, if exists.
+ </p>
+
+ <p>
+ It is also possible to attach event handler for all instances.
+ To prevent interfering with other scripts, these events have been namespaced to <code>.fb</code>.
+ These handlers receive 3 parameters - event, current fancyBox instance and current gallery object.
+ </p>
+ <p>
+ Here is an example of binding to the <code>afterShow</code> event:
+ </p>
+
+ <pre><code>$(document).on('afterShow.fb', function( e, instance, slide ) {
+ // Your code goes here
+});</code></pre>
+
+
+ <p>
+ If you wish to prevent closing of the modal (for example, after form submit), you can use <code>beforeClose</code>
+ callback. Simply return <code>false</code>:
+ </p>
+
+ <pre><code>beforeClose : function( instance, current, e ) {
+ if ( $('#my-field').val() == '' ) {
+ return false;
+ }
+}
+</code></pre>
+
+ <h2 id="modules">Modules</h2>
+
+ <p>
+ fancyBox code is split into several files (modules) that extend core functionality.
+ You can build your own fancyBox version by excluding unnecessary modules, if needed.
+ Each one has their own <code>js</code> and/or <code>css</code> files.
+ </p>
+
+ <p>
+ Some modules can be customized and controlled programmatically.
+ List of all possible options:
+ </p>
+
+ <pre><code>fullScreen : {
+ autoStart : false,
+},
+
+touch : {
+ vertical : true, // Allow to drag content vertically
+ momentum : true // Continuous movement when panning
+},
+
+// Hash value when initializing manually,
+// set `false` to disable hash change
+hash : null,
+
+// Customize or add new media types
+// Example:
+/*
+media : {
+ youtube : {
+ params : {
+ autoplay : 0
+ }
+ }
+}
+*/
+media : {},
+
+slideShow : {
+ autoStart : false,
+ speed : 4000
+},
+
+thumbs : {
+ autoStart : false, // Display thumbnails on opening
+ hideOnClose : true // Hide thumbnail grid when closing animation starts
+}
+
+</code></pre>
+
+ <p>
+ Example (show thumbnails on start):
+ </p>
+
+ <pre><code>$('[data-fancybox="images"]').fancybox({
+ thumbs : {
+ autoStart : true
+ }
+})</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/WOeQMQ?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <p>
+ If you would inspect fancyBox instance object, you would find that same keys ar captialized - these are references for each module object.
+ Also, you would notice that fancyBox uses common naming convention to prefix jQuery objects with <code>$</code>.
+ </p>
+
+ <p>
+ This is how you, for example, can access thumbnail grid element:
+ </p>
+
+ <pre><code>$.fancybox.getInstance().Thumbs.$grid</code></pre>
+
+ <p>
+ This example shows how to call method that toggles thumbnails:
+ </p>
+
+ <pre><code>$.fancybox.getInstance().Thumbs.toggle();</code></pre>
+
+ <p>
+ List of available methods:
+ </p>
+
+ <pre><code>Thumbs.focus()
+Thumbs.update();
+Thumbs.hide();
+Thumbs.show();
+Thumbs.toggle();
+
+FullScreen.request( elem );
+FullScreen.exit();
+FullScreen.toggle( elem );
+FullScreen.isFullscreen();
+FullScreen.enabled();
+
+SlideShow.start();
+SlideShow.stop();
+SlideShow.toggle();
+</code></pre>
+
+ <p>
+ If you wish to disable hash module, use this snippet (after including JS file):
+ </p>
+
+ <pre><code>$.fancybox.defaults.hash = false;</code></pre>
+
+<!--
+
+FAQ
+===
+
+-->
+ <h2 id="faq">FAQ</h2>
+
+ <h3>Opening/closing causes fixed element to jump</h3>
+
+ <p>
+ Simply add <code>compensate-for-scrollbar</code> CSS class to your fixed positioned elements.
+ Example of using Bootstrap navbar component:
+ </p>
+
+ <pre><code><nav class="navbar navbar-inverse navbar-fixed-top compensate-for-scrollbar">
+ <div class="container">
+ ..
+ </div>
+</nav></code></pre>
+
+ <p>
+ The script measures width of the scrollbar and creates <code>compensate-for-scrollbar</code> CSS class
+ that uses this value for <code>margin-right</code> property.
+ Therefore, if your element has <code>width:100%</code>, you should positon it using <code>left</code> and <code>right</code> properties instead. Example:
+ </p>
+
+ <pre><code>.navbar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+}</code></pre>
+
+ <h3>How to customize caption</h3>
+
+ <p>
+ You can use <code>caption</code> option that accepts a function and is called for each group element. Example of appending image download link:
+ </p>
+
+ <pre><code>$( '[data-fancybox]' ).fancybox({
+ caption : function( instance, item ) {
+ var caption = $(this).data('caption') || '';
+
+ if ( item.type === 'image' ) {
+ caption = (caption.length ? caption + '<br />' : '') + '<a href="' + item.src + '">Download image</a>' ;
+ }
+
+ return caption;
+ }
+});</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/jwNbaW?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+
+ <p>
+ Add current image index and image count (the total number of images in the gallery) right in the caption:
+ </p>
+
+ <pre><code>$( '[data-fancybox]' ).fancybox({
+ caption : function( instance, item ) {
+ var caption = $(this).data('caption') || '';
+
+ return '(<span data-fancybox-index></span>/<span data-fancybox-count></span>)' + ( caption.length ? ' ' + caption : '' );
+ }
+});
+</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/LLWpgO?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+
+
+ <p>
+ Inside <code>caption</code> method, <code>this</code> refers to the clicked element. Example of using different source for caption:
+ </p>
+
+ <pre><code>$( '[data-fancybox]' ).fancybox({
+ caption : function( instance, item ) {
+ return $(this).find('figcaption').html();
+ }
+});</code></pre>
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/bRbVaG?editors=1010" target="_blank">View demo on CodePen</a>
+ </p>
+
+
+ <h3>How to create custom button in the toolbar</h3>
+
+ <p>
+ Example of creating reusable button and changing <code>href</code> property dynamically
+ </p>
+
+ <pre><code>// Create template for download button
+$.fancybox.defaults.btnTpl.download = '<a download class="fancybox-button fancybox-download"></a>';
+
+// Choose what buttons to display by default
+$.fancybox.defaults.buttons = [
+ 'slideShow',
+ 'fullScreen',
+ 'thumbs',
+ 'download',
+ 'close'
+];
+
+// Dynamically update download url
+$( '[data-fancybox]' ).fancybox({
+ beforeShow : function( instance, current ) {
+ $('.fancybox-download').attr('href', current.src);
+ }
+});
+</code></pre>
+
+ <p class="demo">
+ <a href="https://codepen.io/fancyapps/pen/JJPYLL" target="_blank">View demo on CodePen</a>
+ </p>
+
+ <h3>How to reposition thumbnail grid</h3>
+
+ <p>
+ There is currenty no JS option to change thumbnail grid position.
+ But fancyBox is designed so that you can use CSS to change position or dimension for each block
+ (e.g., content area, caption or thumbnail grid).
+ This gives you freedom to completely change the look and feel of the modal window, if needed.
+ <a href="https://codepen.io/fancyapps/pen/PjYPMw" target="_blank">View demo on CodePen</a>
+ </p>
+
+ </div>
+
+
+ </div>
+ </section>
+
+ <footer>
+ <div class="content">
+ <p>
+ <a href="javascript:;" onClick="javascript:$('html, body').animate({ scrollTop: 0 }, 0);return false;">Back to Top</a>
+ </p>
+ </div>
+ </footer>
+ <script>
+
+ /* Sticky nvigation */
+
+ var sticky = {
+ $sticky : $( '.sticky' ),
+ offsets : [],
+ targets : [],
+ stickyTop : null,
+
+ set : function() {
+ var self = this;
+
+ self.offsets = [];
+ self.targets = [];
+
+ // Get current top position of sticky element
+
+ self.stickyTop = self.$sticky.css( 'position', 'relative' ).offset().top;
+
+ // Cache all targets and their top positions
+
+ self.$sticky.find( 'a' ).map(function () {
+ var $el = $( this ),
+ href = $el.data('target') || $el.attr( 'href' ),
+ $href = /^#./.test(href) && $( href );
+
+ return $href && $href.length && $href.is( ':visible' ) ? [ [ Math.floor( $href.offset().top - parseInt( $href.css('margin-top') ) ), href ] ] : null;
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ self.offsets.push( this[ 0 ] );
+ self.targets.push( this[ 1 ] );
+ });
+
+ },
+
+ update : function() {
+ var self = this;
+
+ var windowTop = Math.floor( $(window).scrollTop() );
+ var $stickyLinks = self.$sticky.find( 'a' ).removeClass( 'active' );
+ var stickyPosition = 'fixed';
+ var currentIndex = 0;
+
+ // Toggle fixed position depending on visibility
+
+ if ( $(window).width() < 800 || self.stickyTop > windowTop ) {
+ stickyPosition = 'relative';
+
+ } else {
+
+ for ( var i = self.offsets.length; i--; ) {
+ if ( windowTop >= self.offsets[ i ] && ( self.offsets[ i + 1 ] === undefined || windowTop <= self.offsets[ i + 1 ]) ) {
+ currentIndex = i;
+
+ break;
+ }
+ }
+
+ }
+
+ self.$sticky.css( 'position', stickyPosition );
+
+ $stickyLinks.eq( currentIndex ).addClass( 'active' );
+
+ },
+
+ init : function() {
+ var self = this;
+
+ $(window).on('resize', function() {
+
+ self.set();
+
+ self.update();
+
+ });
+
+ $(window).on('scroll', function() {
+
+ self.update();
+
+ });
+
+ self.set();
+
+ self.update();
+
+ }
+ }
+
+ sticky.init();
+
+ </script>
+</body>
+</html>
--- /dev/null
+var gulp = require('gulp'),
+ livereload = require('gulp-livereload'),
+ concat = require('gulp-concat'),
+ uglify = require('gulp-uglify'),
+ rename = require('gulp-rename'),
+ cssnano = require('gulp-cssnano'),
+ sass = require('gulp-sass'),
+ autoprefixer = require('gulp-autoprefixer'),
+ header = require('gulp-header'),
+ replace = require('gulp-replace'),
+ gutil = require('gulp-util');
+
+var pkg = require('./package.json');
+var banner = ['// ==================================================',
+ '// fancyBox v${pkg.version}',
+ '//',
+ '// Licensed GPLv3 for open source use',
+ '// or fancyBox Commercial License for commercial use',
+ '//',
+ '// http://fancyapps.com/fancybox/',
+ '// Copyright ${new Date().getFullYear()} fancyApps',
+ '//',
+ '// ==================================================',
+ ''].join('\n');
+
+// Concatenate & Minify JS
+
+gulp.task('scripts', function() {
+ return gulp.src([
+ 'src/js/core.js',
+ 'src/js/media.js',
+ 'src/js/guestures.js',
+ 'src/js/slideshow.js',
+ 'src/js/fullscreen.js',
+ 'src/js/thumbs.js',
+ 'src/js/hash.js',
+ ])
+ .pipe(concat('jquery.fancybox.js'))
+ .pipe(replace(/({fancybox-version})/g, pkg.version))
+ .pipe(header(banner, { pkg : pkg } ))
+ .pipe(gulp.dest('dist'))
+ .pipe(rename({suffix: '.min'}))
+ .pipe(uglify())
+ .pipe(header(banner, { pkg : pkg } ))
+ .pipe(gulp.dest('dist'));
+ });
+
+
+// Compile CSS
+
+gulp.task('css', function() {
+ return gulp.src('src/css/*.css') // Gets all files src/css
+ .pipe(sass())
+ .pipe(autoprefixer({
+ browsers: ['last 5 versions'],
+ cascade: false
+ }))
+ .pipe(concat('jquery.fancybox.css'))
+ .pipe(gulp.dest('dist'))
+ .pipe(rename({suffix: '.min'}))
+ .pipe(cssnano({zindex: false}))
+ .pipe(gulp.dest('dist'));
+});
+
+// Default Task
+gulp.task('default', ['scripts', 'css']);
--- /dev/null
+{
+ "name": "@fancyapps/fancybox",
+ "description": "Touch enabled, responsive and fully customizable jQuery lightbox script",
+ "version": "3.1.24",
+ "homepage": "http://fancyapps.com/fancybox/",
+ "main": "./dist/jquery.fancybox.min.js",
+ "author": "fancyApps",
+ "license": "GPL-3.0",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/fancyapps/fancybox.git"
+ },
+ "peerDependencies": {
+ "jquery": ">=1.9.0"
+ },
+ "devDependencies": {
+ "del": "^2.2.2",
+ "gulp": "^3.9.1",
+ "gulp-autoprefixer": "^3.1.1",
+ "gulp-concat": "^2.6.1",
+ "gulp-cssnano": "^2.1.2",
+ "gulp-header": "^1.8.8",
+ "gulp-jshint": "^2.0.4",
+ "gulp-livereload": "^3.8.1",
+ "gulp-notify": "^2.2.0",
+ "gulp-rename": "^1.2.2",
+ "gulp-replace": "^0.5.4",
+ "gulp-sass": "^3.0.0",
+ "gulp-uglify": "^2.0.0",
+ "gulp-util": "^3.0.8",
+ "jshint": "^2.9.4"
+ },
+ "keywords": [
+ "touch",
+ "responsive",
+ "lightbox",
+ "fancybox",
+ "gallery",
+ "jQuery",
+ "plugin"
+ ],
+ "bugs": {
+ "url": "https://github.com/fancyapps/fancybox/issues"
+ },
+ "directories": {
+ "doc": "docs"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ }
+}
--- /dev/null
+.fancybox-enabled {
+ overflow: hidden;
+}
+
+.fancybox-enabled body {
+ overflow: visible;
+ height: 100%;
+}
+
+.fancybox-is-hidden {
+ position: absolute;
+ top: -9999px;
+ left: -9999px;
+ visibility: hidden;
+}
+
+.fancybox-container {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 99993;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ backface-visibility: hidden;
+ transform: translateZ(0);
+}
+
+/* Make sure that the first one is on the top */
+.fancybox-container ~ .fancybox-container {
+ z-index: 99992;
+}
+
+.fancybox-outer,
+.fancybox-inner,
+.fancybox-bg,
+.fancybox-stage {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+
+.fancybox-outer {
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+.fancybox-bg {
+ background: rgb(30,30,30);
+ opacity: 0;
+ transition-duration: inherit;
+ transition-property: opacity;
+ transition-timing-function: cubic-bezier(.47,0,.74,.71);
+}
+
+.fancybox-is-open .fancybox-bg {
+ opacity: 0.87;
+ transition-timing-function: cubic-bezier(.22,.61,.36,1);
+}
+
+.fancybox-infobar,
+.fancybox-toolbar,
+.fancybox-caption-wrap {
+ position: absolute;
+ direction: ltr;
+ z-index: 99997;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity .25s, visibility 0s linear .25s;
+ box-sizing: border-box;
+}
+
+.fancybox-show-infobar .fancybox-infobar,
+.fancybox-show-toolbar .fancybox-toolbar,
+.fancybox-show-caption .fancybox-caption-wrap {
+ opacity: 1;
+ visibility: visible;
+ transition: opacity .25s, visibility 0s;
+}
+
+.fancybox-infobar {
+ top: 0;
+ left : 50%;
+ margin-left: -79px;
+}
+
+.fancybox-infobar__body {
+ display: inline-block;
+ width: 70px;
+ line-height: 44px;
+ font-size: 13px;
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+ text-align: center;
+ color: #ddd;
+ background-color: rgba(30,30,30,0.7);
+ pointer-events: none;
+ user-select: none;
+ -webkit-touch-callout: none;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ -webkit-font-smoothing: subpixel-antialiased;
+}
+
+.fancybox-toolbar {
+ top: 0;
+ right: 0;
+}
+
+.fancybox-stage {
+ overflow: hidden;
+ direction: ltr;
+ z-index: 99994;
+ -webkit-transform: translate3d(0, 0, 0);
+}
+
+.fancybox-slide {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ overflow: auto;
+ outline: none;
+ white-space: normal;
+ box-sizing: border-box;
+ text-align: center;
+ z-index: 99994;
+ -webkit-overflow-scrolling: touch;
+ display: none;
+ backface-visibility: hidden;
+ transition-property: transform, opacity;
+ transform-style: preserve-3d;
+}
+
+.fancybox-slide::before {
+ content: '';
+ display: inline-block;
+ vertical-align: middle;
+ height: 100%;
+ width: 0;
+}
+
+.fancybox-is-sliding .fancybox-slide,
+.fancybox-slide--previous,
+.fancybox-slide--current,
+.fancybox-slide--next {
+ display: block;
+}
+
+.fancybox-slide--image {
+ overflow: visible;
+}
+
+.fancybox-slide--image::before {
+ display: none;
+}
+
+.fancybox-slide--video .fancybox-content,
+.fancybox-slide--video iframe {
+ background: #000;
+}
+
+.fancybox-slide--map .fancybox-content,
+.fancybox-slide--map iframe {
+ background: #E5E3DF;
+}
+
+.fancybox-slide--next {
+ z-index: 99995;
+}
+
+.fancybox-slide > * {
+ display: inline-block;
+ position: relative;
+ padding: 24px;
+ margin: 44px 0 44px;
+ border-width: 0;
+ vertical-align: middle;
+ text-align: left;
+ background-color: #fff;
+ overflow: auto;
+ box-sizing: border-box;
+}
+
+.fancybox-slide .fancybox-image-wrap {
+ position: absolute;
+ top: 0;
+ left: 0;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ z-index: 99995;
+ background: transparent;
+ cursor: default;
+ overflow: visible;
+ transform-origin: top left;
+ background-size: 100% 100%;
+ background-repeat: no-repeat;
+ backface-visibility: hidden;
+}
+
+.fancybox-can-zoomOut .fancybox-image-wrap {
+ cursor: zoom-out;
+}
+
+.fancybox-can-zoomIn .fancybox-image-wrap {
+ cursor: zoom-in;
+}
+
+.fancybox-can-drag .fancybox-image-wrap {
+ cursor: grab;
+}
+
+.fancybox-is-dragging .fancybox-image-wrap {
+ cursor: grabbing;
+}
+
+.fancybox-image,
+.fancybox-spaceball {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ max-width: none;
+ max-height: none;
+}
+
+ .fancybox-spaceball {
+ z-index: 1;
+}
+
+.fancybox-slide--iframe .fancybox-content {
+ padding: 0;
+ width: 80%;
+ height: 80%;
+ max-width: calc(100% - 100px);
+ max-height: calc(100% - 88px);
+ overflow: visible;
+ background: #fff;
+}
+
+.fancybox-iframe {
+ display: block;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ width: 100%;
+ height: 100%;
+ background: #fff;
+}
+
+.fancybox-error {
+ margin: 0;
+ padding: 40px;
+ width: 100%;
+ max-width: 380px;
+ background: #fff;
+ cursor: default;
+}
+
+.fancybox-error p {
+ margin: 0;
+ padding: 0;
+ color: #444;
+ font: 16px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
+}
+
+.fancybox-close-small {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 44px;
+ height: 44px;
+ padding: 0;
+ margin: 0;
+ border: 0;
+ border-radius: 0;
+ outline: none;
+ background: transparent;
+ z-index: 10;
+ cursor: pointer;
+}
+
+.fancybox-close-small:after {
+ content: '×';
+ position: absolute;
+ top : 5px;
+ right: 5px;
+ width: 30px;
+ height: 30px;
+ font: 20px/30px Arial,"Helvetica Neue",Helvetica,sans-serif;
+ color: #888;
+ font-weight: 300;
+ text-align: center;
+ border-radius: 50%;
+ border-width: 0;
+ background: #fff;
+ transition: background .25s;
+ box-sizing: border-box;
+ z-index: 2;
+}
+
+.fancybox-close-small:focus:after {
+ outline: 1px dotted #888;
+}
+
+.fancybox-close-small:hover:after {
+ color: #555;
+ background: #eee;
+}
+
+.fancybox-slide--iframe .fancybox-close-small {
+ top : 0;
+ right : -44px;
+}
+
+.fancybox-slide--iframe .fancybox-close-small:after {
+ background: transparent;
+ font-size: 35px;
+ color: #aaa;
+}
+
+.fancybox-slide--iframe .fancybox-close-small:hover:after {
+ color: #fff;
+}
+
+
+/* Caption */
+
+.fancybox-caption-wrap {
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 60px 30px 0 30px;
+ background: linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.1) 20%, rgba(0,0,0,0.2) 40%,rgba(0,0,0,0.6) 80%, rgba(0,0,0,0.8) 100%);
+ pointer-events: none;
+}
+
+.fancybox-caption {
+ padding: 30px 0;
+ border-top: 1px solid rgba(255,255,255,0.4);
+ font-size: 14px;
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+ color: #fff;
+ line-height: 20px;
+ -webkit-text-size-adjust: none;
+}
+
+.fancybox-caption a,
+.fancybox-caption button,
+.fancybox-caption select {
+ pointer-events: all;
+}
+
+.fancybox-caption a {
+ color: #fff;
+ text-decoration: underline;
+}
+
+
+/* Buttons */
+
+.fancybox-button {
+ display: inline-block;
+ position: relative;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ width: 44px;
+ height: 44px;
+ line-height: 44px;
+ text-align: center;
+ background: transparent;
+ color: #ddd;
+ border-radius: 0;
+ cursor: pointer;
+ vertical-align: top;
+ outline: none;
+}
+
+.fancybox-button[disabled] {
+ cursor: default;
+ pointer-events: none;
+}
+
+.fancybox-infobar__body, .fancybox-button {
+ background: rgba(30,30,30,0.6);
+}
+
+.fancybox-button:hover:not([disabled]) {
+ color: #fff;
+ background: rgba(0,0,0,0.8);
+}
+
+.fancybox-button::before,
+.fancybox-button::after {
+ content: '';
+ pointer-events: none;
+ position: absolute;
+ background-color: currentColor;
+ color: currentColor;
+ opacity: 0.9;
+ box-sizing: border-box;
+ display: inline-block;
+}
+
+.fancybox-button[disabled]::before,
+.fancybox-button[disabled]::after {
+ opacity: 0.3;
+}
+
+.fancybox-button--left::after,
+.fancybox-button--right::after {
+ top: 18px;
+ width: 6px;
+ height: 6px;
+ background: transparent;
+ border-top: solid 2px currentColor;
+ border-right: solid 2px currentColor;
+}
+
+.fancybox-button--left::after {
+ left: 20px;
+ transform: rotate(-135deg);
+}
+
+.fancybox-button--right::after {
+ right: 20px;
+ transform: rotate(45deg);
+}
+
+.fancybox-button--left {
+ border-bottom-left-radius: 5px;
+}
+
+.fancybox-button--right {
+ border-bottom-right-radius: 5px;
+}
+
+.fancybox-button--close::before, .fancybox-button--close::after {
+ content: '';
+ display: inline-block;
+ position: absolute;
+ height: 2px;
+ width: 16px;
+ top: calc(50% - 1px);
+ left: calc(50% - 8px);
+}
+
+.fancybox-button--close::before {
+ transform: rotate(45deg);
+}
+
+.fancybox-button--close::after {
+ transform: rotate(-45deg);
+}
+
+
+/* Navigation arrows */
+
+.fancybox-arrow {
+ position: absolute;
+ top: 50%;
+ margin: -50px 0 0 0;
+ height: 100px;
+ width: 54px;
+ padding: 0;
+ border: 0;
+ outline: none;
+ background: none;
+ cursor: pointer;
+ z-index: 99995;
+ opacity: 0;
+ user-select: none;
+ transition: opacity .25s;
+}
+
+.fancybox-arrow::after {
+ content : '';
+ position: absolute;
+ top: 28px;
+ width: 44px;
+ height: 44px;
+ background-color: rgba(30,30,30,0.8);
+ background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiBoZWlnaHQ9IjQ4IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSI0OCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPiAgICA8cGF0aCBkPSJNMTIgNGwtMS40MSAxLjQxTDE2LjE3IDExSDR2MmgxMi4xN2wtNS41OCA1LjU5TDEyIDIwbDgtOHoiLz48L3N2Zz4=);
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-size: 24px 24px;
+}
+
+.fancybox-arrow--right {
+ right: 0;
+}
+
+.fancybox-arrow--left {
+ left: 0;
+ transform: scaleX(-1);
+}
+
+.fancybox-arrow--right::after,
+.fancybox-arrow--left::after {
+ left: 0;
+}
+
+.fancybox-show-nav .fancybox-arrow {
+ opacity: 0.6;
+}
+
+.fancybox-show-nav .fancybox-arrow[disabled] {
+ opacity: 0.3;
+}
+
+
+/* Loading indicator */
+
+.fancybox-loading {
+ border: 6px solid rgba(100, 100, 100, .4);
+ border-top: 6px solid rgba(255, 255, 255, .6);
+ border-radius: 100%;
+ height: 50px;
+ width: 50px;
+ animation: fancybox-rotate .8s infinite linear;
+ background: transparent;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -25px;
+ margin-left: -25px;
+ z-index: 99999;
+}
+
+@keyframes fancybox-rotate {
+ from { transform: rotate( 0deg ); }
+ to { transform: rotate( 359deg ); }
+}
+
+
+/* Transition effects */
+
+.fancybox-animated {
+ transition-timing-function: cubic-bezier(0, 0, 0.25, 1);
+}
+
+/* transitionEffect: slide */
+
+.fancybox-fx-slide.fancybox-slide--previous {
+ transform: translate3d(-100%, 0, 0);
+ opacity: 0;
+}
+
+.fancybox-fx-slide.fancybox-slide--next {
+ transform: translate3d(100%, 0, 0);
+ opacity: 0;
+}
+
+.fancybox-fx-slide.fancybox-slide--current {
+ transform: translate3d(0, 0, 0);
+ opacity: 1;
+}
+
+/* transitionEffect: fade */
+
+.fancybox-fx-fade.fancybox-slide--previous,
+.fancybox-fx-fade.fancybox-slide--next {
+ opacity: 0;
+ transition-timing-function: cubic-bezier(.19,1,.22,1);
+}
+
+.fancybox-fx-fade.fancybox-slide--current {
+ opacity: 1;
+}
+
+/* transitionEffect: zoom-in-out */
+
+.fancybox-fx-zoom-in-out.fancybox-slide--previous {
+ transform: scale3d(1.5, 1.5, 1.5);
+ opacity: 0;
+}
+
+.fancybox-fx-zoom-in-out.fancybox-slide--next {
+ transform: scale3d(0.5, 0.5, 0.5);
+ opacity: 0;
+}
+
+.fancybox-fx-zoom-in-out.fancybox-slide--current {
+ transform: scale3d(1, 1, 1);
+ opacity: 1;
+}
+
+/* transitionEffect: rotate */
+
+.fancybox-fx-rotate.fancybox-slide--previous {
+ transform: rotate(-360deg);
+ opacity: 0;
+}
+
+.fancybox-fx-rotate.fancybox-slide--next {
+ transform: rotate(360deg);
+ opacity: 0;
+}
+
+.fancybox-fx-rotate.fancybox-slide--current {
+ transform: rotate(0deg);
+ opacity: 1;
+}
+
+/* transitionEffect: circular */
+
+.fancybox-fx-circular.fancybox-slide--previous {
+ transform: scale3d(0, 0, 0) translate3d(-100%, 0, 0);
+ opacity: 0;
+}
+
+.fancybox-fx-circular.fancybox-slide--next {
+ transform: scale3d(0, 0, 0) translate3d(100%, 0, 0);
+ opacity: 0;
+}
+
+.fancybox-fx-circular.fancybox-slide--current {
+ transform: scale3d(1, 1, 1) translate3d(0, 0, 0);
+ opacity: 1;
+}
+
+/* transitionEffect: tube */
+
+.fancybox-fx-tube.fancybox-slide--previous {
+ transform: translate3d(-100%, 0, 0) scale(0.1) skew(-10deg);
+}
+
+.fancybox-fx-tube.fancybox-slide--next {
+ transform: translate3d(100%, 0, 0) scale(0.1) skew(10deg);
+}
+
+.fancybox-fx-tube.fancybox-slide--current {
+ transform: translate3d(0, 0, 0) scale(1);
+}
+
+
+/* Styling for Small-Screen Devices */
+
+@media all and (max-width: 800px) {
+
+ .fancybox-infobar {
+ left: 0;
+ margin-left: 0;
+ }
+
+ .fancybox-button--left,
+ .fancybox-button--right {
+ display: none !important;
+ }
+
+ .fancybox-caption {
+ padding: 20px 0;
+ margin: 0;
+ }
+}
--- /dev/null
+
+/* Fullscreen */
+
+.fancybox-button--fullscreen::before {
+ width: 15px;
+ height: 11px;
+ left: calc(50% - 7px);
+ top: calc(50% - 6px);
+ border: 2px solid;
+ background: none;
+}
--- /dev/null
+/* Slideshow button */
+
+.fancybox-button--play {}
+
+.fancybox-button--play::before,
+.fancybox-button--pause::before {
+ top: calc(50% - 6px);
+ left: calc(50% - 4px);
+ background: transparent;
+}
+
+.fancybox-button--play::before {
+ width: 0;
+ height: 0;
+ border-top: 6px inset transparent;
+ border-bottom: 6px inset transparent;
+ border-left: 10px solid;
+ border-radius: 1px;
+}
+
+.fancybox-button--pause::before {
+ width: 7px;
+ height: 11px;
+ border-style: solid;
+ border-width: 0 2px 0 2px;
+}
--- /dev/null
+
+/* Thumbs */
+
+.fancybox-thumbs {
+ display: none;
+}
+
+.fancybox-button--thumbs {
+ display: none;
+}
+
+@media all and (min-width: 800px) {
+
+ .fancybox-button--thumbs {
+ display: inline-block;
+ }
+
+ .fancybox-button--thumbs span {
+ font-size: 23px;
+ }
+
+ .fancybox-button--thumbs::before {
+ width: 3px;
+ height: 3px;
+ top: calc(50% - 2px);
+ left: calc(50% - 2px);
+ box-shadow: 0 -4px 0, -4px -4px 0, 4px -4px 0, 0 0 0 32px inset, -4px 0 0, 4px 0 0, 0 4px 0, -4px 4px 0, 4px 4px 0;
+ }
+
+ .fancybox-thumbs {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: auto;
+ width: 220px;
+ margin: 0;
+ padding: 5px 5px 0 0;
+ background: #fff;
+ word-break: normal;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ -webkit-overflow-scrolling: touch;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ box-sizing: border-box;
+ z-index: 99995;
+ }
+
+ .fancybox-show-thumbs .fancybox-thumbs {
+ display: block;
+ }
+
+ .fancybox-show-thumbs .fancybox-inner {
+ right: 220px;
+ }
+
+ .fancybox-thumbs > ul {
+ list-style: none;
+ position: absolute;
+ position: relative;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ overflow-x: hidden;
+ overflow-y: auto;
+ font-size: 0;
+ }
+
+ .fancybox-thumbs > ul > li {
+ float: left;
+ overflow: hidden;
+ max-width: 50%;
+ padding: 0;
+ margin: 0;
+ width: 105px;
+ height: 75px;
+ position: relative;
+ cursor: pointer;
+ outline: none;
+ border: 5px solid transparent;
+ border-top-width: 0;
+ border-right-width: 0;
+ -webkit-tap-highlight-color: transparent;
+ backface-visibility: hidden;
+ box-sizing: border-box;
+ }
+
+ li.fancybox-thumbs-loading {
+ background: rgba(0,0,0,0.1);
+ }
+
+ .fancybox-thumbs > ul > li > img {
+ position: absolute;
+ top: 0;
+ left: 0;
+ min-width: 100%;
+ min-height: 100%;
+ max-width: none;
+ max-height: none;
+ -webkit-touch-callout: none;
+ user-select: none;
+ }
+
+ .fancybox-thumbs > ul > li:before {
+ content:'';
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ border-radius: 2px;
+ border: 4px solid #4ea7f9;
+ z-index: 99991;
+ opacity: 0;
+ transition: all 0.2s cubic-bezier(.25,.46,.45,.94);
+ }
+
+ .fancybox-thumbs > ul > li.fancybox-thumbs-active:before {
+ opacity: 1;
+ }
+
+}
--- /dev/null
+;(function (window, document, $, undefined) {
+ 'use strict';
+
+ // If there's no jQuery, fancyBox can't work
+ // =========================================
+
+ if ( !$ ) {
+ return;
+ }
+
+ // Check if fancyBox is already initialized
+ // ========================================
+
+ if ( $.fn.fancybox ) {
+
+ $.error('fancyBox already initialized');
+
+ return;
+ }
+
+ // Private default settings
+ // ========================
+
+ var defaults = {
+
+ // Enable infinite gallery navigation
+ loop : false,
+
+ // Space around image, ignored if zoomed-in or viewport smaller than 800px
+ margin : [44, 0],
+
+ // Horizontal space between slides
+ gutter : 50,
+
+ // Enable keyboard navigation
+ keyboard : true,
+
+ // Should display navigation arrows at the screen edges
+ arrows : true,
+
+ // Should display infobar (counter and arrows at the top)
+ infobar : false,
+
+ // Should display toolbar (buttons at the top)
+ toolbar : true,
+
+ // What buttons should appear in the top right corner.
+ // Buttons will be created using templates from `btnTpl` option
+ // and they will be placed into toolbar (class="fancybox-toolbar"` element)
+ buttons : [
+ 'slideShow',
+ 'fullScreen',
+ 'thumbs',
+ 'close'
+ ],
+
+ // Detect "idle" time in seconds
+ idleTime : 4,
+
+ // Should display buttons at top right corner of the content
+ // If 'auto' - they will be created for content having type 'html', 'inline' or 'ajax'
+ // Use template from `btnTpl.smallBtn` for customization
+ smallBtn : 'auto',
+
+ // Disable right-click and use simple image protection for images
+ protect : false,
+
+ // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
+ modal : false,
+
+ image : {
+
+ // Wait for images to load before displaying
+ // Requires predefined image dimensions
+ // If 'auto' - will zoom in thumbnail if 'width' and 'height' attributes are found
+ preload : "auto",
+
+ },
+
+ ajax : {
+
+ // Object containing settings for ajax request
+ settings : {
+
+ // This helps to indicate that request comes from the modal
+ // Feel free to change naming
+ data : {
+ fancybox : true
+ }
+ }
+
+ },
+
+ iframe : {
+
+ // Iframe template
+ tpl : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen allowtransparency="true" src=""></iframe>',
+
+ // Preload iframe before displaying it
+ // This allows to calculate iframe content width and height
+ // (note: Due to "Same Origin Policy", you can't get cross domain data).
+ preload : true,
+
+ // Custom CSS styling for iframe wrapping element
+ // You can use this to set custom iframe dimensions
+ css : {},
+
+ // Iframe tag attributes
+ attr : {
+ scrolling : 'auto'
+ }
+
+ },
+
+ // Open/close animation type
+ // Possible values:
+ // false - disable
+ // "zoom" - zoom images from/to thumbnail
+ // "fade"
+ // "zoom-in-out"
+ //
+ animationEffect : "zoom",
+
+ // Duration in ms for open/close animation
+ animationDuration : 366,
+
+ // Should image change opacity while zooming
+ // If opacity is 'auto', then opacity will be changed if image and thumbnail have different aspect ratios
+ zoomOpacity : 'auto',
+
+ // Transition effect between slides
+ //
+ // Possible values:
+ // false - disable
+ // "fade'
+ // "slide'
+ // "circular'
+ // "tube'
+ // "zoom-in-out'
+ // "rotate'
+ //
+ transitionEffect : "fade",
+
+ // Duration in ms for transition animation
+ transitionDuration : 366,
+
+ // Custom CSS class for slide element
+ slideClass : '',
+
+ // Custom CSS class for layout
+ baseClass : '',
+
+ // Base template for layout
+ baseTpl :
+ '<div class="fancybox-container" role="dialog" tabindex="-1">' +
+ '<div class="fancybox-bg"></div>' +
+ '<div class="fancybox-inner">' +
+ '<div class="fancybox-infobar">' +
+ '<button data-fancybox-prev title="{{PREV}}" class="fancybox-button fancybox-button--left"></button>' +
+ '<div class="fancybox-infobar__body">' +
+ '<span data-fancybox-index></span> / <span data-fancybox-count></span>' +
+ '</div>' +
+ '<button data-fancybox-next title="{{NEXT}}" class="fancybox-button fancybox-button--right"></button>' +
+ '</div>' +
+ '<div class="fancybox-toolbar">' +
+ '{{BUTTONS}}' +
+ '</div>' +
+ '<div class="fancybox-navigation">' +
+ '<button data-fancybox-prev title="{{PREV}}" class="fancybox-arrow fancybox-arrow--left" />' +
+ '<button data-fancybox-next title="{{NEXT}}" class="fancybox-arrow fancybox-arrow--right" />' +
+ '</div>' +
+ '<div class="fancybox-stage"></div>' +
+ '<div class="fancybox-caption-wrap">' +
+ '<div class="fancybox-caption"></div>' +
+ '</div>' +
+ '</div>' +
+ '</div>',
+
+ // Loading indicator template
+ spinnerTpl : '<div class="fancybox-loading"></div>',
+
+ // Error message template
+ errorTpl : '<div class="fancybox-error"><p>{{ERROR}}<p></div>',
+
+ btnTpl : {
+ slideShow : '<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}"></button>',
+ fullScreen : '<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fullscreen" title="{{FULL_SCREEN}}"></button>',
+ thumbs : '<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}"></button>',
+ close : '<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}"></button>',
+
+ // This small close button will be appended to your html/inline/ajax content by default,
+ // if "smallBtn" option is not set to false
+ smallBtn : '<button data-fancybox-close class="fancybox-close-small" title="{{CLOSE}}"></button>'
+ },
+
+ // Container is injected into this element
+ parentEl : 'body',
+
+
+ // Focus handling
+ // ==============
+
+ // Try to focus on the first focusable element after opening
+ autoFocus : true,
+
+ // Put focus back to active element after closing
+ backFocus : true,
+
+ // Do not let user to focus on element outside modal content
+ trapFocus : true,
+
+
+ // Module specific options
+ // =======================
+
+ fullScreen : {
+ autoStart : false,
+ },
+
+ touch : {
+ vertical : true, // Allow to drag content vertically
+ momentum : true // Continue movement after releasing mouse/touch when panning
+ },
+
+ // Hash value when initializing manually,
+ // set `false` to disable hash change
+ hash : null,
+
+ // Customize or add new media types
+ // Example:
+ /*
+ media : {
+ youtube : {
+ params : {
+ autoplay : 0
+ }
+ }
+ }
+ */
+ media : {},
+
+ slideShow : {
+ autoStart : false,
+ speed : 4000
+ },
+
+ thumbs : {
+ autoStart : false, // Display thumbnails on opening
+ hideOnClose : true // Hide thumbnail grid when closing animation starts
+ },
+
+ // Callbacks
+ //==========
+
+ // See Documentation/API/Events for more information
+ // Example:
+ /*
+ afterShow: function( instance, current ) {
+ console.info( 'Clicked element:' );
+ console.info( current.opts.$orig );
+ }
+ */
+
+ onInit : $.noop, // When instance has been initialized
+
+ beforeLoad : $.noop, // Before the content of a slide is being loaded
+ afterLoad : $.noop, // When the content of a slide is done loading
+
+ beforeShow : $.noop, // Before open animation starts
+ afterShow : $.noop, // When content is done loading and animating
+
+ beforeClose : $.noop, // Before the instance attempts to close. Return false to cancel the close.
+ afterClose : $.noop, // After instance has been closed
+
+ onActivate : $.noop, // When instance is brought to front
+ onDeactivate : $.noop, // When other instance has been activated
+
+
+ // Interaction
+ // ===========
+
+ // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
+ // each option can be string or method that returns value.
+ //
+ // Possible values:
+ // "close" - close instance
+ // "next" - move to next gallery item
+ // "nextOrClose" - move to next gallery item or close if gallery has only one item
+ // "toggleControls" - show/hide controls
+ // "zoom" - zoom image (if loaded)
+ // false - do nothing
+
+ // Clicked on the content
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+
+ // Clicked on the slide
+ clickSlide : 'close',
+
+ // Clicked on the background (backdrop) element
+ clickOutside : 'close',
+
+ // Same as previous two, but for double click
+ dblclickContent : false,
+ dblclickSlide : false,
+ dblclickOutside : false,
+
+
+ // Custom options when mobile device is detected
+ // =============================================
+
+ mobile : {
+ clickContent : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : false;
+ },
+ clickSlide : function( current, event ) {
+ return current.type === 'image' ? 'toggleControls' : "close";
+ },
+ dblclickContent : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ },
+ dblclickSlide : function( current, event ) {
+ return current.type === 'image' ? 'zoom' : false;
+ }
+ },
+
+
+ // Internationalization
+ // ============
+
+ lang : 'en',
+ i18n : {
+ 'en' : {
+ CLOSE : 'Close',
+ NEXT : 'Next',
+ PREV : 'Previous',
+ ERROR : 'The requested content cannot be loaded. <br/> Please try again later.',
+ PLAY_START : 'Start slideshow',
+ PLAY_STOP : 'Pause slideshow',
+ FULL_SCREEN : 'Full screen',
+ THUMBS : 'Thumbnails'
+ },
+ 'de' : {
+ CLOSE : 'Schliessen',
+ NEXT : 'Weiter',
+ PREV : 'Zurück',
+ ERROR : 'Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es später nochmal.',
+ PLAY_START : 'Diaschau starten',
+ PLAY_STOP : 'Diaschau beenden',
+ FULL_SCREEN : 'Vollbild',
+ THUMBS : 'Vorschaubilder'
+ }
+ }
+
+ };
+
+ // Few useful variables and methods
+ // ================================
+
+ var $W = $(window);
+ var $D = $(document);
+
+ var called = 0;
+
+
+ // Check if an object is a jQuery object and not a native JavaScript object
+ // ========================================================================
+
+ var isQuery = function ( obj ) {
+ return obj && obj.hasOwnProperty && obj instanceof $;
+ };
+
+
+ // Handle multiple browsers for "requestAnimationFrame" and "cancelAnimationFrame"
+ // ===============================================================================
+
+ var requestAFrame = (function () {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ // if all else fails, use setTimeout
+ function (callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })();
+
+
+ // Detect the supported transition-end event property name
+ // =======================================================
+
+ var transitionEnd = (function () {
+ var t, el = document.createElement("fakeelement");
+
+ var transitions = {
+ "transition" : "transitionend",
+ "OTransition" : "oTransitionEnd",
+ "MozTransition" : "transitionend",
+ "WebkitTransition": "webkitTransitionEnd"
+ };
+
+ for (t in transitions) {
+ if (el.style[t] !== undefined){
+ return transitions[t];
+ }
+ }
+ })();
+
+
+ // Force redraw on an element.
+ // This helps in cases where the browser doesn't redraw an updated element properly.
+ // =================================================================================
+
+ var forceRedraw = function( $el ) {
+ return ( $el && $el.length && $el[0].offsetHeight );
+ };
+
+
+ // Class definition
+ // ================
+
+ var FancyBox = function( content, opts, index ) {
+ var self = this;
+
+ self.opts = $.extend( true, { index : index }, defaults, opts || {} );
+
+ // Exclude buttons option from deep merging
+ if ( opts && $.isArray( opts.buttons ) ) {
+ self.opts.buttons = opts.buttons;
+ }
+
+ self.id = self.opts.id || ++called;
+ self.group = [];
+
+ self.currIndex = parseInt( self.opts.index, 10 ) || 0;
+ self.prevIndex = null;
+
+ self.prevPos = null;
+ self.currPos = 0;
+
+ self.firstRun = null;
+
+ // Create group elements from original item collection
+ self.createGroup( content );
+
+ if ( !self.group.length ) {
+ return;
+ }
+
+ // Save last active element and current scroll position
+ self.$lastFocus = $(document.activeElement).blur();
+
+ // Collection of gallery objects
+ self.slides = {};
+
+ self.init( content );
+
+ };
+
+ $.extend(FancyBox.prototype, {
+
+ // Create DOM structure
+ // ====================
+
+ init : function() {
+ var self = this;
+
+ var testWidth, $container, buttonStr;
+
+ var firstItemOpts = self.group[ self.currIndex ].opts;
+
+ self.scrollTop = $D.scrollTop();
+ self.scrollLeft = $D.scrollLeft();
+
+
+ // Hide scrollbars
+ // ===============
+
+ if ( !$.fancybox.getInstance() && !$.fancybox.isMobile && $( 'body' ).css('overflow') !== 'hidden' ) {
+ testWidth = $( 'body' ).width();
+
+ $( 'html' ).addClass( 'fancybox-enabled' );
+
+ // Compare body width after applying "overflow: hidden"
+ testWidth = $( 'body' ).width() - testWidth;
+
+ // If width has changed - compensate missing scrollbars by adding right margin
+ if ( testWidth > 1 ) {
+ $( 'head' ).append( '<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar, .fancybox-enabled body { margin-right: ' + testWidth + 'px; }</style>' );
+ }
+ }
+
+
+ // Build html markup and set references
+ // ====================================
+
+ // Build html code for buttons and insert into main template
+ buttonStr = '';
+
+ $.each( firstItemOpts.buttons, function( index, value ) {
+ buttonStr += ( firstItemOpts.btnTpl[ value ] || '' );
+ });
+
+ // Create markup from base template, it will be initially hidden to
+ // avoid unnecessary work like painting while initializing is not complete
+ $container = $( self.translate( self, firstItemOpts.baseTpl.replace( '\{\{BUTTONS\}\}', buttonStr ) ) )
+ .addClass( 'fancybox-is-hidden' )
+ .attr('id', 'fancybox-container-' + self.id)
+ .addClass( firstItemOpts.baseClass )
+ .data( 'FancyBox', self )
+ .prependTo( firstItemOpts.parentEl );
+
+ // Create object holding references to jQuery wrapped nodes
+ self.$refs = {
+ container : $container
+ };
+
+ [ 'bg', 'inner', 'infobar', 'toolbar', 'stage', 'caption' ].forEach(function(item) {
+ self.$refs[ item ] = $container.find( '.fancybox-' + item );
+ });
+
+ // Check for redundant elements
+ if ( !firstItemOpts.arrows || self.group.length < 2 ) {
+ $container.find('.fancybox-navigation').remove();
+ }
+
+ if ( !firstItemOpts.infobar ) {
+ self.$refs.infobar.remove();
+ }
+
+ if ( !firstItemOpts.toolbar ) {
+ self.$refs.toolbar.remove();
+ }
+
+ self.trigger( 'onInit' );
+
+ // Bring to front and enable events
+ self.activate();
+
+ // Build slides, load and reveal content
+ self.jumpTo( self.currIndex );
+ },
+
+
+ // Simple i18n support - replaces object keys found in template
+ // with corresponding values
+ // ============================================================
+
+ translate : function( obj, str ) {
+ var arr = obj.opts.i18n[ obj.opts.lang ];
+
+ return str.replace(/\{\{(\w+)\}\}/g, function(match, n) {
+ var value = arr[n];
+
+ if ( value === undefined ) {
+ return match;
+ }
+
+ return value;
+ });
+ },
+
+ // Create array of gally item objects
+ // Check if each object has valid type and content
+ // ===============================================
+
+ createGroup : function ( content ) {
+ var self = this;
+ var items = $.makeArray( content );
+
+ $.each(items, function( i, item ) {
+ var obj = {},
+ opts = {},
+ data = [],
+ $item,
+ type,
+ src,
+ srcParts;
+
+ // Step 1 - Make sure we have an object
+ // ====================================
+
+ if ( $.isPlainObject( item ) ) {
+
+ // We probably have manual usage here, something like
+ // $.fancybox.open( [ { src : "image.jpg", type : "image" } ] )
+
+ obj = item;
+ opts = item.opts || item;
+
+ } else if ( $.type( item ) === 'object' && $( item ).length ) {
+
+ // Here we propbably have jQuery collection returned by some selector
+
+ $item = $( item );
+ data = $item.data();
+
+ opts = 'options' in data ? data.options : {};
+ opts = $.type( opts ) === 'object' ? opts : {};
+
+ obj.src = 'src' in data ? data.src : ( opts.src || $item.attr( 'href' ) );
+
+ [ 'width', 'height', 'thumb', 'type', 'filter' ].forEach(function(item) {
+ if ( item in data ) {
+ opts[ item ] = data[ item ];
+ }
+ });
+
+ if ( 'srcset' in data ) {
+ opts.image = { srcset : data.srcset };
+ }
+
+ opts.$orig = $item;
+
+ if ( !obj.type && !obj.src ) {
+ obj.type = 'inline';
+ obj.src = item;
+ }
+
+ } else {
+
+ // Assume we have a simple html code, for example:
+ // $.fancybox.open( '<div><h1>Hi!</h1></div>' );
+
+ obj = {
+ type : 'html',
+ src : item + ''
+ };
+
+ }
+
+ // Each gallery object has full collection of options
+ obj.opts = $.extend( true, {}, self.opts, opts );
+
+ if ( $.fancybox.isMobile ) {
+ obj.opts = $.extend( true, {}, obj.opts, obj.opts.mobile );
+ }
+
+
+ // Step 2 - Make sure we have content type, if not - try to guess
+ // ==============================================================
+
+ type = obj.type || obj.opts.type;
+ src = obj.src || '';
+
+ if ( !type && src ) {
+ if ( src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i) ) {
+ type = 'image';
+
+ } else if ( src.match(/\.(pdf)((\?|#).*)?$/i) ) {
+ type = 'pdf';
+
+ } else if ( src.charAt(0) === '#' ) {
+ type = 'inline';
+ }
+ }
+
+ obj.type = type;
+
+
+ // Step 3 - Some adjustments
+ // =========================
+
+ obj.index = self.group.length;
+
+ // Check if $orig and $thumb objects exist
+ if ( obj.opts.$orig && !obj.opts.$orig.length ) {
+ delete obj.opts.$orig;
+ }
+
+ if ( !obj.opts.$thumb && obj.opts.$orig ) {
+ obj.opts.$thumb = obj.opts.$orig.find( 'img:first' );
+ }
+
+ if ( obj.opts.$thumb && !obj.opts.$thumb.length ) {
+ delete obj.opts.$thumb;
+ }
+
+ // Caption is a "special" option, it can be passed as a method
+ if ( $.type( obj.opts.caption ) === 'function' ) {
+ obj.opts.caption = obj.opts.caption.apply( item, [ self, obj ] );
+
+ } else if ( 'caption' in data ) {
+ obj.opts.caption = data.caption;
+ }
+
+ // Make sure we have caption as a string
+ obj.opts.caption = obj.opts.caption === undefined ? '' : obj.opts.caption + '';
+
+ // Check if url contains "filter" used to filter the content
+ // Example: "ajax.html #something"
+ if ( type === 'ajax' ) {
+ srcParts = src.split(/\s+/, 2);
+
+ if ( srcParts.length > 1 ) {
+ obj.src = srcParts.shift();
+
+ obj.opts.filter = srcParts.shift();
+ }
+ }
+
+ if ( obj.opts.smallBtn == 'auto' ) {
+
+ if ( $.inArray( type, ['html', 'inline', 'ajax'] ) > -1 ) {
+ obj.opts.toolbar = false;
+ obj.opts.smallBtn = true;
+
+ } else {
+ obj.opts.smallBtn = false;
+ }
+
+ }
+
+ // If the type is "pdf", then simply load file into iframe
+ if ( type === 'pdf' ) {
+ obj.type = 'iframe';
+
+ obj.opts.iframe.preload = false;
+ }
+
+ // Hide all buttons and disable interactivity for modal items
+ if ( obj.opts.modal ) {
+
+ obj.opts = $.extend(true, obj.opts, {
+ // Remove buttons
+ infobar : 0,
+ toolbar : 0,
+
+ smallBtn : 0,
+
+ // Disable keyboard navigation
+ keyboard : 0,
+
+ // Disable some modules
+ slideShow : 0,
+ fullScreen : 0,
+ thumbs : 0,
+ touch : 0,
+
+ // Disable click event handlers
+ clickContent : false,
+ clickSlide : false,
+ clickOutside : false,
+ dblclickContent : false,
+ dblclickSlide : false,
+ dblclickOutside : false
+ });
+
+ }
+
+ // Step 4 - Add processed object to group
+ // ======================================
+
+ self.group.push( obj );
+
+ });
+
+ },
+
+
+ // Attach an event handler functions for:
+ // - navigation buttons
+ // - browser scrolling, resizing;
+ // - focusing
+ // - keyboard
+ // - detect idle
+ // ======================================
+
+ addEvents : function() {
+ var self = this;
+
+ self.removeEvents();
+
+ // Make navigation elements clickable
+ self.$refs.container.on('click.fb-close', '[data-fancybox-close]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.close( e );
+
+ }).on( 'click.fb-prev touchend.fb-prev', '[data-fancybox-prev]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.previous();
+
+ }).on( 'click.fb-next touchend.fb-next', '[data-fancybox-next]', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ self.next();
+
+ });
+
+
+ // Handle page scrolling and browser resizing
+ $W.on('orientationchange.fb resize.fb', function(e) {
+
+ if ( e && e.originalEvent && e.originalEvent.type === "resize" ) {
+
+ requestAFrame(function() {
+ self.update();
+ });
+
+ } else {
+
+ self.$refs.stage.hide();
+
+ setTimeout(function() {
+ self.$refs.stage.show();
+
+ self.update();
+ }, 500);
+
+ }
+
+ });
+
+ // Trap keyboard focus inside of the modal, so the user does not accidentally tab outside of the modal
+ // (a.k.a. "escaping the modal")
+ $D.on('focusin.fb', function(e) {
+ var instance = $.fancybox ? $.fancybox.getInstance() : null;
+
+ if ( instance.isClosing || !instance.current || !instance.current.opts.trapFocus || $( e.target ).hasClass( 'fancybox-container' ) || $( e.target ).is( document ) ) {
+ return;
+ }
+
+ if ( instance && $( e.target ).css( 'position' ) !== 'fixed' && !instance.$refs.container.has( e.target ).length ) {
+ e.stopPropagation();
+
+ instance.focus();
+
+ // Sometimes page gets scrolled, set it back
+ $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
+ }
+ });
+
+
+ // Enable keyboard navigation
+ $D.on('keydown.fb', function (e) {
+ var current = self.current,
+ keycode = e.keyCode || e.which;
+
+ if ( !current || !current.opts.keyboard ) {
+ return;
+ }
+
+ if ( $(e.target).is('input') || $(e.target).is('textarea') ) {
+ return;
+ }
+
+ // Backspace and Esc keys
+ if ( keycode === 8 || keycode === 27 ) {
+ e.preventDefault();
+
+ self.close( e );
+
+ return;
+ }
+
+ // Left arrow and Up arrow
+ if ( keycode === 37 || keycode === 38 ) {
+ e.preventDefault();
+
+ self.previous();
+
+ return;
+ }
+
+ // Righ arrow and Down arrow
+ if ( keycode === 39 || keycode === 40 ) {
+ e.preventDefault();
+
+ self.next();
+
+ return;
+ }
+
+ self.trigger('afterKeydown', e, keycode);
+ });
+
+
+ // Hide controls after some inactivity period
+ if ( self.group[ self.currIndex ].opts.idleTime ) {
+ self.idleSecondsCounter = 0;
+
+ $D.on('mousemove.fb-idle mouseenter.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle', function() {
+ self.idleSecondsCounter = 0;
+
+ if ( self.isIdle ) {
+ self.showControls();
+ }
+
+ self.isIdle = false;
+ });
+
+ self.idleInterval = window.setInterval(function() {
+
+ self.idleSecondsCounter++;
+
+ if ( self.idleSecondsCounter >= self.group[ self.currIndex ].opts.idleTime ) {
+ self.isIdle = true;
+ self.idleSecondsCounter = 0;
+
+ self.hideControls();
+ }
+
+ }, 1000);
+ }
+
+ },
+
+
+ // Remove events added by the core
+ // ===============================
+
+ removeEvents : function () {
+ var self = this;
+
+ $W.off( 'orientationchange.fb resize.fb' );
+ $D.off( 'focusin.fb keydown.fb .fb-idle' );
+
+ this.$refs.container.off( '.fb-close .fb-prev .fb-next' );
+
+ if ( self.idleInterval ) {
+ window.clearInterval( self.idleInterval );
+
+ self.idleInterval = null;
+ }
+ },
+
+
+ // Change to previous gallery item
+ // ===============================
+
+ previous : function( duration ) {
+ return this.jumpTo( this.currPos - 1, duration );
+ },
+
+
+ // Change to next gallery item
+ // ===========================
+
+ next : function( duration ) {
+ return this.jumpTo( this.currPos + 1, duration );
+ },
+
+
+ // Switch to selected gallery item
+ // ===============================
+
+ jumpTo : function ( pos, duration, slide ) {
+ var self = this,
+ firstRun,
+ loop,
+ current,
+ previous,
+ canvasWidth,
+ currentPos,
+ transitionProps;
+
+ var groupLen = self.group.length;
+
+ if ( self.isSliding || self.isClosing || ( self.isAnimating && self.firstRun ) ) {
+ return;
+ }
+
+ pos = parseInt( pos, 10 );
+ loop = self.current ? self.current.opts.loop : self.opts.loop;
+
+ if ( !loop && ( pos < 0 || pos >= groupLen ) ) {
+ return false;
+ }
+
+ firstRun = self.firstRun = ( self.firstRun === null );
+
+ if ( groupLen < 2 && !firstRun && !!self.isSliding ) {
+ return;
+ }
+
+ previous = self.current;
+
+ self.prevIndex = self.currIndex;
+ self.prevPos = self.currPos;
+
+ // Create slides
+ current = self.createSlide( pos );
+
+ if ( groupLen > 1 ) {
+ if ( loop || current.index > 0 ) {
+ self.createSlide( pos - 1 );
+ }
+
+ if ( loop || current.index < groupLen - 1 ) {
+ self.createSlide( pos + 1 );
+ }
+ }
+
+ self.current = current;
+ self.currIndex = current.index;
+ self.currPos = current.pos;
+
+ self.trigger( 'beforeShow', firstRun );
+
+ self.updateControls();
+
+ currentPos = $.fancybox.getTranslate( current.$slide );
+
+ current.isMoved = ( currentPos.left !== 0 || currentPos.top !== 0 ) && !current.$slide.hasClass( 'fancybox-animated' );
+ current.forcedDuration = undefined;
+
+ if ( $.isNumeric( duration ) ) {
+ current.forcedDuration = duration;
+ } else {
+ duration = current.opts[ firstRun ? 'animationDuration' : 'transitionDuration' ];
+ }
+
+ duration = parseInt( duration, 10 );
+
+ // Fresh start - reveal container, current slide and start loading content
+ if ( firstRun ) {
+
+ if ( current.opts.animationEffect && duration ) {
+ self.$refs.container.css( 'transition-duration', duration + 'ms' );
+ }
+
+ self.$refs.container.removeClass( 'fancybox-is-hidden' );
+
+ forceRedraw( self.$refs.container );
+
+ self.$refs.container.addClass( 'fancybox-is-open' );
+
+ // Make first slide visible (to display loading icon, if needed)
+ current.$slide.addClass( 'fancybox-slide--current' );
+
+ self.loadSlide( current );
+
+ self.preload();
+
+ return;
+ }
+
+ // Clean up
+ $.each(self.slides, function( index, slide ) {
+ $.fancybox.stop( slide.$slide );
+ });
+
+ // Make current that slide is visible even if content is still loading
+ current.$slide.removeClass( 'fancybox-slide--next fancybox-slide--previous' ).addClass( 'fancybox-slide--current' );
+
+ // If slides have been dragged, animate them to correct position
+ if ( current.isMoved ) {
+ canvasWidth = Math.round( current.$slide.width() );
+
+ $.each(self.slides, function( index, slide ) {
+ var pos = slide.pos - current.pos;
+
+ $.fancybox.animate( slide.$slide, {
+ top : 0,
+ left : ( pos * canvasWidth ) + ( pos * slide.opts.gutter )
+ }, duration, function() {
+
+ slide.$slide.removeAttr('style').removeClass( 'fancybox-slide--next fancybox-slide--previous' );
+
+ if ( slide.pos === self.currPos ) {
+ current.isMoved = false;
+
+ self.complete();
+ }
+ });
+ });
+
+ } else {
+ self.$refs.stage.children().removeAttr( 'style' );
+ }
+
+ // Start transition that reveals current content
+ // or wait when it will be loaded
+
+ if ( current.isLoaded ) {
+ self.revealContent( current );
+
+ } else {
+ self.loadSlide( current );
+ }
+
+ self.preload();
+
+ if ( previous.pos === current.pos ) {
+ return;
+ }
+
+ // Handle previous slide
+ // =====================
+
+ transitionProps = 'fancybox-slide--' + ( previous.pos > current.pos ? 'next' : 'previous' );
+
+ previous.$slide.removeClass( 'fancybox-slide--complete fancybox-slide--current fancybox-slide--next fancybox-slide--previous' );
+
+ previous.isComplete = false;
+
+ if ( !duration || ( !current.isMoved && !current.opts.transitionEffect ) ) {
+ return;
+ }
+
+ if ( current.isMoved ) {
+ previous.$slide.addClass( transitionProps );
+
+ } else {
+
+ transitionProps = 'fancybox-animated ' + transitionProps + ' fancybox-fx-' + current.opts.transitionEffect;
+
+ $.fancybox.animate( previous.$slide, transitionProps, duration, function() {
+ previous.$slide.removeClass( transitionProps ).removeAttr( 'style' );
+ });
+
+ }
+
+ },
+
+
+ // Create new "slide" element
+ // These are gallery items that are actually added to DOM
+ // =======================================================
+
+ createSlide : function( pos ) {
+
+ var self = this;
+ var $slide;
+ var index;
+
+ index = pos % self.group.length;
+ index = index < 0 ? self.group.length + index : index;
+
+ if ( !self.slides[ pos ] && self.group[ index ] ) {
+ $slide = $('<div class="fancybox-slide"></div>').appendTo( self.$refs.stage );
+
+ self.slides[ pos ] = $.extend( true, {}, self.group[ index ], {
+ pos : pos,
+ $slide : $slide,
+ isLoaded : false,
+ });
+
+ self.updateSlide( self.slides[ pos ] );
+ }
+
+ return self.slides[ pos ];
+ },
+
+
+ // Scale image to the actual size of the image
+ // ===========================================
+
+ scaleToActual : function( x, y, duration ) {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var imgPos, posX, posY, scaleX, scaleY;
+
+ var canvasWidth = parseInt( current.$slide.width(), 10 );
+ var canvasHeight = parseInt( current.$slide.height(), 10 );
+
+ var newImgWidth = current.width;
+ var newImgHeight = current.height;
+
+ if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating) {
+ return;
+ }
+
+ $.fancybox.stop( $what );
+
+ self.isAnimating = true;
+
+ x = x === undefined ? canvasWidth * 0.5 : x;
+ y = y === undefined ? canvasHeight * 0.5 : y;
+
+ imgPos = $.fancybox.getTranslate( $what );
+
+ scaleX = newImgWidth / imgPos.width;
+ scaleY = newImgHeight / imgPos.height;
+
+ // Get center position for original image
+ posX = ( canvasWidth * 0.5 - newImgWidth * 0.5 );
+ posY = ( canvasHeight * 0.5 - newImgHeight * 0.5 );
+
+ // Make sure image does not move away from edges
+ if ( newImgWidth > canvasWidth ) {
+ posX = imgPos.left * scaleX - ( ( x * scaleX ) - x );
+
+ if ( posX > 0 ) {
+ posX = 0;
+ }
+
+ if ( posX < canvasWidth - newImgWidth ) {
+ posX = canvasWidth - newImgWidth;
+ }
+ }
+
+ if ( newImgHeight > canvasHeight) {
+ posY = imgPos.top * scaleY - ( ( y * scaleY ) - y );
+
+ if ( posY > 0 ) {
+ posY = 0;
+ }
+
+ if ( posY < canvasHeight - newImgHeight ) {
+ posY = canvasHeight - newImgHeight;
+ }
+ }
+
+ self.updateCursor( newImgWidth, newImgHeight );
+
+ $.fancybox.animate( $what, {
+ top : posY,
+ left : posX,
+ scaleX : scaleX,
+ scaleY : scaleY
+ }, duration || 330, function() {
+ self.isAnimating = false;
+ });
+
+ // Stop slideshow
+ if ( self.SlideShow && self.SlideShow.isActive ) {
+ self.SlideShow.stop();
+ }
+ },
+
+
+ // Scale image to fit inside parent element
+ // ========================================
+
+ scaleToFit : function( duration ) {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+ var end;
+
+ if ( !( current.type == 'image' && !current.hasError) || !$what || self.isAnimating ) {
+ return;
+ }
+
+ $.fancybox.stop( $what );
+
+ self.isAnimating = true;
+
+ end = self.getFitPos( current );
+
+ self.updateCursor( end.width, end.height );
+
+ $.fancybox.animate( $what, {
+ top : end.top,
+ left : end.left,
+ scaleX : end.width / $what.width(),
+ scaleY : end.height / $what.height()
+ }, duration || 330, function() {
+ self.isAnimating = false;
+ });
+
+ },
+
+ // Calculate image size to fit inside viewport
+ // ===========================================
+
+ getFitPos : function( slide ) {
+ var self = this;
+ var $what = slide.$content;
+
+ var imgWidth = slide.width;
+ var imgHeight = slide.height;
+
+ var margin = slide.opts.margin;
+
+ var canvasWidth, canvasHeight, minRatio, width, height;
+
+ if ( !$what || !$what.length || ( !imgWidth && !imgHeight) ) {
+ return false;
+ }
+
+ // Convert "margin to CSS style: [ top, right, bottom, left ]
+ if ( $.type( margin ) === "number" ) {
+ margin = [ margin, margin ];
+ }
+
+ if ( margin.length == 2 ) {
+ margin = [ margin[0], margin[1], margin[0], margin[1] ];
+ }
+
+ if ( $W.width() < 800 ) {
+ margin = [ 0, 0, 0, 0 ];
+ }
+
+ // We can not use $slide width here, because it can have different diemensions while in transiton
+ canvasWidth = parseInt( self.$refs.stage.width(), 10 ) - ( margin[ 1 ] + margin[ 3 ] );
+ canvasHeight = parseInt( self.$refs.stage.height(), 10 ) - ( margin[ 0 ] + margin[ 2 ] );
+
+ minRatio = Math.min(1, canvasWidth / imgWidth, canvasHeight / imgHeight );
+
+ width = Math.floor( minRatio * imgWidth );
+ height = Math.floor( minRatio * imgHeight );
+
+ // Use floor rounding to make sure it really fits
+ return {
+ top : Math.floor( ( canvasHeight - height ) * 0.5 ) + margin[ 0 ],
+ left : Math.floor( ( canvasWidth - width ) * 0.5 ) + margin[ 3 ],
+ width : width,
+ height : height
+ };
+
+ },
+
+
+ // Update position and content of all slides
+ // =========================================
+
+ update : function() {
+
+ var self = this;
+
+ $.each( self.slides, function( key, slide ) {
+ self.updateSlide( slide );
+ });
+
+ },
+
+
+ // Update slide position and scale content to fit
+ // ==============================================
+
+ updateSlide : function( slide ) {
+
+ var self = this;
+ var $what = slide.$content;
+
+ if ( $what && ( slide.width || slide.height ) ) {
+ $.fancybox.stop( $what );
+
+ $.fancybox.setTranslate( $what, self.getFitPos( slide ) );
+
+ if ( slide.pos === self.currPos ) {
+ self.updateCursor();
+ }
+ }
+
+ slide.$slide.trigger( 'refresh' );
+
+ self.trigger( 'onUpdate', slide );
+
+ },
+
+ // Update cursor style depending if content can be zoomed
+ // ======================================================
+
+ updateCursor : function( nextWidth, nextHeight ) {
+
+ var self = this;
+ var isScaledDown;
+
+ var $container = self.$refs.container.removeClass('fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-drag fancybox-can-zoomOut');
+
+ if ( !self.current || self.isClosing ) {
+ return;
+ }
+
+ if ( self.isZoomable() ) {
+
+ $container.addClass( 'fancybox-is-zoomable' );
+
+ if ( nextWidth !== undefined && nextHeight !== undefined ) {
+ isScaledDown = nextWidth < self.current.width && nextHeight < self.current.height;
+
+ } else {
+ isScaledDown = self.isScaledDown();
+ }
+
+ if ( isScaledDown ) {
+
+ // If image is scaled down, then, obviously, it can be zoomed to full size
+ $container.addClass('fancybox-can-zoomIn');
+
+ } else {
+
+ if ( self.current.opts.touch ) {
+
+ // If image size ir largen than available available and touch module is not disable,
+ // then user can do panning
+ $container.addClass('fancybox-can-drag');
+
+ } else {
+ $container.addClass('fancybox-can-zoomOut');
+ }
+
+ }
+
+ } else if ( self.current.opts.touch ) {
+ $container.addClass('fancybox-can-drag');
+ }
+
+ },
+
+
+ // Check if current slide is zoomable
+ // ==================================
+
+ isZoomable : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var fitPos;
+
+ if ( !current || self.isClosing ) {
+ return;
+ }
+
+ // Assume that slide is zoomable if
+ // - image is loaded successfuly
+ // - click action is "zoom"
+ // - actual size of the image is smaller than available area
+ if ( current.type === 'image' && current.isLoaded && !current.hasError &&
+ ( current.opts.clickContent === 'zoom' || ( $.isFunction( current.opts.clickContent ) && current.opts.clickContent( current ) === "zoom" ) )
+ ) {
+
+ fitPos = self.getFitPos( current );
+
+ if ( current.width > fitPos.width || current.height > fitPos.height ) {
+ return true;
+ }
+
+ }
+
+ return false;
+
+ },
+
+
+ // Check if current image dimensions are smaller than actual
+ // =========================================================
+
+ isScaledDown : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var rez = false;
+
+ if ( $what ) {
+ rez = $.fancybox.getTranslate( $what );
+ rez = rez.width < current.width || rez.height < current.height;
+ }
+
+ return rez;
+
+ },
+
+
+ // Check if image dimensions exceed parent element
+ // ===============================================
+
+ canPan : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var $what = current.$content;
+
+ var rez = false;
+
+ if ( $what ) {
+ rez = self.getFitPos( current );
+ rez = Math.abs( $what.width() - rez.width ) > 1 || Math.abs( $what.height() - rez.height ) > 1;
+
+ }
+
+ return rez;
+
+ },
+
+
+ // Load content into the slide
+ // ===========================
+
+ loadSlide : function( slide ) {
+
+ var self = this, type, $slide;
+ var ajaxLoad;
+
+ if ( slide.isLoading ) {
+ return;
+ }
+
+ if ( slide.isLoaded ) {
+ return;
+ }
+
+ slide.isLoading = true;
+
+ self.trigger( 'beforeLoad', slide );
+
+ type = slide.type;
+ $slide = slide.$slide;
+
+ $slide
+ .off( 'refresh' )
+ .trigger( 'onReset' )
+ .addClass( 'fancybox-slide--' + ( type || 'unknown' ) )
+ .addClass( slide.opts.slideClass );
+
+ // Create content depending on the type
+
+ switch ( type ) {
+
+ case 'image':
+
+ self.setImage( slide );
+
+ break;
+
+ case 'iframe':
+
+ self.setIframe( slide );
+
+ break;
+
+ case 'html':
+
+ self.setContent( slide, slide.src || slide.content );
+
+ break;
+
+ case 'inline':
+
+ if ( $( slide.src ).length ) {
+ self.setContent( slide, $( slide.src ) );
+
+ } else {
+ self.setError( slide );
+ }
+
+ break;
+
+ case 'ajax':
+
+ self.showLoading( slide );
+
+ ajaxLoad = $.ajax( $.extend( {}, slide.opts.ajax.settings, {
+ url : slide.src,
+ success : function ( data, textStatus ) {
+
+ if ( textStatus === 'success' ) {
+ self.setContent( slide, data );
+ }
+
+ },
+ error : function ( jqXHR, textStatus ) {
+
+ if ( jqXHR && textStatus !== 'abort' ) {
+ self.setError( slide );
+ }
+
+ }
+ }));
+
+ $slide.one( 'onReset', function () {
+ ajaxLoad.abort();
+ });
+
+ break;
+
+ default:
+
+ self.setError( slide );
+
+ break;
+
+ }
+
+ return true;
+
+ },
+
+
+ // Use thumbnail image, if possible
+ // ================================
+
+ setImage : function( slide ) {
+
+ var self = this;
+ var srcset = slide.opts.image.srcset;
+
+ var found, temp, pxRatio, windowWidth;
+
+ // If we have "srcset", then we need to find matching "src" value.
+ // This is necessary, because when you set an src attribute, the browser will preload the image
+ // before any javascript or even CSS is applied.
+ if ( srcset ) {
+ pxRatio = window.devicePixelRatio || 1;
+ windowWidth = window.innerWidth * pxRatio;
+
+ temp = srcset.split(',').map(function ( el ) {
+ var ret = {};
+
+ el.trim().split(/\s+/).forEach(function ( el, i ) {
+ var value = parseInt( el.substring(0, el.length - 1), 10 );
+
+ if ( i === 0 ) {
+ return ( ret.url = el );
+ }
+
+ if ( value ) {
+ ret.value = value;
+ ret.postfix = el[ el.length - 1 ];
+ }
+
+ });
+
+ return ret;
+ });
+
+ // Sort by value
+ temp.sort(function (a, b) {
+ return a.value - b.value;
+ });
+
+ // Ok, now we have an array of all srcset values
+ for ( var j = 0; j < temp.length; j++ ) {
+ var el = temp[ j ];
+
+ if ( ( el.postfix === 'w' && el.value >= windowWidth ) || ( el.postfix === 'x' && el.value >= pxRatio ) ) {
+ found = el;
+ break;
+ }
+ }
+
+ // If not found, take the last one
+ if ( !found && temp.length ) {
+ found = temp[ temp.length - 1 ];
+ }
+
+ if ( found ) {
+ slide.src = found.url;
+
+ // If we have default width/height values, we can calculate height for matching source
+ if ( slide.width && slide.height && found.postfix == 'w' ) {
+ slide.height = ( slide.width / slide.height ) * found.value;
+ slide.width = found.value;
+ }
+ }
+ }
+
+ // This will be wrapper containing both ghost and actual image
+ slide.$content = $('<div class="fancybox-image-wrap"></div>')
+ .addClass( 'fancybox-is-hidden' )
+ .appendTo( slide.$slide );
+
+
+ // If we have a thumbnail, we can display it while actual image is loading
+ // Users will not stare at black screen and actual image will appear gradually
+ if ( slide.opts.preload !== false && slide.opts.width && slide.opts.height && ( slide.opts.thumb || slide.opts.$thumb ) ) {
+
+ slide.width = slide.opts.width;
+ slide.height = slide.opts.height;
+
+ slide.$ghost = $('<img />')
+ .one('error', function() {
+
+ $(this).remove();
+
+ slide.$ghost = null;
+
+ self.setBigImage( slide );
+
+ })
+ .one('load', function() {
+
+ self.afterLoad( slide );
+
+ self.setBigImage( slide );
+
+ })
+ .addClass( 'fancybox-image' )
+ .appendTo( slide.$content )
+ .attr( 'src', slide.opts.thumb || slide.opts.$thumb.attr( 'src' ) );
+
+ } else {
+
+ self.setBigImage( slide );
+
+ }
+
+ },
+
+
+ // Create full-size image
+ // ======================
+
+ setBigImage : function ( slide ) {
+ var self = this;
+ var $img = $('<img />');
+
+ slide.$image = $img
+ .one('error', function() {
+
+ self.setError( slide );
+
+ })
+ .one('load', function() {
+
+ // Clear timeout that checks if loading icon needs to be displayed
+ clearTimeout( slide.timouts );
+
+ slide.timouts = null;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ slide.width = this.naturalWidth;
+ slide.height = this.naturalHeight;
+
+ if ( slide.opts.image.srcset ) {
+ $img.attr( 'sizes', '100vw' ).attr( 'srcset', slide.opts.image.srcset );
+ }
+
+ self.hideLoading( slide );
+
+ if ( slide.$ghost ) {
+
+ slide.timouts = setTimeout(function() {
+ slide.timouts = null;
+
+ slide.$ghost.hide();
+
+ }, Math.min( 300, Math.max( 1000, slide.height / 1600 ) ) );
+
+ } else {
+ self.afterLoad( slide );
+ }
+
+ })
+ .addClass( 'fancybox-image' )
+ .attr('src', slide.src)
+ .appendTo( slide.$content );
+
+ if ( $img[0].complete ) {
+ $img.trigger( 'load' );
+
+ } else if( $img[0].error ) {
+ $img.trigger( 'error' );
+
+ } else {
+
+ slide.timouts = setTimeout(function() {
+ if ( !$img[0].complete && !slide.hasError ) {
+ self.showLoading( slide );
+ }
+
+ }, 100);
+
+ }
+
+ },
+
+
+ // Create iframe wrapper, iframe and bindings
+ // ==========================================
+
+ setIframe : function( slide ) {
+ var self = this,
+ opts = slide.opts.iframe,
+ $slide = slide.$slide,
+ $iframe;
+
+ slide.$content = $('<div class="fancybox-content' + ( opts.preload ? ' fancybox-is-hidden' : '' ) + '"></div>')
+ .css( opts.css )
+ .appendTo( $slide );
+
+ $iframe = $( opts.tpl.replace(/\{rnd\}/g, new Date().getTime()) )
+ .attr( opts.attr )
+ .appendTo( slide.$content );
+
+ if ( opts.preload ) {
+
+ self.showLoading( slide );
+
+ // Unfortunately, it is not always possible to determine if iframe is successfully loaded
+ // (due to browser security policy)
+
+ $iframe.on('load.fb error.fb', function(e) {
+ this.isReady = 1;
+
+ slide.$slide.trigger( 'refresh' );
+
+ self.afterLoad( slide );
+ });
+
+ // Recalculate iframe content size
+ // ===============================
+
+ $slide.on('refresh.fb', function() {
+ var $wrap = slide.$content,
+ $contents,
+ $body,
+ scrollWidth,
+ frameWidth,
+ frameHeight;
+
+ if ( $iframe[0].isReady !== 1 ) {
+ return;
+ }
+
+ // Check if content is accessible,
+ // it will fail if frame is not with the same origin
+
+ try {
+ $contents = $iframe.contents();
+ $body = $contents.find('body');
+
+ } catch (ignore) {}
+
+ // Calculate dimensions for the wrapper
+ if ( $body && $body.length && !( opts.css.width !== undefined && opts.css.height !== undefined ) ) {
+
+ scrollWidth = $iframe[0].contentWindow.document.documentElement.scrollWidth;
+
+ frameWidth = Math.ceil( $body.outerWidth(true) + ( $wrap.width() - scrollWidth ) );
+ frameHeight = Math.ceil( $body.outerHeight(true) );
+
+ // Resize wrapper to fit iframe content
+ $wrap.css({
+ 'width' : opts.css.width === undefined ? frameWidth + ( $wrap.outerWidth() - $wrap.innerWidth() ) : opts.css.width,
+ 'height' : opts.css.height === undefined ? frameHeight + ( $wrap.outerHeight() - $wrap.innerHeight() ) : opts.css.height
+ });
+
+ }
+
+ $wrap.removeClass( 'fancybox-is-hidden' );
+
+ });
+
+ } else {
+
+ this.afterLoad( slide );
+
+ }
+
+ $iframe.attr( 'src', slide.src );
+
+ if ( slide.opts.smallBtn === true ) {
+ slide.$content.prepend( self.translate( slide, slide.opts.btnTpl.smallBtn ) );
+ }
+
+ // Remove iframe if closing or changing gallery item
+ $slide.one( 'onReset', function () {
+
+ // This helps IE not to throw errors when closing
+ try {
+
+ $( this ).find( 'iframe' ).hide().attr( 'src', '//about:blank' );
+
+ } catch ( ignore ) {}
+
+ $( this ).empty();
+
+ slide.isLoaded = false;
+
+ });
+
+ },
+
+
+ // Wrap and append content to the slide
+ // ======================================
+
+ setContent : function ( slide, content ) {
+
+ var self = this;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ self.hideLoading( slide );
+
+ slide.$slide.empty();
+
+ if ( isQuery( content ) && content.parent().length ) {
+
+ // If content is a jQuery object, then it will be moved to the slide.
+ // The placeholder is created so we will know where to put it back.
+ // If user is navigating gallery fast, then the content might be already inside fancyBox
+ // =====================================================================================
+
+ // Make sure content is not already moved to fancyBox
+ content.parent( '.fancybox-slide--inline' ).trigger( 'onReset' );
+
+ // Create temporary element marking original place of the content
+ slide.$placeholder = $( '<div></div>' ).hide().insertAfter( content );
+
+ // Make sure content is visible
+ content.css('display', 'inline-block');
+
+ } else if ( !slide.hasError ) {
+
+ // If content is just a plain text, try to convert it to html
+ if ( $.type( content ) === 'string' ) {
+ content = $('<div>').append( $.trim( content ) ).contents();
+
+ // If we have text node, then add wrapping element to make vertical alignment work
+ if ( content[0].nodeType === 3 ) {
+ content = $('<div>').html( content );
+ }
+ }
+
+ // If "filter" option is provided, then filter content
+ if ( slide.opts.filter ) {
+ content = $('<div>').html( content ).find( slide.opts.filter );
+ }
+
+ }
+
+ slide.$slide.one('onReset', function () {
+
+ // Put content back
+ if ( slide.$placeholder ) {
+ slide.$placeholder.after( content.hide() ).remove();
+
+ slide.$placeholder = null;
+ }
+
+ // Remove custom close button
+ if ( slide.$smallBtn ) {
+ slide.$smallBtn.remove();
+
+ slide.$smallBtn = null;
+ }
+
+ // Remove content and mark slide as not loaded
+ if ( !slide.hasError ) {
+ $(this).empty();
+
+ slide.isLoaded = false;
+ }
+
+ });
+
+ slide.$content = $( content ).appendTo( slide.$slide );
+
+ if ( slide.opts.smallBtn && !slide.$smallBtn ) {
+ slide.$smallBtn = $( self.translate( slide, slide.opts.btnTpl.smallBtn ) ).appendTo( slide.$content );
+ }
+
+ this.afterLoad( slide );
+ },
+
+ // Display error message
+ // =====================
+
+ setError : function ( slide ) {
+
+ slide.hasError = true;
+
+ slide.$slide.removeClass( 'fancybox-slide--' + slide.type );
+
+ this.setContent( slide, this.translate( slide, slide.opts.errorTpl ) );
+
+ },
+
+
+ // Show loading icon inside the slide
+ // ==================================
+
+ showLoading : function( slide ) {
+
+ var self = this;
+
+ slide = slide || self.current;
+
+ if ( slide && !slide.$spinner ) {
+ slide.$spinner = $( self.opts.spinnerTpl ).appendTo( slide.$slide );
+ }
+
+ },
+
+ // Remove loading icon from the slide
+ // ==================================
+
+ hideLoading : function( slide ) {
+
+ var self = this;
+
+ slide = slide || self.current;
+
+ if ( slide && slide.$spinner ) {
+ slide.$spinner.remove();
+
+ delete slide.$spinner;
+ }
+
+ },
+
+
+ // Adjustments after slide content has been loaded
+ // ===============================================
+
+ afterLoad : function( slide ) {
+
+ var self = this;
+
+ if ( self.isClosing ) {
+ return;
+ }
+
+ slide.isLoading = false;
+ slide.isLoaded = true;
+
+ self.trigger( 'afterLoad', slide );
+
+ self.hideLoading( slide );
+
+ if ( slide.opts.protect && slide.$content && !slide.hasError ) {
+
+ // Disable right click
+ slide.$content.on( 'contextmenu.fb', function( e ) {
+ if ( e.button == 2 ) {
+ e.preventDefault();
+ }
+
+ return true;
+ });
+
+ // Add fake element on top of the image
+ // This makes a bit harder for user to select image
+ if ( slide.type === 'image' ) {
+ $( '<div class="fancybox-spaceball"></div>' ).appendTo( slide.$content );
+ }
+
+ }
+
+ self.revealContent( slide );
+
+ },
+
+
+ // Make content visible
+ // This method is called right after content has been loaded or
+ // user navigates gallery and transition should start
+ // ============================================================
+
+ revealContent : function( slide ) {
+
+ var self = this;
+ var $slide = slide.$slide;
+
+ var effect, effectClassName, duration, opacity, end, start = false;
+
+ effect = slide.opts[ self.firstRun ? 'animationEffect' : 'transitionEffect' ];
+ duration = slide.opts[ self.firstRun ? 'animationDuration' : 'transitionDuration' ];
+
+ duration = parseInt( slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10 );
+
+ if ( slide.isMoved || slide.pos !== self.currPos || !duration ) {
+ effect = false;
+ }
+
+ // Check if can zoom
+ if ( effect === 'zoom' && !( slide.pos === self.currPos && duration && slide.type === 'image' && !slide.hasError && ( start = self.getThumbPos( slide ) ) ) ) {
+ effect = 'fade';
+ }
+
+
+ // Zoom animation
+ // ==============
+
+ if ( effect === 'zoom' ) {
+ end = self.getFitPos( slide );
+
+ end.scaleX = end.width / start.width;
+ end.scaleY = end.height / start.height;
+
+ delete end.width;
+ delete end.height;
+
+ // Check if we need to animate opacity
+ opacity = slide.opts.zoomOpacity;
+
+ if ( opacity == 'auto' ) {
+ opacity = Math.abs( slide.width / slide.height - start.width / start.height ) > 0.1;
+ }
+
+ if ( opacity ) {
+ start.opacity = 0.1;
+ end.opacity = 1;
+ }
+
+ // Draw image at start position
+ $.fancybox.setTranslate( slide.$content.removeClass( 'fancybox-is-hidden' ), start );
+
+ forceRedraw( slide.$content );
+
+ // Start animation
+ $.fancybox.animate( slide.$content, end, duration, function() {
+ self.complete();
+ });
+
+ return;
+ }
+
+
+ self.updateSlide( slide );
+
+
+ // Simply show content
+ // ===================
+
+ if ( !effect ) {
+ forceRedraw( $slide );
+
+ slide.$content.removeClass( 'fancybox-is-hidden' );
+
+ if ( slide.pos === self.currPos ) {
+ self.complete();
+ }
+
+ return;
+ }
+
+ $.fancybox.stop( $slide );
+
+ effectClassName = 'fancybox-animated fancybox-slide--' + ( slide.pos > self.prevPos ? 'next' : 'previous' ) + ' fancybox-fx-' + effect;
+
+ $slide.removeAttr( 'style' ).removeClass( 'fancybox-slide--current fancybox-slide--next fancybox-slide--previous' ).addClass( effectClassName );
+
+ slide.$content.removeClass( 'fancybox-is-hidden' );
+
+ //Force reflow for CSS3 transitions
+ forceRedraw( $slide );
+
+ $.fancybox.animate( $slide, 'fancybox-slide--current', duration, function(e) {
+ $slide.removeClass( effectClassName ).removeAttr( 'style' );
+
+ if ( slide.pos === self.currPos ) {
+ self.complete();
+ }
+
+ }, true);
+
+ },
+
+
+ // Check if we can and have to zoom from thumbnail
+ //================================================
+
+ getThumbPos : function( slide ) {
+
+ var self = this;
+ var rez = false;
+
+ // Check if element is inside the viewport by at least 1 pixel
+ var isElementVisible = function( $el ) {
+ var element = $el[0];
+
+ var elementRect = element.getBoundingClientRect();
+ var parentRects = [];
+
+ var visibleInAllParents;
+
+ while ( element.parentElement !== null ) {
+ if ( $(element.parentElement).css('overflow') === 'hidden' || $(element.parentElement).css('overflow') === 'auto' ) {
+ parentRects.push(element.parentElement.getBoundingClientRect());
+ }
+
+ element = element.parentElement;
+ }
+
+ visibleInAllParents = parentRects.every(function(parentRect){
+ var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
+ var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
+
+ return visiblePixelX > 0 && visiblePixelY > 0;
+ });
+
+ return visibleInAllParents &&
+ elementRect.bottom > 0 && elementRect.right > 0 &&
+ elementRect.left < $(window).width() && elementRect.top < $(window).height();
+ };
+
+ var $thumb = slide.opts.$thumb;
+ var thumbPos = $thumb ? $thumb.offset() : 0;
+ var slidePos;
+
+ if ( thumbPos && $thumb[0].ownerDocument === document && isElementVisible( $thumb ) ) {
+ slidePos = self.$refs.stage.offset();
+
+ rez = {
+ top : thumbPos.top - slidePos.top + parseFloat( $thumb.css( "border-top-width" ) || 0 ),
+ left : thumbPos.left - slidePos.left + parseFloat( $thumb.css( "border-left-width" ) || 0 ),
+ width : $thumb.width(),
+ height : $thumb.height(),
+ scaleX : 1,
+ scaleY : 1
+ };
+ }
+
+ return rez;
+ },
+
+
+ // Final adjustments after current gallery item is moved to position
+ // and it`s content is loaded
+ // ==================================================================
+
+ complete : function() {
+
+ var self = this;
+
+ var current = self.current;
+ var slides = {};
+
+ if ( current.isMoved || !current.isLoaded || current.isComplete ) {
+ return;
+ }
+
+ current.isComplete = true;
+
+ current.$slide.siblings().trigger( 'onReset' );
+
+ // Trigger any CSS3 transiton inside the slide
+ forceRedraw( current.$slide );
+
+ current.$slide.addClass( 'fancybox-slide--complete' );
+
+ // Remove unnecessary slides
+ $.each( self.slides, function( key, slide ) {
+ if ( slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1 ) {
+ slides[ slide.pos ] = slide;
+
+ } else if ( slide ) {
+
+ $.fancybox.stop( slide.$slide );
+
+ slide.$slide.unbind().remove();
+ }
+ });
+
+ self.slides = slides;
+
+ self.updateCursor();
+
+ self.trigger( 'afterShow' );
+
+ // Try to focus on the first focusable element
+ if ( $( document.activeElement ).is( '[disabled]' ) || ( current.opts.autoFocus && !( current.type == 'image' || current.type === 'iframe' ) ) ) {
+ self.focus();
+ }
+
+ },
+
+
+ // Preload next and previous slides
+ // ================================
+
+ preload : function() {
+ var self = this;
+ var next, prev;
+
+ if ( self.group.length < 2 ) {
+ return;
+ }
+
+ next = self.slides[ self.currPos + 1 ];
+ prev = self.slides[ self.currPos - 1 ];
+
+ if ( next && next.type === 'image' ) {
+ self.loadSlide( next );
+ }
+
+ if ( prev && prev.type === 'image' ) {
+ self.loadSlide( prev );
+ }
+
+ },
+
+
+ // Try to find and focus on the first focusable element
+ // ====================================================
+
+ focus : function() {
+ var current = this.current;
+ var $el;
+
+ if ( this.isClosing ) {
+ return;
+ }
+
+ // Skip for images and iframes
+ $el = current && current.isComplete ? current.$slide.find('button,:input,[tabindex],a').filter(':not([disabled]):visible:first') : null;
+ $el = $el && $el.length ? $el : this.$refs.container;
+
+ $el.focus();
+ },
+
+
+ // Activates current instance - brings container to the front and enables keyboard,
+ // notifies other instances about deactivating
+ // =================================================================================
+
+ activate : function () {
+ var self = this;
+
+ // Deactivate all instances
+ $( '.fancybox-container' ).each(function () {
+ var instance = $(this).data( 'FancyBox' );
+
+ // Skip self and closing instances
+ if (instance && instance.uid !== self.uid && !instance.isClosing) {
+ instance.trigger( 'onDeactivate' );
+ }
+
+ });
+
+ if ( self.current ) {
+ if ( self.$refs.container.index() > 0 ) {
+ self.$refs.container.prependTo( document.body );
+ }
+
+ self.updateControls();
+ }
+
+ self.trigger( 'onActivate' );
+
+ self.addEvents();
+
+ },
+
+
+ // Start closing procedure
+ // This will start "zoom-out" animation if needed and clean everything up afterwards
+ // =================================================================================
+
+ close : function( e, d ) {
+
+ var self = this;
+ var current = self.current;
+
+ var effect, duration;
+ var $what, opacity, start, end;
+
+ var done = function() {
+ self.cleanUp( e );
+ };
+
+ if ( self.isClosing ) {
+ return false;
+ }
+
+ self.isClosing = true;
+
+ // If beforeClose callback prevents closing, make sure content is centered
+ if ( self.trigger( 'beforeClose', e ) === false ) {
+ self.isClosing = false;
+
+ requestAFrame(function() {
+ self.update();
+ });
+
+ return false;
+ }
+
+ // Remove all events
+ // If there are multiple instances, they will be set again by "activate" method
+ self.removeEvents();
+
+ if ( current.timouts ) {
+ clearTimeout( current.timouts );
+ }
+
+ $what = current.$content;
+ effect = current.opts.animationEffect;
+ duration = $.isNumeric( d ) ? d : ( effect ? current.opts.animationDuration : 0 );
+
+ // Remove other slides
+ current.$slide.off( transitionEnd ).removeClass( 'fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated' );
+
+ current.$slide.siblings().trigger( 'onReset' ).remove();
+
+ // Trigger animations
+ if ( duration ) {
+ self.$refs.container.removeClass( 'fancybox-is-open' ).addClass( 'fancybox-is-closing' );
+ }
+
+ // Clean up
+ self.hideLoading( current );
+
+ self.hideControls();
+
+ self.updateCursor();
+
+ // Check if possible to zoom-out
+ if ( effect === 'zoom' && !( e !== true && $what && duration && current.type === 'image' && !current.hasError && ( end = self.getThumbPos( current ) ) ) ) {
+ effect = 'fade';
+ }
+
+ if ( effect === 'zoom' ) {
+ $.fancybox.stop( $what );
+
+ start = $.fancybox.getTranslate( $what );
+
+ start.width = start.width * start.scaleX;
+ start.height = start.height * start.scaleY;
+
+ // Check if we need to animate opacity
+ opacity = current.opts.zoomOpacity;
+
+ if ( opacity == 'auto' ) {
+ opacity = Math.abs( current.width / current.height - end.width / end.height ) > 0.1;
+ }
+
+ if ( opacity ) {
+ end.opacity = 0;
+ }
+
+ start.scaleX = start.width / end.width;
+ start.scaleY = start.height / end.height;
+
+ start.width = end.width;
+ start.height = end.height;
+
+ $.fancybox.setTranslate( current.$content, start );
+
+ $.fancybox.animate( current.$content, end, duration, done );
+
+ return true;
+ }
+
+ if ( effect && duration ) {
+
+ // If skip animation
+ if ( e === true ) {
+ setTimeout( done, duration );
+
+ } else {
+ $.fancybox.animate( current.$slide.removeClass( 'fancybox-slide--current' ), 'fancybox-animated fancybox-slide--previous fancybox-fx-' + effect, duration, done );
+ }
+
+ } else {
+ done();
+ }
+
+ return true;
+ },
+
+
+ // Final adjustments after removing the instance
+ // =============================================
+
+ cleanUp : function( e ) {
+ var self = this,
+ instance;
+
+ self.current.$slide.trigger( 'onReset' );
+
+ self.$refs.container.empty().remove();
+
+ self.trigger( 'afterClose', e );
+
+ // Place back focus
+ if ( self.$lastFocus && !!self.current.opts.backFocus ) {
+ self.$lastFocus.focus();
+ }
+
+ self.current = null;
+
+ // Check if there are other instances
+ instance = $.fancybox.getInstance();
+
+ if ( instance ) {
+ instance.activate();
+
+ } else {
+
+ $W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
+
+ $( 'html' ).removeClass( 'fancybox-enabled' );
+
+ $( '#fancybox-style-noscroll' ).remove();
+ }
+
+ },
+
+
+ // Call callback and trigger an event
+ // ==================================
+
+ trigger : function( name, slide ) {
+ var args = Array.prototype.slice.call(arguments, 1),
+ self = this,
+ obj = slide && slide.opts ? slide : self.current,
+ rez;
+
+ if ( obj ) {
+ args.unshift( obj );
+
+ } else {
+ obj = self;
+ }
+
+ args.unshift( self );
+
+ if ( $.isFunction( obj.opts[ name ] ) ) {
+ rez = obj.opts[ name ].apply( obj, args );
+ }
+
+ if ( rez === false ) {
+ return rez;
+ }
+
+ if ( name === 'afterClose' ) {
+ $D.trigger( name + '.fb', args );
+
+ } else {
+ self.$refs.container.trigger( name + '.fb', args );
+ }
+
+ },
+
+
+ // Update infobar values, navigation button states and reveal caption
+ // ==================================================================
+
+ updateControls : function ( force ) {
+
+ var self = this;
+
+ var current = self.current;
+ var index = current.index;
+ var opts = current.opts;
+ var caption = opts.caption;
+ var $caption = self.$refs.caption;
+
+ // Recalculate content dimensions
+ current.$slide.trigger( 'refresh' );
+
+ self.$caption = caption && caption.length ? $caption.html( caption ) : null;
+
+ if ( !self.isHiddenControls ) {
+ self.showControls();
+ }
+
+ // Update info and navigation elements
+ $('[data-fancybox-count]').html( self.group.length );
+ $('[data-fancybox-index]').html( index + 1 );
+
+ $('[data-fancybox-prev]').prop('disabled', ( !opts.loop && index <= 0 ) );
+ $('[data-fancybox-next]').prop('disabled', ( !opts.loop && index >= self.group.length - 1 ) );
+
+ },
+
+ // Hide toolbar and caption
+ // ========================
+
+ hideControls : function () {
+
+ this.isHiddenControls = true;
+
+ this.$refs.container.removeClass('fancybox-show-infobar fancybox-show-toolbar fancybox-show-caption fancybox-show-nav');
+
+ },
+
+ showControls : function() {
+
+ var self = this;
+ var opts = self.current ? self.current.opts : self.opts;
+ var $container = self.$refs.container;
+
+ self.isHiddenControls = false;
+ self.idleSecondsCounter = 0;
+
+ $container
+ .toggleClass('fancybox-show-toolbar', !!( opts.toolbar && opts.buttons ) )
+ .toggleClass('fancybox-show-infobar', !!( opts.infobar && self.group.length > 1 ) )
+ .toggleClass('fancybox-show-nav', !!( opts.arrows && self.group.length > 1 ) )
+ .toggleClass('fancybox-is-modal', !!opts.modal );
+
+ if ( self.$caption ) {
+ $container.addClass( 'fancybox-show-caption ');
+
+ } else {
+ $container.removeClass( 'fancybox-show-caption' );
+ }
+
+ },
+
+
+ // Toggle toolbar and caption
+ // ==========================
+
+ toggleControls : function() {
+
+ if ( this.isHiddenControls ) {
+ this.showControls();
+
+ } else {
+ this.hideControls();
+ }
+
+ },
+
+
+ });
+
+
+ $.fancybox = {
+
+ version : "{fancybox-version}",
+ defaults : defaults,
+
+
+ // Get current instance and execute a command.
+ //
+ // Examples of usage:
+ //
+ // $instance = $.fancybox.getInstance();
+ // $.fancybox.getInstance().jumpTo( 1 );
+ // $.fancybox.getInstance( 'jumpTo', 1 );
+ // $.fancybox.getInstance( function() {
+ // console.info( this.currIndex );
+ // });
+ // ======================================================
+
+ getInstance : function ( command ) {
+ var instance = $('.fancybox-container:not(".fancybox-is-closing"):first').data( 'FancyBox' );
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ if ( instance instanceof FancyBox ) {
+
+ if ( $.type( command ) === 'string' ) {
+ instance[ command ].apply( instance, args );
+
+ } else if ( $.type( command ) === 'function' ) {
+ command.apply( instance, args );
+
+ }
+
+ return instance;
+ }
+
+ return false;
+
+ },
+
+
+ // Create new instance
+ // ===================
+
+ open : function ( items, opts, index ) {
+ return new FancyBox( items, opts, index );
+ },
+
+
+ // Close current or all instances
+ // ==============================
+
+ close : function ( all ) {
+ var instance = this.getInstance();
+
+ if ( instance ) {
+ instance.close();
+
+ // Try to find and close next instance
+
+ if ( all === true ) {
+ this.close();
+ }
+ }
+
+ },
+
+ // Close instances and unbind all events
+ // ==============================
+
+ destroy : function() {
+
+ this.close( true );
+
+ $D.off( 'click.fb-start' );
+
+ },
+
+
+ // Try to detect mobile devices
+ // ============================
+
+ isMobile : document.createTouch !== undefined && /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent),
+
+
+ // Detect if 'translate3d' support is available
+ // ============================================
+
+ use3d : (function() {
+ var div = document.createElement('div');
+
+ return window.getComputedStyle && window.getComputedStyle( div ).getPropertyValue('transform') && !(document.documentMode && document.documentMode < 11);
+ }()),
+
+
+ // Helper function to get current visual state of an element
+ // returns array[ top, left, horizontal-scale, vertical-scale, opacity ]
+ // =====================================================================
+
+ getTranslate : function( $el ) {
+ var matrix;
+
+ if ( !$el || !$el.length ) {
+ return false;
+ }
+
+ matrix = $el.eq( 0 ).css('transform');
+
+ if ( matrix && matrix.indexOf( 'matrix' ) !== -1 ) {
+ matrix = matrix.split('(')[1];
+ matrix = matrix.split(')')[0];
+ matrix = matrix.split(',');
+ } else {
+ matrix = [];
+ }
+
+ if ( matrix.length ) {
+
+ // If IE
+ if ( matrix.length > 10 ) {
+ matrix = [ matrix[13], matrix[12], matrix[0], matrix[5] ];
+
+ } else {
+ matrix = [ matrix[5], matrix[4], matrix[0], matrix[3]];
+ }
+
+ matrix = matrix.map(parseFloat);
+
+ } else {
+ matrix = [ 0, 0, 1, 1 ];
+
+ var transRegex = /\.*translate\((.*)px,(.*)px\)/i;
+ var transRez = transRegex.exec( $el.eq( 0 ).attr('style') );
+
+ if ( transRez ) {
+ matrix[ 0 ] = parseFloat( transRez[2] );
+ matrix[ 1 ] = parseFloat( transRez[1] );
+ }
+ }
+
+ return {
+ top : matrix[ 0 ],
+ left : matrix[ 1 ],
+ scaleX : matrix[ 2 ],
+ scaleY : matrix[ 3 ],
+ opacity : parseFloat( $el.css('opacity') ),
+ width : $el.width(),
+ height : $el.height()
+ };
+
+ },
+
+
+ // Shortcut for setting "translate3d" properties for element
+ // Can set be used to set opacity, too
+ // ========================================================
+
+ setTranslate : function( $el, props ) {
+ var str = '';
+ var css = {};
+
+ if ( !$el || !props ) {
+ return;
+ }
+
+ if ( props.left !== undefined || props.top !== undefined ) {
+ str = ( props.left === undefined ? $el.position().left : props.left ) + 'px, ' + ( props.top === undefined ? $el.position().top : props.top ) + 'px';
+
+ if ( this.use3d ) {
+ str = 'translate3d(' + str + ', 0px)';
+
+ } else {
+ str = 'translate(' + str + ')';
+ }
+ }
+
+ if ( props.scaleX !== undefined && props.scaleY !== undefined ) {
+ str = (str.length ? str + ' ' : '') + 'scale(' + props.scaleX + ', ' + props.scaleY + ')';
+ }
+
+ if ( str.length ) {
+ css.transform = str;
+ }
+
+ if ( props.opacity !== undefined ) {
+ css.opacity = props.opacity;
+ }
+
+ if ( props.width !== undefined ) {
+ css.width = props.width;
+ }
+
+ if ( props.height !== undefined ) {
+ css.height = props.height;
+ }
+
+ return $el.css( css );
+ },
+
+
+ // Simple CSS transition handler
+ // =============================
+
+ animate : function ( $el, to, duration, callback, leaveAnimationName ) {
+ var event = transitionEnd || 'transitionend';
+
+ if ( $.isFunction( duration ) ) {
+ callback = duration;
+ duration = null;
+ }
+
+ if ( !$.isPlainObject( to ) ) {
+ $el.removeAttr('style');
+ }
+
+ $el.on( event, function(e) {
+
+ // Skip events from child elements and z-index change
+ if ( e && e.originalEvent && ( !$el.is( e.originalEvent.target ) || e.originalEvent.propertyName == 'z-index' ) ) {
+ return;
+ }
+
+ $el.off( event );
+
+ if ( $.isPlainObject( to ) ) {
+
+ if ( to.scaleX !== undefined && to.scaleY !== undefined ) {
+ $el.css( 'transition-duration', '0ms' );
+
+ to.width = Math.round( $el.width() * to.scaleX );
+ to.height = Math.round( $el.height() * to.scaleY );
+
+ to.scaleX = 1;
+ to.scaleY = 1;
+
+ $.fancybox.setTranslate( $el, to );
+ }
+
+ } else if ( leaveAnimationName !== true ) {
+ $el.removeClass( to );
+ }
+
+ if ( $.isFunction( callback ) ) {
+ callback( e );
+ }
+
+ });
+
+ if ( $.isNumeric( duration ) ) {
+ $el.css( 'transition-duration', duration + 'ms' );
+ }
+
+ if ( $.isPlainObject( to ) ) {
+ $.fancybox.setTranslate( $el, to );
+
+ } else {
+ $el.addClass( to );
+ }
+
+ $el.data("timer", setTimeout(function() {
+ $el.trigger( 'transitionend' );
+ }, duration + 16));
+
+ },
+
+ stop : function( $el ) {
+ clearTimeout( $el.data("timer") );
+
+ $el.off( transitionEnd );
+ }
+
+ };
+
+
+ // Default click handler for "fancyboxed" links
+ // ============================================
+
+ function _run( e ) {
+ var target = e.currentTarget,
+ opts = e.data ? e.data.options : {},
+ items = opts.selector ? $( opts.selector ) : ( e.data ? e.data.items : [] ),
+ value = $(target).attr( 'data-fancybox' ) || '',
+ index = 0,
+ active = $.fancybox.getInstance();
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ // Avoid opening multiple times
+ if ( active && active.current.opts.$orig.is( target ) ) {
+ return;
+ }
+
+ // Get all related items and find index for clicked one
+ if ( value ) {
+ items = items.length ? items.filter( '[data-fancybox="' + value + '"]' ) : $( '[data-fancybox="' + value + '"]' );
+ index = items.index( target );
+
+ // Sometimes current item can not be found
+ // (for example, when slider clones items)
+ if ( index < 0 ) {
+ index = 0;
+ }
+
+ } else {
+ items = [ target ];
+ }
+
+ $.fancybox.open( items, opts, index );
+ }
+
+
+ // Create a jQuery plugin
+ // ======================
+
+ $.fn.fancybox = function (options) {
+ var selector;
+
+ options = options || {};
+ selector = options.selector || false;
+
+ if ( selector ) {
+
+ $( 'body' ).off( 'click.fb-start', selector ).on( 'click.fb-start', selector, {
+ options : options
+ }, _run );
+
+ } else {
+
+ this.off( 'click.fb-start' ).on( 'click.fb-start', {
+ items : this,
+ options : options
+ }, _run);
+
+ }
+
+ return this;
+ };
+
+
+ // Self initializing plugin
+ // ========================
+
+ $D.on( 'click.fb-start', '[data-fancybox]', _run );
+
+}( window, document, window.jQuery ));
--- /dev/null
+// ==========================================================================
+//
+// FullScreen
+// Adds fullscreen functionality
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ // Collection of methods supported by user browser
+ var fn = (function () {
+
+ var fnMap = [
+ [
+ 'requestFullscreen',
+ 'exitFullscreen',
+ 'fullscreenElement',
+ 'fullscreenEnabled',
+ 'fullscreenchange',
+ 'fullscreenerror'
+ ],
+ // new WebKit
+ [
+ 'webkitRequestFullscreen',
+ 'webkitExitFullscreen',
+ 'webkitFullscreenElement',
+ 'webkitFullscreenEnabled',
+ 'webkitfullscreenchange',
+ 'webkitfullscreenerror'
+
+ ],
+ // old WebKit (Safari 5.1)
+ [
+ 'webkitRequestFullScreen',
+ 'webkitCancelFullScreen',
+ 'webkitCurrentFullScreenElement',
+ 'webkitCancelFullScreen',
+ 'webkitfullscreenchange',
+ 'webkitfullscreenerror'
+
+ ],
+ [
+ 'mozRequestFullScreen',
+ 'mozCancelFullScreen',
+ 'mozFullScreenElement',
+ 'mozFullScreenEnabled',
+ 'mozfullscreenchange',
+ 'mozfullscreenerror'
+ ],
+ [
+ 'msRequestFullscreen',
+ 'msExitFullscreen',
+ 'msFullscreenElement',
+ 'msFullscreenEnabled',
+ 'MSFullscreenChange',
+ 'MSFullscreenError'
+ ]
+ ];
+
+ var val;
+ var ret = {};
+ var i, j;
+
+ for ( i = 0; i < fnMap.length; i++ ) {
+ val = fnMap[ i ];
+
+ if ( val && val[ 1 ] in document ) {
+ for ( j = 0; j < val.length; j++ ) {
+ ret[ fnMap[ 0 ][ j ] ] = val[ j ];
+ }
+
+ return ret;
+ }
+ }
+
+ return false;
+ })();
+
+ // If browser does not have Full Screen API, then simply unset default button template and stop
+ if ( !fn ) {
+ $.fancybox.defaults.btnTpl.fullScreen = false;
+
+ return;
+ }
+
+ var FullScreen = {
+ request : function ( elem ) {
+
+ elem = elem || document.documentElement;
+
+ elem[ fn.requestFullscreen ]( elem.ALLOW_KEYBOARD_INPUT );
+
+ },
+ exit : function () {
+
+ document[ fn.exitFullscreen ]();
+
+ },
+ toggle : function ( elem ) {
+
+ elem = elem || document.documentElement;
+
+ if ( this.isFullscreen() ) {
+ this.exit();
+
+ } else {
+ this.request( elem );
+ }
+
+ },
+ isFullscreen : function() {
+
+ return Boolean( document[ fn.fullscreenElement ] );
+
+ },
+ enabled : function() {
+
+ return Boolean( document[ fn.fullscreenEnabled ] );
+
+ }
+ };
+
+ $(document).on({
+ 'onInit.fb' : function(e, instance) {
+ var $container;
+
+ var $button = instance.$refs.toolbar.find('[data-fancybox-fullscreen]');
+
+ if ( instance && !instance.FullScreen && instance.group[ instance.currIndex ].opts.fullScreen ) {
+ $container = instance.$refs.container;
+
+ $container.on('click.fb-fullscreen', '[data-fancybox-fullscreen]', function(e) {
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ FullScreen.toggle( $container[ 0 ] );
+
+ });
+
+ if ( instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true ) {
+ FullScreen.request( $container[ 0 ] );
+ }
+
+ // Expose API
+ instance.FullScreen = FullScreen;
+
+ } else {
+ $button.hide();
+ }
+
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+
+ // "P" or Spacebar
+ if ( instance && instance.FullScreen && keycode === 70 ) {
+ keypress.preventDefault();
+
+ instance.FullScreen.toggle( instance.$refs.container[ 0 ] );
+ }
+
+ },
+
+ 'beforeClose.fb' : function( instance ) {
+ if ( instance && instance.FullScreen ) {
+ FullScreen.exit();
+ }
+ }
+ });
+
+ $(document).on(fn.fullscreenchange, function() {
+ var instance = $.fancybox.getInstance();
+
+ // If image is zooming, then force to stop and reposition properly
+ if ( instance.current && instance.current.type === 'image' && instance.isAnimating ) {
+ instance.current.$content.css( 'transition', 'none' );
+
+ instance.isAnimating = false;
+
+ instance.update( true, true, 0 );
+ }
+
+ });
+
+}(document, window.jQuery));
--- /dev/null
+// ==========================================================================
+//
+// Guestures
+// Adds touch guestures, handles click and tap events
+//
+// ==========================================================================
+;(function (window, document, $) {
+ 'use strict';
+
+ var requestAFrame = (function () {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ // if all else fails, use setTimeout
+ function (callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })();
+
+
+ var cancelAFrame = (function () {
+ return window.cancelAnimationFrame ||
+ window.webkitCancelAnimationFrame ||
+ window.mozCancelAnimationFrame ||
+ window.oCancelAnimationFrame ||
+ function (id) {
+ window.clearTimeout(id);
+ };
+ })();
+
+
+ var pointers = function( e ) {
+ var result = [];
+
+ e = e.originalEvent || e || window.e;
+ e = e.touches && e.touches.length ? e.touches : ( e.changedTouches && e.changedTouches.length ? e.changedTouches : [ e ] );
+
+ for ( var key in e ) {
+
+ if ( e[ key ].pageX ) {
+ result.push( { x : e[ key ].pageX, y : e[ key ].pageY } );
+
+ } else if ( e[ key ].clientX ) {
+ result.push( { x : e[ key ].clientX, y : e[ key ].clientY } );
+ }
+ }
+
+ return result;
+ };
+
+ var distance = function( point2, point1, what ) {
+ if ( !point1 || !point2 ) {
+ return 0;
+ }
+
+ if ( what === 'x' ) {
+ return point2.x - point1.x;
+
+ } else if ( what === 'y' ) {
+ return point2.y - point1.y;
+ }
+
+ return Math.sqrt( Math.pow( point2.x - point1.x, 2 ) + Math.pow( point2.y - point1.y, 2 ) );
+ };
+
+ var isClickable = function( $el ) {
+ if ( $el.is('a,button,input,select,textarea') || $.isFunction( $el.get(0).onclick ) ) {
+ return true;
+ }
+
+ // Check for attributes like data-fancybox-next or data-fancybox-close
+ for ( var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++ ) {
+ if ( atts[i].nodeName.substr(0, 14) === 'data-fancybox-' ) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ var hasScrollbars = function( el ) {
+ var overflowY = window.getComputedStyle( el )['overflow-y'];
+ var overflowX = window.getComputedStyle( el )['overflow-x'];
+
+ var vertical = (overflowY === 'scroll' || overflowY === 'auto') && el.scrollHeight > el.clientHeight;
+ var horizontal = (overflowX === 'scroll' || overflowX === 'auto') && el.scrollWidth > el.clientWidth;
+
+ return vertical || horizontal;
+ };
+
+ var isScrollable = function ( $el ) {
+ var rez = false;
+
+ while ( true ) {
+ rez = hasScrollbars( $el.get(0) );
+
+ if ( rez ) {
+ break;
+ }
+
+ $el = $el.parent();
+
+ if ( !$el.length || $el.hasClass( 'fancybox-stage' ) || $el.is( 'body' ) ) {
+ break;
+ }
+ }
+
+ return rez;
+ };
+
+
+ var Guestures = function ( instance ) {
+ var self = this;
+
+ self.instance = instance;
+
+ self.$bg = instance.$refs.bg;
+ self.$stage = instance.$refs.stage;
+ self.$container = instance.$refs.container;
+
+ self.destroy();
+
+ self.$container.on( 'touchstart.fb.touch mousedown.fb.touch', $.proxy(self, 'ontouchstart') );
+ };
+
+ Guestures.prototype.destroy = function() {
+ this.$container.off( '.fb.touch' );
+ };
+
+ Guestures.prototype.ontouchstart = function( e ) {
+ var self = this;
+
+ var $target = $( e.target );
+ var instance = self.instance;
+ var current = instance.current;
+ var $content = current.$content;
+
+ var isTouchDevice = ( e.type == 'touchstart' );
+
+ // Do not respond to both events
+ if ( isTouchDevice ) {
+ self.$container.off( 'mousedown.fb.touch' );
+ }
+
+ // Ignore clicks while zooming or closing
+ if ( !current || self.instance.isAnimating || self.instance.isClosing ) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ return;
+ }
+
+ // Ignore right click
+ if ( e.originalEvent && e.originalEvent.button == 2 ) {
+ return;
+ }
+
+ // Ignore taping on links, buttons, input elements
+ if ( !$target.length || isClickable( $target ) || isClickable( $target.parent() ) ) {
+ return;
+ }
+
+ // Ignore clicks on the scrollbar
+ if ( e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left ) {
+ return;
+ }
+
+ self.startPoints = pointers( e );
+
+ // Prevent zooming if already swiping
+ if ( !self.startPoints || ( self.startPoints.length > 1 && instance.isSliding ) ) {
+ return;
+ }
+
+ self.$target = $target;
+ self.$content = $content;
+ self.canTap = true;
+
+ $(document).off( '.fb.touch' );
+
+ $(document).on( isTouchDevice ? 'touchend.fb.touch touchcancel.fb.touch' : 'mouseup.fb.touch mouseleave.fb.touch', $.proxy(self, "ontouchend"));
+ $(document).on( isTouchDevice ? 'touchmove.fb.touch' : 'mousemove.fb.touch', $.proxy(self, "ontouchmove"));
+
+ e.stopPropagation();
+
+ if ( !(instance.current.opts.touch || instance.canPan() ) || !( $target.is( self.$stage ) || self.$stage.find( $target ).length ) ) {
+
+ // Prevent ghosting
+ if ( $target.is('img') ) {
+ e.preventDefault();
+ }
+
+ return;
+ }
+
+ if ( !( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) ) {
+ e.preventDefault();
+ }
+
+ self.canvasWidth = Math.round( current.$slide[0].clientWidth );
+ self.canvasHeight = Math.round( current.$slide[0].clientHeight );
+
+ self.startTime = new Date().getTime();
+ self.distanceX = self.distanceY = self.distance = 0;
+
+ self.isPanning = false;
+ self.isSwiping = false;
+ self.isZooming = false;
+
+ self.sliderStartPos = self.sliderLastPos || { top: 0, left: 0 };
+ self.contentStartPos = $.fancybox.getTranslate( self.$content );
+ self.contentLastPos = null;
+
+ if ( self.startPoints.length === 1 && !self.isZooming ) {
+ self.canTap = !instance.isSliding;
+
+ if ( current.type === 'image' && ( self.contentStartPos.width > self.canvasWidth + 1 || self.contentStartPos.height > self.canvasHeight + 1 ) ) {
+
+ $.fancybox.stop( self.$content );
+
+ self.$content.css( 'transition-duration', '0ms' );
+
+ self.isPanning = true;
+
+ } else {
+
+ self.isSwiping = true;
+ }
+
+ self.$container.addClass('fancybox-controls--isGrabbing');
+ }
+
+ if ( self.startPoints.length === 2 && !instance.isAnimating && !current.hasError && current.type === 'image' && ( current.isLoaded || current.$ghost ) ) {
+ self.isZooming = true;
+
+ self.isSwiping = false;
+ self.isPanning = false;
+
+ $.fancybox.stop( self.$content );
+
+ self.$content.css( 'transition-duration', '0ms' );
+
+ self.centerPointStartX = ( ( self.startPoints[0].x + self.startPoints[1].x ) * 0.5 ) - $(window).scrollLeft();
+ self.centerPointStartY = ( ( self.startPoints[0].y + self.startPoints[1].y ) * 0.5 ) - $(window).scrollTop();
+
+ self.percentageOfImageAtPinchPointX = ( self.centerPointStartX - self.contentStartPos.left ) / self.contentStartPos.width;
+ self.percentageOfImageAtPinchPointY = ( self.centerPointStartY - self.contentStartPos.top ) / self.contentStartPos.height;
+
+ self.startDistanceBetweenFingers = distance( self.startPoints[0], self.startPoints[1] );
+ }
+
+ };
+
+ Guestures.prototype.ontouchmove = function( e ) {
+
+ var self = this;
+
+ self.newPoints = pointers( e );
+
+ if ( $.fancybox.isMobile && ( isScrollable( self.$target ) || isScrollable( self.$target.parent() ) ) ) {
+ e.stopPropagation();
+
+ self.canTap = false;
+
+ return;
+ }
+
+ if ( !( self.instance.current.opts.touch || self.instance.canPan() ) || !self.newPoints || !self.newPoints.length ) {
+ return;
+ }
+
+ self.distanceX = distance( self.newPoints[0], self.startPoints[0], 'x' );
+ self.distanceY = distance( self.newPoints[0], self.startPoints[0], 'y' );
+
+ self.distance = distance( self.newPoints[0], self.startPoints[0] );
+
+ // Skip false ontouchmove events (Chrome)
+ if ( self.distance > 0 ) {
+
+ if ( !( self.$target.is( self.$stage ) || self.$stage.find( self.$target ).length ) ) {
+ return;
+ }
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ if ( self.isSwiping ) {
+ self.onSwipe();
+
+ } else if ( self.isPanning ) {
+ self.onPan();
+
+ } else if ( self.isZooming ) {
+ self.onZoom();
+ }
+
+ }
+
+ };
+
+ Guestures.prototype.onSwipe = function() {
+
+ var self = this;
+
+ var swiping = self.isSwiping;
+ var left = self.sliderStartPos.left || 0;
+ var angle;
+
+ if ( swiping === true ) {
+
+ if ( Math.abs( self.distance ) > 10 ) {
+
+ self.canTap = false;
+
+ if ( self.instance.group.length < 2 && self.instance.opts.touch.vertical ) {
+ self.isSwiping = 'y';
+
+ } else if ( self.instance.isSliding || self.instance.opts.touch.vertical === false || ( self.instance.opts.touch.vertical === 'auto' && $( window ).width() > 800 ) ) {
+ self.isSwiping = 'x';
+
+ } else {
+ angle = Math.abs( Math.atan2( self.distanceY, self.distanceX ) * 180 / Math.PI );
+
+ self.isSwiping = ( angle > 45 && angle < 135 ) ? 'y' : 'x';
+ }
+
+ self.instance.isSliding = self.isSwiping;
+
+ // Reset points to avoid jumping, because we dropped first swipes to calculate the angle
+ self.startPoints = self.newPoints;
+
+ $.each(self.instance.slides, function( index, slide ) {
+ $.fancybox.stop( slide.$slide );
+
+ slide.$slide.css( 'transition-duration', '0ms' );
+
+ slide.inTransition = false;
+
+ if ( slide.pos === self.instance.current.pos ) {
+ self.sliderStartPos.left = $.fancybox.getTranslate( slide.$slide ).left;
+ }
+ });
+
+ //self.instance.current.isMoved = true;
+
+ // Stop slideshow
+ if ( self.instance.SlideShow && self.instance.SlideShow.isActive ) {
+ self.instance.SlideShow.stop();
+ }
+ }
+
+ } else {
+
+ if ( swiping == 'x' ) {
+
+ // Sticky edges
+ if ( self.distanceX > 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === 0 && !self.instance.current.opts.loop ) ) ) {
+ left = left + Math.pow( self.distanceX, 0.8 );
+
+ } else if ( self.distanceX < 0 && ( self.instance.group.length < 2 || ( self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop ) ) ) {
+ left = left - Math.pow( -self.distanceX, 0.8 );
+
+ } else {
+ left = left + self.distanceX;
+ }
+
+ }
+
+ self.sliderLastPos = {
+ top : swiping == 'x' ? 0 : self.sliderStartPos.top + self.distanceY,
+ left : left
+ };
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+
+ if ( self.sliderLastPos ) {
+ $.each(self.instance.slides, function( index, slide ) {
+ var pos = slide.pos - self.instance.currPos;
+
+ $.fancybox.setTranslate( slide.$slide, {
+ top : self.sliderLastPos.top,
+ left : self.sliderLastPos.left + ( pos * self.canvasWidth ) + ( pos * slide.opts.gutter )
+ });
+ });
+
+ self.$container.addClass( 'fancybox-is-sliding' );
+ }
+
+ });
+
+ }
+
+ };
+
+ Guestures.prototype.onPan = function() {
+
+ var self = this;
+
+ var newOffsetX, newOffsetY, newPos;
+
+ self.canTap = false;
+
+ if ( self.contentStartPos.width > self.canvasWidth ) {
+ newOffsetX = self.contentStartPos.left + self.distanceX;
+
+ } else {
+ newOffsetX = self.contentStartPos.left;
+ }
+
+ newOffsetY = self.contentStartPos.top + self.distanceY;
+
+ newPos = self.limitMovement( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
+
+ newPos.scaleX = self.contentStartPos.scaleX;
+ newPos.scaleY = self.contentStartPos.scaleY;
+
+ self.contentLastPos = newPos;
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+ $.fancybox.setTranslate( self.$content, self.contentLastPos );
+ });
+ };
+
+ // Make panning sticky to the edges
+ Guestures.prototype.limitMovement = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
+
+ var self = this;
+
+ var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY;
+
+ var canvasWidth = self.canvasWidth;
+ var canvasHeight = self.canvasHeight;
+
+ var currentOffsetX = self.contentStartPos.left;
+ var currentOffsetY = self.contentStartPos.top;
+
+ var distanceX = self.distanceX;
+ var distanceY = self.distanceY;
+
+ // Slow down proportionally to traveled distance
+
+ minTranslateX = Math.max(0, canvasWidth * 0.5 - newWidth * 0.5 );
+ minTranslateY = Math.max(0, canvasHeight * 0.5 - newHeight * 0.5 );
+
+ maxTranslateX = Math.min( canvasWidth - newWidth, canvasWidth * 0.5 - newWidth * 0.5 );
+ maxTranslateY = Math.min( canvasHeight - newHeight, canvasHeight * 0.5 - newHeight * 0.5 );
+
+ if ( newWidth > canvasWidth ) {
+
+ // ->
+ if ( distanceX > 0 && newOffsetX > minTranslateX ) {
+ newOffsetX = minTranslateX - 1 + Math.pow( -minTranslateX + currentOffsetX + distanceX, 0.8 ) || 0;
+ }
+
+ // <-
+ if ( distanceX < 0 && newOffsetX < maxTranslateX ) {
+ newOffsetX = maxTranslateX + 1 - Math.pow( maxTranslateX - currentOffsetX - distanceX, 0.8 ) || 0;
+ }
+
+ }
+
+ if ( newHeight > canvasHeight ) {
+
+ // \/
+ if ( distanceY > 0 && newOffsetY > minTranslateY ) {
+ newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8 ) || 0;
+ }
+
+ // /\
+ if ( distanceY < 0 && newOffsetY < maxTranslateY ) {
+ newOffsetY = maxTranslateY + 1 - Math.pow ( maxTranslateY - currentOffsetY - distanceY, 0.8 ) || 0;
+ }
+
+ }
+
+ return {
+ top : newOffsetY,
+ left : newOffsetX
+ };
+
+ };
+
+
+ Guestures.prototype.limitPosition = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
+
+ var self = this;
+
+ var canvasWidth = self.canvasWidth;
+ var canvasHeight = self.canvasHeight;
+
+ if ( newWidth > canvasWidth ) {
+ newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;
+ newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;
+
+ } else {
+
+ // Center horizontally
+ newOffsetX = Math.max( 0, canvasWidth / 2 - newWidth / 2 );
+
+ }
+
+ if ( newHeight > canvasHeight ) {
+ newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;
+ newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;
+
+ } else {
+
+ // Center vertically
+ newOffsetY = Math.max( 0, canvasHeight / 2 - newHeight / 2 );
+
+ }
+
+ return {
+ top : newOffsetY,
+ left : newOffsetX
+ };
+
+ };
+
+ Guestures.prototype.onZoom = function() {
+
+ var self = this;
+
+ // Calculate current distance between points to get pinch ratio and new width and height
+
+ var currentWidth = self.contentStartPos.width;
+ var currentHeight = self.contentStartPos.height;
+
+ var currentOffsetX = self.contentStartPos.left;
+ var currentOffsetY = self.contentStartPos.top;
+
+ var endDistanceBetweenFingers = distance( self.newPoints[0], self.newPoints[1] );
+
+ var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;
+
+ var newWidth = Math.floor( currentWidth * pinchRatio );
+ var newHeight = Math.floor( currentHeight * pinchRatio );
+
+ // This is the translation due to pinch-zooming
+ var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX;
+ var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;
+
+ //Point between the two touches
+
+ var centerPointEndX = ((self.newPoints[0].x + self.newPoints[1].x) / 2) - $(window).scrollLeft();
+ var centerPointEndY = ((self.newPoints[0].y + self.newPoints[1].y) / 2) - $(window).scrollTop();
+
+ // And this is the translation due to translation of the centerpoint
+ // between the two fingers
+
+ var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;
+ var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;
+
+ // The new offset is the old/current one plus the total translation
+
+ var newOffsetX = currentOffsetX + ( translateFromZoomingX + translateFromTranslatingX );
+ var newOffsetY = currentOffsetY + ( translateFromZoomingY + translateFromTranslatingY );
+
+ var newPos = {
+ top : newOffsetY,
+ left : newOffsetX,
+ scaleX : self.contentStartPos.scaleX * pinchRatio,
+ scaleY : self.contentStartPos.scaleY * pinchRatio
+ };
+
+ self.canTap = false;
+
+ self.newWidth = newWidth;
+ self.newHeight = newHeight;
+
+ self.contentLastPos = newPos;
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.requestId = requestAFrame(function() {
+ $.fancybox.setTranslate( self.$content, self.contentLastPos );
+ });
+
+ };
+
+ Guestures.prototype.ontouchend = function( e ) {
+
+ var self = this;
+ var dMs = Math.max( (new Date().getTime() ) - self.startTime, 1);
+
+ var swiping = self.isSwiping;
+ var panning = self.isPanning;
+ var zooming = self.isZooming;
+
+ self.endPoints = pointers( e );
+
+ self.$container.removeClass( 'fancybox-controls--isGrabbing' );
+
+ $(document).off( '.fb.touch' );
+
+ if ( self.requestId ) {
+ cancelAFrame( self.requestId );
+
+ self.requestId = null;
+ }
+
+ self.isSwiping = false;
+ self.isPanning = false;
+ self.isZooming = false;
+
+ if ( self.canTap ) {
+ return self.onTap( e );
+ }
+
+ self.speed = 366;
+
+ // Speed in px/ms
+ self.velocityX = self.distanceX / dMs * 0.5;
+ self.velocityY = self.distanceY / dMs * 0.5;
+
+ self.speedX = Math.max( self.speed * 0.5, Math.min( self.speed * 1.5, ( 1 / Math.abs( self.velocityX ) ) * self.speed ) );
+
+ if ( panning ) {
+ self.endPanning();
+
+ } else if ( zooming ) {
+ self.endZooming();
+
+ } else {
+ self.endSwiping( swiping );
+ }
+
+ return;
+ };
+
+ Guestures.prototype.endSwiping = function( swiping ) {
+
+ var self = this;
+ var ret = false;
+
+ self.instance.isSliding = false;
+ self.sliderLastPos = null;
+
+ // Close if swiped vertically / navigate if horizontally
+ if ( swiping == 'y' && Math.abs( self.distanceY ) > 50 ) {
+
+ // Continue vertical movement
+ $.fancybox.animate( self.instance.current.$slide, {
+ top : self.sliderStartPos.top + self.distanceY + ( self.velocityY * 150 ),
+ opacity : 0
+ }, 150 );
+
+ ret = self.instance.close( true, 300 );
+
+ } else if ( swiping == 'x' && self.distanceX > 50 && self.instance.group.length > 1 ) {
+ ret = self.instance.previous( self.speedX );
+
+ } else if ( swiping == 'x' && self.distanceX < -50 && self.instance.group.length > 1 ) {
+ ret = self.instance.next( self.speedX );
+ }
+
+ if ( ret === false && ( swiping == 'x' || swiping == 'y' ) ) {
+ self.instance.jumpTo( self.instance.current.index, 150 );
+ }
+
+ self.$container.removeClass( 'fancybox-is-sliding' );
+
+ };
+
+ // Limit panning from edges
+ // ========================
+
+ Guestures.prototype.endPanning = function() {
+
+ var self = this;
+ var newOffsetX, newOffsetY, newPos;
+
+ if ( !self.contentLastPos ) {
+ return;
+ }
+
+ if ( self.instance.current.opts.touch.momentum === false ) {
+ newOffsetX = self.contentLastPos.left;
+ newOffsetY = self.contentLastPos.top;
+
+ } else {
+
+ // Continue movement
+ newOffsetX = self.contentLastPos.left + ( self.velocityX * self.speed );
+ newOffsetY = self.contentLastPos.top + ( self.velocityY * self.speed );
+ }
+
+ newPos = self.limitPosition( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
+
+ newPos.width = self.contentStartPos.width;
+ newPos.height = self.contentStartPos.height;
+
+ $.fancybox.animate( self.$content, newPos, 330 );
+ };
+
+
+ Guestures.prototype.endZooming = function() {
+
+ var self = this;
+
+ var current = self.instance.current;
+
+ var newOffsetX, newOffsetY, newPos, reset;
+
+ var newWidth = self.newWidth;
+ var newHeight = self.newHeight;
+
+ if ( !self.contentLastPos ) {
+ return;
+ }
+
+ newOffsetX = self.contentLastPos.left;
+ newOffsetY = self.contentLastPos.top;
+
+ reset = {
+ top : newOffsetY,
+ left : newOffsetX,
+ width : newWidth,
+ height : newHeight,
+ scaleX : 1,
+ scaleY : 1
+ };
+
+ // Reset scalex/scaleY values; this helps for perfomance and does not break animation
+ $.fancybox.setTranslate( self.$content, reset );
+
+ if ( newWidth < self.canvasWidth && newHeight < self.canvasHeight ) {
+ self.instance.scaleToFit( 150 );
+
+ } else if ( newWidth > current.width || newHeight > current.height ) {
+ self.instance.scaleToActual( self.centerPointStartX, self.centerPointStartY, 150 );
+
+ } else {
+
+ newPos = self.limitPosition( newOffsetX, newOffsetY, newWidth, newHeight );
+
+ // Switch from scale() to width/height or animation will not work correctly
+ $.fancybox.setTranslate( self.content, $.fancybox.getTranslate( self.$content ) );
+
+ $.fancybox.animate( self.$content, newPos, 150 );
+ }
+
+ };
+
+ Guestures.prototype.onTap = function(e) {
+ var self = this;
+ var $target = $( e.target );
+
+ var instance = self.instance;
+ var current = instance.current;
+
+ var endPoints = ( e && pointers( e ) ) || self.startPoints;
+
+ var tapX = endPoints[0] ? endPoints[0].x - self.$stage.offset().left : 0;
+ var tapY = endPoints[0] ? endPoints[0].y - self.$stage.offset().top : 0;
+
+ var where;
+
+ var process = function ( prefix ) {
+
+ var action = current.opts[ prefix ];
+
+ if ( $.isFunction( action ) ) {
+ action = action.apply( instance, [ current, e ] );
+ }
+
+ if ( !action) {
+ return;
+ }
+
+ switch ( action ) {
+
+ case "close" :
+
+ instance.close( self.startEvent );
+
+ break;
+
+ case "toggleControls" :
+
+ instance.toggleControls( true );
+
+ break;
+
+ case "next" :
+
+ instance.next();
+
+ break;
+
+ case "nextOrClose" :
+
+ if ( instance.group.length > 1 ) {
+ instance.next();
+
+ } else {
+ instance.close( self.startEvent );
+ }
+
+ break;
+
+ case "zoom" :
+
+ if ( current.type == 'image' && ( current.isLoaded || current.$ghost ) ) {
+
+ if ( instance.canPan() ) {
+ instance.scaleToFit();
+
+ } else if ( instance.isScaledDown() ) {
+ instance.scaleToActual( tapX, tapY );
+
+ } else if ( instance.group.length < 2 ) {
+ instance.close( self.startEvent );
+ }
+ }
+
+ break;
+ }
+
+ };
+
+ // Ignore right click
+ if ( e.originalEvent && e.originalEvent.button == 2 ) {
+ return;
+ }
+
+ // Skip if current slide is not in the center
+ if ( instance.isSliding ) {
+ return;
+ }
+
+ // Skip if clicked on the scrollbar
+ if ( tapX > $target[0].clientWidth + $target.offset().left ) {
+ return;
+ }
+
+ // Check where is clicked
+ if ( $target.is( '.fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container' ) ) {
+ where = 'Outside';
+
+ } else if ( $target.is( '.fancybox-slide' ) ) {
+ where = 'Slide';
+
+ } else if ( instance.current.$content && instance.current.$content.has( e.target ).length ) {
+ where = 'Content';
+
+ } else {
+ return;
+ }
+
+ // Check if this is a double tap
+ if ( self.tapped ) {
+
+ // Stop previously created single tap
+ clearTimeout( self.tapped );
+ self.tapped = null;
+
+ // Skip if distance between taps is too big
+ if ( Math.abs( tapX - self.tapX ) > 50 || Math.abs( tapY - self.tapY ) > 50 || instance.isSliding ) {
+ return this;
+ }
+
+ // OK, now we assume that this is a double-tap
+ process( 'dblclick' + where );
+
+ } else {
+
+ // Single tap will be processed if user has not clicked second time within 300ms
+ // or there is no need to wait for double-tap
+ self.tapX = tapX;
+ self.tapY = tapY;
+
+ if ( current.opts[ 'dblclick' + where ] && current.opts[ 'dblclick' + where ] !== current.opts[ 'click' + where ] ) {
+ self.tapped = setTimeout(function() {
+ self.tapped = null;
+
+ process( 'click' + where );
+
+ }, 300);
+
+ } else {
+ process( 'click' + where );
+ }
+
+ }
+
+ return this;
+ };
+
+ $(document).on('onActivate.fb', function (e, instance) {
+ if ( instance && !instance.Guestures ) {
+ instance.Guestures = new Guestures( instance );
+ }
+ });
+
+ $(document).on('beforeClose.fb', function (e, instance) {
+ if ( instance && instance.Guestures ) {
+ instance.Guestures.destroy();
+ }
+ });
+
+
+}(window, document, window.jQuery));
--- /dev/null
+// ==========================================================================
+//
+// Hash
+// Enables linking to each modal
+//
+// ==========================================================================
+;(function (document, window, $) {
+ 'use strict';
+
+ // Simple $.escapeSelector polyfill (for jQuery prior v3)
+ if ( !$.escapeSelector ) {
+ $.escapeSelector = function( sel ) {
+ var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
+ var fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ };
+
+ return ( sel + "" ).replace( rcssescape, fcssescape );
+ };
+ }
+
+ // Variable containing last hash value set by fancyBox
+ // It will be used to determine if fancyBox needs to close after hash change is detected
+ var currentHash = null;
+
+ // Throtlling the history change
+ var timerID = null;
+
+ // Get info about gallery name and current index from url
+ function parseUrl() {
+ var hash = window.location.hash.substr( 1 );
+ var rez = hash.split( '-' );
+ var index = rez.length > 1 && /^\+?\d+$/.test( rez[ rez.length - 1 ] ) ? parseInt( rez.pop( -1 ), 10 ) || 1 : 1;
+ var gallery = rez.join( '-' );
+
+ // Index is starting from 1
+ if ( index < 1 ) {
+ index = 1;
+ }
+
+ return {
+ hash : hash,
+ index : index,
+ gallery : gallery
+ };
+ }
+
+ // Trigger click evnt on links to open new fancyBox instance
+ function triggerFromUrl( url ) {
+ var $el;
+
+ if ( url.gallery !== '' ) {
+
+ // If we can find element matching 'data-fancybox' atribute, then trigger click event for that ..
+ $el = $( "[data-fancybox='" + $.escapeSelector( url.gallery ) + "']" ).eq( url.index - 1 );
+
+ if ( $el.length ) {
+ $el.trigger( 'click' );
+
+ } else {
+
+ // .. if not, try finding element by ID
+ $( "#" + $.escapeSelector( url.gallery ) + "" ).trigger( 'click' );
+
+ }
+
+ }
+ }
+
+ // Get gallery name from current instance
+ function getGallery( instance ) {
+ var opts;
+
+ if ( !instance ) {
+ return false;
+ }
+
+ opts = instance.current ? instance.current.opts : instance.opts;
+
+ return opts.$orig ? opts.$orig.data( 'fancybox' ) : ( opts.hash || '' );
+ }
+
+ // Star when DOM becomes ready
+ $(function() {
+
+ // Small delay is used to allow other scripts to process "dom ready" event
+ setTimeout(function() {
+
+ // Check if this module is not disabled
+ if ( $.fancybox.defaults.hash === false ) {
+ return;
+ }
+
+ // Update hash when opening/closing fancyBox
+ $(document).on({
+ 'onInit.fb' : function( e, instance ) {
+ var url, gallery;
+
+ if ( instance.group[ instance.currIndex ].opts.hash === false ) {
+ return;
+ }
+
+ url = parseUrl();
+ gallery = getGallery( instance );
+
+ // Make sure gallery start index matches index from hash
+ if ( gallery && url.gallery && gallery == url.gallery ) {
+ instance.currIndex = url.index - 1;
+ }
+
+ },
+
+ 'beforeShow.fb' : function( e, instance, current, firstRun ) {
+ var gallery;
+
+ if ( current.opts.hash === false ) {
+ return;
+ }
+
+ gallery = getGallery( instance );
+
+ // Update window hash
+ if ( gallery && gallery !== '' ) {
+
+ if ( window.location.hash.indexOf( gallery ) < 0 ) {
+ instance.opts.origHash = window.location.hash;
+ }
+
+ currentHash = gallery + ( instance.group.length > 1 ? '-' + ( current.index + 1 ) : '' );
+
+ if ( 'replaceState' in window.history ) {
+ if ( timerID ) {
+ clearTimeout( timerID );
+ }
+
+ timerID = setTimeout(function() {
+ window.history[ firstRun ? 'pushState' : 'replaceState' ]( {} , document.title, window.location.pathname + window.location.search + '#' + currentHash );
+
+ timerID = null;
+
+ }, 300);
+
+ } else {
+ window.location.hash = currentHash;
+ }
+
+ }
+
+ },
+
+ 'beforeClose.fb' : function( e, instance, current ) {
+ var gallery, origHash;
+
+ if ( timerID ) {
+ clearTimeout( timerID );
+ }
+
+ if ( current.opts.hash === false ) {
+ return;
+ }
+
+ gallery = getGallery( instance );
+ origHash = instance && instance.opts.origHash ? instance.opts.origHash : '';
+
+ // Remove hash from location bar
+ if ( gallery && gallery !== '' ) {
+
+ if ( 'replaceState' in history ) {
+ window.history.replaceState( {} , document.title, window.location.pathname + window.location.search + origHash );
+
+ } else {
+ window.location.hash = origHash;
+
+ // Keep original scroll position
+ $( window ).scrollTop( instance.scrollTop ).scrollLeft( instance.scrollLeft );
+ }
+ }
+
+ currentHash = null;
+ }
+ });
+
+ // Check if need to close after url has changed
+ $(window).on('hashchange.fb', function() {
+ var url = parseUrl();
+
+ if ( $.fancybox.getInstance() ) {
+ if ( currentHash && currentHash !== url.gallery + '-' + url.index && !( url.index === 1 && currentHash == url.gallery ) ) {
+ currentHash = null;
+
+ $.fancybox.close();
+ }
+
+ } else if ( url.gallery !== '' ) {
+ triggerFromUrl( url );
+ }
+ });
+
+ // If navigating away from current page
+ $(window).one('unload.fb popstate.fb', function() {
+ $.fancybox.getInstance( 'close', true, 0 );
+ });
+
+ // Check current hash and trigger click event on matching element to start fancyBox, if needed
+ triggerFromUrl( parseUrl() );
+
+ }, 50);
+
+ });
+
+
+}(document, window, window.jQuery));
--- /dev/null
+// ==========================================================================
+//
+// Media
+// Adds additional media type support
+//
+// ==========================================================================
+;(function ($) {
+
+ 'use strict';
+
+ // Formats matching url to final form
+
+ var format = function (url, rez, params) {
+ if ( !url ) {
+ return;
+ }
+
+ params = params || '';
+
+ if ( $.type(params) === "object" ) {
+ params = $.param(params, true);
+ }
+
+ $.each(rez, function (key, value) {
+ url = url.replace('$' + key, value || '');
+ });
+
+ if (params.length) {
+ url += (url.indexOf('?') > 0 ? '&' : '?') + params;
+ }
+
+ return url;
+ };
+
+ // Object containing properties for each media type
+
+ var defaults = {
+ youtube : {
+ matcher : /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
+ params : {
+ autoplay : 1,
+ autohide : 1,
+ fs : 1,
+ rel : 0,
+ hd : 1,
+ wmode : 'transparent',
+ enablejsapi : 1,
+ html5 : 1
+ },
+ paramPlace : 8,
+ type : 'iframe',
+ url : '//www.youtube.com/embed/$4',
+ thumb : '//img.youtube.com/vi/$4/hqdefault.jpg'
+ },
+
+ vimeo : {
+ matcher : /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,
+ params : {
+ autoplay : 1,
+ hd : 1,
+ show_title : 1,
+ show_byline : 1,
+ show_portrait : 0,
+ fullscreen : 1,
+ api : 1
+ },
+ paramPlace : 3,
+ type : 'iframe',
+ url : '//player.vimeo.com/video/$2'
+ },
+
+ metacafe : {
+ matcher : /metacafe.com\/watch\/(\d+)\/(.*)?/,
+ type : 'iframe',
+ url : '//www.metacafe.com/embed/$1/?ap=1'
+ },
+
+ dailymotion : {
+ matcher : /dailymotion.com\/video\/(.*)\/?(.*)/,
+ params : {
+ additionalInfos : 0,
+ autoStart : 1
+ },
+ type : 'iframe',
+ url : '//www.dailymotion.com/embed/video/$1'
+ },
+
+ vine : {
+ matcher : /vine.co\/v\/([a-zA-Z0-9\?\=\-]+)/,
+ type : 'iframe',
+ url : '//vine.co/v/$1/embed/simple'
+ },
+
+ instagram : {
+ matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
+ type : 'image',
+ url : '//$1/p/$2/media/?size=l'
+ },
+
+ // Examples:
+ // http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
+ // https://www.google.com/maps/@37.7852006,-122.4146355,14.65z
+ // https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572
+ gmap_place : {
+ matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,
+ type : 'iframe',
+ url : function (rez) {
+ return '//maps.google.' + rez[2] + '/?ll=' + ( rez[9] ? rez[9] + '&z=' + Math.floor( rez[10] ) + ( rez[12] ? rez[12].replace(/^\//, "&") : '' ) : rez[12] ) + '&output=' + ( rez[12] && rez[12].indexOf('layer=c') > 0 ? 'svembed' : 'embed' );
+ }
+ },
+
+ // Examples:
+ // https://www.google.com/maps/search/Empire+State+Building/
+ // https://www.google.com/maps/search/?api=1&query=centurylink+field
+ // https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393
+ gmap_search : {
+ matcher : /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,
+ type : 'iframe',
+ url : function (rez) {
+ return '//maps.google.' + rez[2] + '/maps?q=' + rez[5].replace('query=', 'q=').replace('api=1', '') + '&output=embed';
+ }
+ }
+ };
+
+ $(document).on('onInit.fb', function (e, instance) {
+
+ $.each(instance.group, function( i, item ) {
+
+ var url = item.src || '',
+ type = false,
+ media,
+ thumb,
+ rez,
+ params,
+ urlParams,
+ o,
+ provider;
+
+ // Skip items that already have content type
+ if ( item.type ) {
+ return;
+ }
+
+ media = $.extend( true, {}, defaults, item.opts.media );
+
+ // Look for any matching media type
+ $.each(media, function ( n, el ) {
+ rez = url.match(el.matcher);
+ o = {};
+ provider = n;
+
+ if (!rez) {
+ return;
+ }
+
+ type = el.type;
+
+ if ( el.paramPlace && rez[ el.paramPlace ] ) {
+ urlParams = rez[ el.paramPlace ];
+
+ if ( urlParams[ 0 ] == '?' ) {
+ urlParams = urlParams.substring(1);
+ }
+
+ urlParams = urlParams.split('&');
+
+ for ( var m = 0; m < urlParams.length; ++m ) {
+ var p = urlParams[ m ].split('=', 2);
+
+ if ( p.length == 2 ) {
+ o[ p[0] ] = decodeURIComponent( p[1].replace(/\+/g, " ") );
+ }
+ }
+ }
+
+ params = $.extend( true, {}, el.params, item.opts[ n ], o );
+
+ url = $.type(el.url) === "function" ? el.url.call(this, rez, params, item) : format(el.url, rez, params);
+ thumb = $.type(el.thumb) === "function" ? el.thumb.call(this, rez, params, item) : format(el.thumb, rez);
+
+ if ( provider === 'vimeo' ) {
+ url = url.replace('&%23', '#');
+ }
+
+ return false;
+ });
+
+ // If it is found, then change content type and update the url
+
+ if ( type ) {
+ item.src = url;
+ item.type = type;
+
+ if ( !item.opts.thumb && !( item.opts.$thumb && item.opts.$thumb.length ) ) {
+ item.opts.thumb = thumb;
+ }
+
+ if ( type === 'iframe' ) {
+ $.extend(true, item.opts, {
+ iframe : {
+ preload : false,
+ attr : {
+ scrolling : "no"
+ }
+ }
+ });
+
+ item.contentProvider = provider;
+
+ item.opts.slideClass += ' fancybox-slide--' + ( provider == 'gmap_place' || provider == 'gmap_search' ? 'map' : 'video' );
+ }
+
+ } else {
+
+ // If no content type is found, then set it to `image` as fallback
+ item.type = 'image';
+ }
+
+ });
+
+ });
+
+}(window.jQuery));
--- /dev/null
+// ==========================================================================
+//
+// SlideShow
+// Enables slideshow functionality
+//
+// Example of usage:
+// $.fancybox.getInstance().SlideShow.start()
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ var SlideShow = function( instance ) {
+ this.instance = instance;
+ this.init();
+ };
+
+ $.extend( SlideShow.prototype, {
+ timer : null,
+ isActive : false,
+ $button : null,
+ speed : 3000,
+
+ init : function() {
+ var self = this;
+
+ self.$button = self.instance.$refs.toolbar.find('[data-fancybox-play]').on('click', function() {
+ self.toggle();
+ });
+
+ if ( self.instance.group.length < 2 || !self.instance.group[ self.instance.currIndex ].opts.slideShow ) {
+ self.$button.hide();
+ }
+ },
+
+ set : function() {
+ var self = this;
+
+ // Check if reached last element
+ if ( self.instance && self.instance.current && (self.instance.current.opts.loop || self.instance.currIndex < self.instance.group.length - 1 )) {
+ self.timer = setTimeout(function() {
+ self.instance.next();
+
+ }, self.instance.current.opts.slideShow.speed || self.speed);
+
+ } else {
+ self.stop();
+ self.instance.idleSecondsCounter = 0;
+ self.instance.showControls();
+ }
+
+ },
+
+ clear : function() {
+ var self = this;
+
+ clearTimeout( self.timer );
+
+ self.timer = null;
+ },
+
+ start : function() {
+ var self = this;
+ var current = self.instance.current;
+
+ if ( self.instance && current && ( current.opts.loop || current.index < self.instance.group.length - 1 )) {
+
+ self.isActive = true;
+
+ self.$button
+ .attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_STOP )
+ .addClass( 'fancybox-button--pause' );
+
+ if ( current.isComplete ) {
+ self.set();
+ }
+ }
+ },
+
+ stop : function() {
+ var self = this;
+ var current = self.instance.current;
+
+ self.clear();
+
+ self.$button
+ .attr( 'title', current.opts.i18n[ current.opts.lang ].PLAY_START )
+ .removeClass( 'fancybox-button--pause' );
+
+ self.isActive = false;
+ },
+
+ toggle : function() {
+ var self = this;
+
+ if ( self.isActive ) {
+ self.stop();
+
+ } else {
+ self.start();
+ }
+ }
+
+ });
+
+ $(document).on({
+ 'onInit.fb' : function(e, instance) {
+ if ( instance && !instance.SlideShow ) {
+ instance.SlideShow = new SlideShow( instance );
+ }
+ },
+
+ 'beforeShow.fb' : function(e, instance, current, firstRun) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( firstRun ) {
+
+ if ( SlideShow && current.opts.slideShow.autoStart ) {
+ SlideShow.start();
+ }
+
+ } else if ( SlideShow && SlideShow.isActive ) {
+ SlideShow.clear();
+ }
+ },
+
+ 'afterShow.fb' : function(e, instance, current) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow && SlideShow.isActive ) {
+ SlideShow.set();
+ }
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+ var SlideShow = instance && instance.SlideShow;
+
+ // "P" or Spacebar
+ if ( SlideShow && current.opts.slideShow && ( keycode === 80 || keycode === 32 ) && !$(document.activeElement).is( 'button,a,input' ) ) {
+ keypress.preventDefault();
+
+ SlideShow.toggle();
+ }
+ },
+
+ 'beforeClose.fb onDeactivate.fb' : function(e, instance) {
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow ) {
+ SlideShow.stop();
+ }
+ }
+ });
+
+ // Page Visibility API to pause slideshow when window is not active
+ $(document).on("visibilitychange", function() {
+ var instance = $.fancybox.getInstance();
+ var SlideShow = instance && instance.SlideShow;
+
+ if ( SlideShow && SlideShow.isActive ) {
+ if ( document.hidden ) {
+ SlideShow.clear();
+
+ } else {
+ SlideShow.set();
+ }
+ }
+ });
+
+}(document, window.jQuery));
--- /dev/null
+// ==========================================================================
+//
+// Thumbs
+// Displays thumbnails in a grid
+//
+// ==========================================================================
+;(function (document, $) {
+ 'use strict';
+
+ var FancyThumbs = function( instance ) {
+ this.instance = instance;
+ this.init();
+ };
+
+ $.extend( FancyThumbs.prototype, {
+
+ $button : null,
+ $grid : null,
+ $list : null,
+ isVisible : false,
+
+ init : function() {
+ var self = this;
+
+ var first = self.instance.group[0],
+ second = self.instance.group[1];
+
+ self.$button = self.instance.$refs.toolbar.find( '[data-fancybox-thumbs]' );
+
+ if ( self.instance.group.length > 1 && self.instance.group[ self.instance.currIndex ].opts.thumbs && (
+ ( first.type == 'image' || first.opts.thumb || first.opts.$thumb ) &&
+ ( second.type == 'image' || second.opts.thumb || second.opts.$thumb )
+ )) {
+
+ self.$button.on('click', function() {
+ self.toggle();
+ });
+
+ self.isActive = true;
+
+ } else {
+ self.$button.hide();
+
+ self.isActive = false;
+ }
+
+ },
+
+ create : function() {
+ var instance = this.instance,
+ list,
+ src;
+
+ this.$grid = $('<div class="fancybox-thumbs"></div>').appendTo( instance.$refs.container );
+
+ list = '<ul>';
+
+ $.each(instance.group, function( i, item ) {
+
+ src = item.opts.thumb || ( item.opts.$thumb ? item.opts.$thumb.attr('src') : null );
+
+ if ( !src && item.type === 'image' ) {
+ src = item.src;
+ }
+
+ if ( src && src.length ) {
+ list += '<li data-index="' + i + '" tabindex="0" class="fancybox-thumbs-loading"><img data-src="' + src + '" /></li>';
+ }
+
+ });
+
+ list += '</ul>';
+
+ this.$list = $( list ).appendTo( this.$grid ).on('click', 'li', function() {
+ instance.jumpTo( $(this).data('index') );
+ });
+
+ this.$list.find('img').hide().one('load', function() {
+
+ var $parent = $(this).parent().removeClass('fancybox-thumbs-loading'),
+ thumbWidth = $parent.outerWidth(),
+ thumbHeight = $parent.outerHeight(),
+ width,
+ height,
+ widthRatio,
+ heightRatio;
+
+ width = this.naturalWidth || this.width;
+ height = this.naturalHeight || this.height;
+
+ //Calculate thumbnail width/height and center it
+
+ widthRatio = width / thumbWidth;
+ heightRatio = height / thumbHeight;
+
+ if (widthRatio >= 1 && heightRatio >= 1) {
+ if (widthRatio > heightRatio) {
+ width = width / heightRatio;
+ height = thumbHeight;
+
+ } else {
+ width = thumbWidth;
+ height = height / widthRatio;
+ }
+ }
+
+ $(this).css({
+ width : Math.floor(width),
+ height : Math.floor(height),
+ 'margin-top' : Math.min( 0, Math.floor(thumbHeight * 0.3 - height * 0.3 ) ),
+ 'margin-left' : Math.min( 0, Math.floor(thumbWidth * 0.5 - width * 0.5 ) )
+ }).show();
+
+ })
+ .each(function() {
+ this.src = $( this ).data( 'src' );
+ });
+
+ },
+
+ focus : function() {
+
+ if ( this.instance.current ) {
+ this.$list
+ .children()
+ .removeClass('fancybox-thumbs-active')
+ .filter('[data-index="' + this.instance.current.index + '"]')
+ .addClass('fancybox-thumbs-active')
+ .focus();
+ }
+
+ },
+
+ close : function() {
+ this.$grid.hide();
+ },
+
+ update : function() {
+
+ this.instance.$refs.container.toggleClass( 'fancybox-show-thumbs', this.isVisible );
+
+ if ( this.isVisible ) {
+
+ if ( !this.$grid ) {
+ this.create();
+ }
+
+ this.instance.trigger( 'onThumbsShow' );
+
+ this.focus();
+
+ } else if ( this.$grid ) {
+ this.instance.trigger( 'onThumbsHide' );
+ }
+
+ // Update content position
+ this.instance.update();
+
+ },
+
+ hide : function() {
+ this.isVisible = false;
+ this.update();
+ },
+
+ show : function() {
+ this.isVisible = true;
+ this.update();
+ },
+
+ toggle : function() {
+ this.isVisible = !this.isVisible;
+ this.update();
+ }
+
+ });
+
+ $(document).on({
+
+ 'onInit.fb' : function(e, instance) {
+ if ( instance && !instance.Thumbs ) {
+ instance.Thumbs = new FancyThumbs( instance );
+ }
+ },
+
+ 'beforeShow.fb' : function(e, instance, item, firstRun) {
+ var Thumbs = instance && instance.Thumbs;
+
+ if ( !Thumbs || !Thumbs.isActive ) {
+ return;
+ }
+
+ if ( item.modal ) {
+ Thumbs.$button.hide();
+
+ Thumbs.hide();
+
+ return;
+ }
+
+ if ( firstRun && instance.opts.thumbs.autoStart === true ) {
+ Thumbs.show();
+ }
+
+ if ( Thumbs.isVisible ) {
+ Thumbs.focus();
+ }
+ },
+
+ 'afterKeydown.fb' : function(e, instance, current, keypress, keycode) {
+ var Thumbs = instance && instance.Thumbs;
+
+ // "G"
+ if ( Thumbs && Thumbs.isActive && keycode === 71 ) {
+ keypress.preventDefault();
+
+ Thumbs.toggle();
+ }
+ },
+
+ 'beforeClose.fb' : function( e, instance ) {
+ var Thumbs = instance && instance.Thumbs;
+
+ if ( Thumbs && Thumbs.isVisible && instance.opts.thumbs.hideOnClose !== false ) {
+ Thumbs.close();
+ }
+ }
+
+ });
+
+}(document, window.jQuery));
public function modelAction($actionData = false)
{
- echo "ASF";
+
+ wp_enqueue_style('fancyStyle', GLM_MEMBERS_FOR_SALE_PLUGIN_URL . '/fancybox/dist/jquery.fancybox.min.css');
+ wp_enqueue_script('fancyScript', GLM_MEMBERS_FOR_SALE_PLUGIN_URL . '/fancybox/dist/jquery.fancybox.min.js', array('jquery'), '', true );
+
$success_message = "";
$option = false;
if (isset($_REQUEST['option']) && trim($_REQUEST['option']) != '') {
}
.item-image{
display: block;
+ max-width: 200px;
}
.item-image-row{
border-bottom: 1px solid lightgray;
}
div{
line-height: 1.1;
- padding: 5px;
+ padding: 3px 0 3px 0;
}
.front-list-topic{
padding: 5px;
text-align: center;
color: white;
border-radius: 5px;
- margin-bottom: 10px;
+ margin: 0 auto 10px auto;
}
.item-wanted{
background: green;
.item-sale{
background: red;
}
+ .item-detail-link{
+ display: inline-block;
+ padding: 5px;
+ background: blue;
+ color: white;
+ text-decoration: none;
+ margin-top: 5px;
+ }
+}
+.front-item-detail-wrapper{
+ .item-detail-images{
+ padding-top: 20px;
+ }
}
\ No newline at end of file
+<div class="glm-row front-item-detail-wrapper">
+ <div class="glm-small-12 glm-columns">
+ {$itemData.title}
+ </div>
+ <div class="glm-small-12 glm-columns">
+ {$itemData.company}
+ </div>
+ <div class="glm-small-12 glm-columns">
+ {$itemData.descr}
+ </div>
+ <div class="glm-small-12 glm-columns">
+ {$itemData.terms}
+ </div>
+ <div class="glm-small-12 glm-columns">
+ {$itemData.contact_name}
+ </div>
+ <div class="glm-small-12 glm-columns">
+ {$itemData.contact_email}
+ </div>
+ <div class="glm-small-12 glm-columns">
+ {$itemData.contact_phone}
+ </div>
+ <div class="glm-row item-detail-images">
+ <div class="glm-small-12 glm-medium-4 glm-columns image-1-detail">
+ <a class="item-detail-image" data-fancybox data-src="{$glmPluginMediaUrl}/images/large/{$itemData.image_1}">
+ <img src="{$glmPluginMediaUrl}/images/small/{$itemData.image_1}" alt="">
+ </a>
+ </div>
+ <div class="glm-small-12 glm-medium-4 glm-columns image-2-detail">
+ <a class="item-detail-image" data-fancybox data-src="{$glmPluginMediaUrl}/images/large/{$itemData.image_2}">
+ <img src="{$glmPluginMediaUrl}/images/small/{$itemData.image_2}" alt="">
+ </a>
+ </div>
+ <div class="glm-small-12 glm-medium-4 glm-columns image-3-detail">
+ <a class="item-detail-image" data-fancybox data-src="{$glmPluginMediaUrl}/images/large/{$itemData.image_3}">
+ <img src="{$glmPluginMediaUrl}/images/small/{$itemData.image_3}" alt="">
+ </a>
+ </div>
+ </div>
+</div>
+<script>
+ jQuery(function($){
+ $('.item-detail-image').fancybox({
+ fitToView: true
+ });
+ });
+</script>
<div class="glm-small-12 glm-columns front-item-email no-padding">
<a href="mailto:{$data.contact_email}">{$data.contact_email}</a>
</div>
+ <a class="item-detail-link" href="{$siteBaseUrl}for-sale-detail/?item={$data.id}">Item Details</a>
</div>
<div class="glm-small-12 glm-medium-3 glm-columns">
{if $data.topic.value == 1}
{if $data.image_1}
<img src="{$glmPluginMediaUrl}/images/small/{$data.image_1}" alt="">
{/if}
- <a href="{$siteBaseUrl}for-sale-detail/?item={$data.id}">Item Details</a>
+
</div>
</div>
{/foreach}