FooGallery – Image Gallery WordPress Plugin - Version 2.0.24

Version Description

  • Date Updated : 2021-18-04
  • Update : FooGallery client side 2.0.11
  • Fix : Fixed compatibility with WPRocket and rendering inline script of gallery items json
Download this release

Release Info

Developer bradvin
Plugin Icon 128x128 FooGallery – Image Gallery WordPress Plugin
Version 2.0.24
Comparing to
See all releases

Code changes from version 1.9.53 to 2.0.24

Files changed (31) hide show
  1. README.txt +71 -3
  2. assets/1x1.gif +0 -0
  3. assets/extension_bg.png +0 -0
  4. css/admin-foogallery.css +40 -6
  5. css/admin-page-foogallery-extensions.css +3 -30
  6. css/admin-page-foogallery-help.css +505 -0
  7. css/foogallery.admin.min.css +1 -1
  8. extensions/albums/class-albums-extension.php +8 -15
  9. extensions/default-templates/class-default-templates.php +1 -0
  10. extensions/default-templates/default/class-default-gallery-template.php +20 -12
  11. extensions/default-templates/default/gallery-default.php +2 -1
  12. extensions/default-templates/functions.php +12 -2
  13. extensions/default-templates/image-viewer/class-image-viewer-gallery-template.php +4 -14
  14. extensions/default-templates/justified/class-justified-gallery-template.php +131 -90
  15. extensions/default-templates/masonry/class-masonry-gallery-template.php +88 -10
  16. extensions/default-templates/masonry/gallery-masonry.php +4 -0
  17. extensions/default-templates/shared/css/admin-foogallery.css +0 -33
  18. extensions/default-templates/shared/css/foogallery.css +763 -254
  19. extensions/default-templates/shared/css/foogallery.min.css +1 -1
  20. extensions/default-templates/shared/js/foogallery.js +4891 -5640
  21. extensions/default-templates/shared/js/foogallery.min.js +5 -5
  22. extensions/default-templates/simple-portfolio/class-simple-portfolio-gallery-template.php +47 -44
  23. extensions/default-templates/thumbnail/class-thumbnail-gallery-template.php +59 -26
  24. extensions/default-templates/thumbnail/gallery-thumbnail.php +3 -20
  25. extensions/extensions.json.js +0 -118
  26. extensions/nextgen-importer/class-nextgen-gallery-importer-extension.php +0 -25
  27. foogallery.php +5 -4
  28. freemius/LICENSE.txt +1 -1
  29. freemius/assets/css/admin/account.css +1 -1
  30. freemius/assets/css/admin/common.css +2 -2
  31. freemius/assets/css/admin/connect.css +1 -1
README.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: bradvin, steveush, fooplugins
3
  Donate link: https://fooplugins.com
4
  Tags: gallery, image gallery, photo gallery, responsive gallery, wordpress gallery plugin, best gallery plugin, albums, media gallery, video gallery, lightbox
5
  Requires at least: 3.9
6
- Tested up to: 5.6
7
- Stable tag: trunk
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -16,7 +16,7 @@ FooGallery is a powerful, responsive photo gallery plugin. Stunning gallery layo
16
 
17
  Make gallery management in WordPress great again! With FooGallery you can easily add a stunning photo gallery to your website in minutes.
18
 
19
- FooGallery is an easy-to-use image gallery plugin, with stunning gallery layouts. It is also responsive, retina-ready and supports lazy loading for lightning fast photo galleries.
20
 
21
  Live previews are available while creating an image gallery, and also within the Gutenberg block editor with our FooGallery Block.
22
 
@@ -26,6 +26,17 @@ That is why we think FooGallery is the best gallery plugin. After using it, we h
26
 
27
  [Visit the FooGallery Wordpress Gallery Plugin Homepage](https://fooplugins.com/foogallery/)
28
 
 
 
 
 
 
 
 
 
 
 
 
29
  = WordPress Gallery Plugin Features =
30
 
31
  The following free features make FooGallery the **best gallery plugin** on the market!
@@ -94,6 +105,12 @@ The following free features make FooGallery the **best gallery plugin** on the m
94
 
95
  [See More Demos](https://fooplugins.com/foogallery/demos/)
96
 
 
 
 
 
 
 
97
  **Documentation**
98
 
99
  * [FooGallery Documentation](https://fooplugins.com/documentation/foogallery/)
@@ -227,6 +244,57 @@ Please update in order to for FooGallery to work in WP 5.5+!
227
 
228
  == Changelog ==
229
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  = 1.9.53 =
231
  * Date Updated : 2021-23-01
232
  * Update : FooGallery client side 1.4.26
3
  Donate link: https://fooplugins.com
4
  Tags: gallery, image gallery, photo gallery, responsive gallery, wordpress gallery plugin, best gallery plugin, albums, media gallery, video gallery, lightbox
5
  Requires at least: 3.9
6
+ Tested up to: 5.7
7
+ Stable tag: 2.0.24
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
16
 
17
  Make gallery management in WordPress great again! With FooGallery you can easily add a stunning photo gallery to your website in minutes.
18
 
19
+ FooGallery is an easy-to-use image gallery plugin, with stunning gallery layouts and a focus on speed. It is also responsive, retina-ready and supports lazy loading for lightning fast photo galleries.
20
 
21
  Live previews are available while creating an image gallery, and also within the Gutenberg block editor with our FooGallery Block.
22
 
26
 
27
  [Visit the FooGallery Wordpress Gallery Plugin Homepage](https://fooplugins.com/foogallery/)
28
 
29
+ = Major Updates for Google's Core Web Vitals =
30
+
31
+ A faster gallery now means a more favourable ranking in Google!
32
+ FooGallery has been specifically optimized to score better for Google's Core Web Vitals update in May 2021.
33
+ We have focused on the speed of our javascript code, and also improved the visual stability of all gallery layouts.
34
+ This has led to dramatically better scores for the 3 key factors including:
35
+
36
+ * Largest Contentful Paint - galleries load and appear quicker for your visitors
37
+ * First Input Delay - you can interact with the gallery sooner
38
+ * Cumulative Layout Shift - gallery images shift around a lot less than before!
39
+
40
  = WordPress Gallery Plugin Features =
41
 
42
  The following free features make FooGallery the **best gallery plugin** on the market!
105
 
106
  [See More Demos](https://fooplugins.com/foogallery/demos/)
107
 
108
+ **Test Drive**
109
+
110
+ Take FooGallery for a test drive! Spin up your very own WP instance with FooGallery pre-installed:
111
+
112
+ [Start FooGallery Test Drive!](https://tastewp.com/new/?pre-installed-plugin-slug=foogallery)
113
+
114
  **Documentation**
115
 
116
  * [FooGallery Documentation](https://fooplugins.com/documentation/foogallery/)
244
 
245
  == Changelog ==
246
 
247
+ = 2.0.24 =
248
+ * Date Updated : 2021-18-04
249
+ * Update : FooGallery client side 2.0.11
250
+ * Fix : Fixed compatibility with WPRocket and rendering inline script of gallery items json
251
+
252
+
253
+ = 2.0.20 =
254
+ * Date Updated : 2021-11-04
255
+ * New : Major performance improvements for all gallery templates (improving scores for Core Web Vitals)
256
+ * New : Added "Mobile Columns" gallery setting for Responsive Galleries
257
+ * New : Added 6 Columns option for Masonry gallery layout
258
+ * New : Added "Horizontal Layout" gallery setting for Masonry galleries, to try maintain left-to-right order of images
259
+ * New : Made all image loaded effects in PRO now available in free!!
260
+ * New : Added first-class support for ShortPixel Adaptive Images as a thumbnail engine. (can be changed from settings)
261
+ * New : Added "Alignment" gallery setting under "Captions" tab for changing horizontal alignment of thumbnail captions
262
+ * New : Added "Image Title Attribute" gallery setting under "Advanced" tab for disabling the title attribute added to thumbnail img tags
263
+ * New : Added gallery settings to change the lightbox captions when FooBox is the selected lightbox
264
+ * New : Added ability to refresh gallery preview when editing by clicking preview button again
265
+ * New : Added lazyload support to stack album, giving a major performance boost to very large albums!
266
+ * New : Overhauled Help page when plugin is activated, including the ability create demo gallery content and view inline demos
267
+ * New : Added ability to override captions for FooBox
268
+ * Update : FooGallery client side 2.0.9
269
+ * Update : Simplified extensions admin page and removed all build-your-own logic
270
+ * Update : Updated the Justified gallery template. Removed "Max Row Height" and "Last Row" settings.
271
+ * Update : Updated the Thumbnail gallery template. Removed "Thumbnail Crop" setting.
272
+ * Fix : Updated styling for FooGallery Block to look correct in latest version of Gutenberg
273
+ * Fix : JSON objects get built using all attributes needed
274
+ * Fix : Could not add images to the gallery for some installs, due to no thumbnail sizes being returned. Made the logic more resilient.
275
+ * Fix : Compatible with WP Rocket Lazy loading
276
+ * Fix : Javascript error with Masonry related to script dependencies when using script minifiers
277
+
278
+
279
+ = 1.10.4 =
280
+ * Date Updated : 2021-02-03
281
+ * Fix : fix for fatal error running pre WP5 : Fatal error: Uncaught ArgumentCountError: Too few arguments to function FooGallery_Thumb_Engine_Default::delete_cache_folder_for_attachment()
282
+
283
+ = 1.10.3 =
284
+ * Date Updated : 2021-20-02
285
+ * Fix : fixed a fatal PHP error on some installs
286
+
287
+ = 1.10.1 =
288
+ * Date Updated : 2021-18-02
289
+ * Fix : fixed a fatal PHP error with PHP 5.6
290
+
291
+ = 1.10.0 =
292
+ * Date Updated : 2021-18-02
293
+ * Update : Removed WPThumb library completely
294
+ * Update : Updated to Freemius SDK 2.4.2
295
+ * Fix : updated FooGallery block category to 'media'
296
+
297
+
298
  = 1.9.53 =
299
  * Date Updated : 2021-23-01
300
  * Update : FooGallery client side 1.4.26
assets/1x1.gif DELETED
Binary file
assets/extension_bg.png DELETED
Binary file
css/admin-foogallery.css CHANGED
@@ -443,20 +443,25 @@ button[data-balloon]{overflow:visible}[data-balloon]{position:relative}[data-bal
443
  margin-left: 10px;
444
  }
445
 
 
 
 
 
446
  .foogallery-items-view-switch {
447
  vertical-align: middle;
448
  display: inline-block;
449
  }
450
 
451
  .foogallery-items-view-switch a {
 
452
  padding: 4px 10px;
453
  line-height: 12px;
454
- border: 1px solid #ccc;
455
  float: left;
456
  display: inline-block;
457
  text-decoration: none;
458
- margin-right: 10px;
459
- border-radius: 4px;
460
  text-align: center;
461
  white-space: nowrap;
462
  vertical-align: middle;
@@ -467,18 +472,32 @@ button[data-balloon]{overflow:visible}[data-balloon]{position:relative}[data-bal
467
  -moz-user-select: none;
468
  -ms-user-select: none;
469
  user-select: none;
470
- background: #f7f7f7;
471
- color: #555;
 
 
 
 
 
 
 
 
 
 
 
 
472
  }
473
 
474
  .foogallery-items-view-switch a:first-child:not(:last-child) {
475
  border-top-right-radius: 0;
476
  border-bottom-right-radius: 0;
 
477
  }
478
 
479
  .foogallery-items-view-switch a:last-child:not(:first-child) {
480
  border-top-left-radius: 0;
481
  border-bottom-left-radius: 0;
 
482
  }
483
 
484
  .foogallery-items-view-switch a:first-child {
@@ -486,7 +505,14 @@ button[data-balloon]{overflow:visible}[data-balloon]{position:relative}[data-bal
486
  }
487
 
488
  .foogallery-items-view-switch a.current {
489
- background: #0085ba;
 
 
 
 
 
 
 
490
  color: #fff;
491
  }
492
 
@@ -507,6 +533,9 @@ button[data-balloon]{overflow:visible}[data-balloon]{position:relative}[data-bal
507
  padding:20px;
508
  text-align: center
509
  }
 
 
 
510
 
511
  .foogallery-items-view .button-hero .dashicons {
512
  vertical-align: middle;
@@ -619,4 +648,9 @@ button[data-balloon]{overflow:visible}[data-balloon]{position:relative}[data-bal
619
 
620
  .foogallery-custom-metabox-header .foogallery-template-selector {
621
  margin-left: 10px;
 
 
 
 
 
622
  }
443
  margin-left: 10px;
444
  }
445
 
446
+ .foogallery-items-view-switch-container .spinner {
447
+ margin: 2px 10px 0;
448
+ }
449
+
450
  .foogallery-items-view-switch {
451
  vertical-align: middle;
452
  display: inline-block;
453
  }
454
 
455
  .foogallery-items-view-switch a {
456
+ font-size: 11px;
457
  padding: 4px 10px;
458
  line-height: 12px;
459
+ border: 1px solid #2271b1;
460
  float: left;
461
  display: inline-block;
462
  text-decoration: none;
463
+ margin: 0;
464
+ border-radius: 3px;
465
  text-align: center;
466
  white-space: nowrap;
467
  vertical-align: middle;
472
  -moz-user-select: none;
473
  -ms-user-select: none;
474
  user-select: none;
475
+ /*background: #f7f7f7;*/
476
+ /*color: #555;*/
477
+
478
+ color: #2271b1;
479
+ background: #f6f7f7;
480
+ }
481
+ .foogallery-items-view-switch a:hover {
482
+ background: #f0f0f1;
483
+ border-color: #0a4b78;
484
+ color: #0a4b78;
485
+ }
486
+ .foogallery-items-view-switch a:focus {
487
+ box-shadow: none;
488
+ outline: none;
489
  }
490
 
491
  .foogallery-items-view-switch a:first-child:not(:last-child) {
492
  border-top-right-radius: 0;
493
  border-bottom-right-radius: 0;
494
+ border-right: none;
495
  }
496
 
497
  .foogallery-items-view-switch a:last-child:not(:first-child) {
498
  border-top-left-radius: 0;
499
  border-bottom-left-radius: 0;
500
+ border-left: none;
501
  }
502
 
503
  .foogallery-items-view-switch a:first-child {
505
  }
506
 
507
  .foogallery-items-view-switch a.current {
508
+ background: #2271b1;
509
+ border-color: #2271b1;
510
+ color: #fff;
511
+ }
512
+
513
+ .foogallery-items-view-switch a.current:hover {
514
+ background: #135e96;
515
+ border-color: #135e96;
516
  color: #fff;
517
  }
518
 
533
  padding:20px;
534
  text-align: center
535
  }
536
+ .foogallery-items-view-preview {
537
+ overflow: hidden;
538
+ }
539
 
540
  .foogallery-items-view .button-hero .dashicons {
541
  vertical-align: middle;
648
 
649
  .foogallery-custom-metabox-header .foogallery-template-selector {
650
  margin-left: 10px;
651
+ }
652
+
653
+ .foogallery-custom-metabox-header .foogallery-template-selector select {
654
+ font-size: 13px;
655
+ margin-left: 6px;
656
  }
css/admin-page-foogallery-extensions.css CHANGED
@@ -1,8 +1,3 @@
1
- .extensions-wrap {
2
- margin-left: 0;
3
- width: 98%;
4
- max-width: 98%;
5
- }
6
 
7
  .foogallery-extension-browser .extension-controls {
8
  margin-bottom: 10px;
@@ -12,36 +7,14 @@
12
  margin:0;
13
  }
14
 
15
- .extension-search-box {
16
- display: inline-block;
17
- margin-left: 20px;
18
- float: left;
19
- }
20
-
21
- .extension-search-box #extensions-search-input {
22
- position: relative;
23
- top: -4px;
24
- margin: 0;
25
- width: 280px;
26
- font-size: 16px;
27
- font-weight: 300;
28
- line-height: 1.4em;
29
- }
30
-
31
  .extension-reload {
32
- float: left;
33
  display: inline-block;
34
- margin-left: 20px;
35
- vertical-align: middle;
36
- }
37
-
38
- .extension-reload .button {
39
  vertical-align: middle;
40
  }
41
 
42
- .extension-reload span.dashicons {
43
- vertical-align: middle;
44
- font-size: 18px;
45
  }
46
 
47
  .extension-reload .button.disabled span.dashicons {
 
 
 
 
 
1
 
2
  .foogallery-extension-browser .extension-controls {
3
  margin-bottom: 10px;
7
  margin:0;
8
  }
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  .extension-reload {
 
11
  display: inline-block;
 
 
 
 
 
12
  vertical-align: middle;
13
  }
14
 
15
+ .extension-reload .button {
16
+ padding: 3px 5px 0 5px;
17
+ line-height: 0;
18
  }
19
 
20
  .extension-reload .button.disabled span.dashicons {
css/admin-page-foogallery-help.css CHANGED
@@ -1,3 +1,508 @@
1
  .foogallery_page_foogallery-help .fs-notice {
2
  margin-right: 200px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  }
1
  .foogallery_page_foogallery-help .fs-notice {
2
  margin-right: 200px !important;
3
+ }
4
+
5
+
6
+ body {
7
+ background-color: #646970;/*#484c50;*/
8
+ }
9
+ #wpcontent {
10
+ padding-right: 20px;
11
+ box-sizing: border-box;
12
+ }
13
+ @media screen and (max-width: 782px){
14
+ .auto-fold #wpcontent {
15
+ padding-right: 10px;
16
+ }
17
+ }
18
+
19
+ .foogallery-admin-help,
20
+ .foogallery-admin-help * {
21
+ box-sizing: border-box;
22
+ }
23
+
24
+ .foogallery-admin-help {
25
+ max-width: 1000px;
26
+ margin: 24px auto;
27
+ clear: both;
28
+ background-color: #1d2327;/*#23282d;*/
29
+ border-radius: 20px;
30
+ color: #ffffff;
31
+ font-size: 14px;
32
+ line-height: 1.4;
33
+ }
34
+
35
+ .foogallery-admin-help img {
36
+ display: block;
37
+ max-width: 100%;
38
+ height: auto;
39
+ box-sizing: border-box;
40
+ margin: 0 auto;
41
+ }
42
+ .foogallery-admin-help p {
43
+ margin: 0.8em 0;
44
+ font-size: 14px;
45
+ line-height: 1.4;
46
+ }
47
+ .foogallery-admin-help h2,
48
+ .foogallery-admin-help h3,
49
+ .foogallery-admin-help h4 {
50
+ color: inherit;
51
+ }
52
+
53
+ .foogallery-admin-help a {
54
+ color: #3582c4;
55
+ text-decoration: none;
56
+ }
57
+ .foogallery-admin-help a:focus {
58
+ box-shadow: none;
59
+ }
60
+ .foogallery-admin-help a:hover {
61
+ color: #4f94d4;
62
+ }
63
+
64
+ .foogallery-admin-help-header {
65
+ margin: 0;
66
+ color: #FFFFFF;
67
+ position: relative;
68
+ text-align: center;
69
+ padding: 20px;
70
+ }
71
+ .foogallery-admin-help-header > img {
72
+ margin: 3em auto;
73
+ }
74
+
75
+ .foogallery-admin-help-tagline {
76
+ margin: 0;
77
+ padding: 10px;
78
+ font-size: 1.5em;
79
+ }
80
+
81
+ .foogallery-admin-help-ribbon {
82
+ position: absolute;
83
+ right: -5px;
84
+ top: -5px;
85
+ z-index: 1;
86
+ overflow: hidden;
87
+ width: 75px;
88
+ height: 75px;
89
+ text-align: right;
90
+ }
91
+ .foogallery-admin-help-ribbon span {
92
+ font-size: 10px;
93
+ font-weight: 600;
94
+ color: #2b2400;
95
+ text-transform: uppercase;
96
+ text-align: center;
97
+ line-height: 20px;
98
+ transform: rotate(45deg);
99
+ width: 100px;
100
+ display: block;
101
+ background: #d67935;
102
+ box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1);
103
+ position: absolute;
104
+ top: 19px; right: -21px;
105
+ }
106
+ .foogallery-admin-help-ribbon span::before {
107
+ content: "";
108
+ position: absolute;
109
+ left: 0;
110
+ top: 100%;
111
+ z-index: -1;
112
+ border-left: 3px solid #d67935;
113
+ border-right: 3px solid transparent;
114
+ border-bottom: 3px solid transparent;
115
+ border-top: 3px solid #d67935;
116
+ }
117
+ .foogallery-admin-help-ribbon span::after {
118
+ content: "";
119
+ position: absolute;
120
+ right: 0;
121
+ top: 100%;
122
+ z-index: -1;
123
+ border-left: 3px solid transparent;
124
+ border-right: 3px solid #d67935;
125
+ border-bottom: 3px solid transparent;
126
+ border-top: 3px solid #d67935;
127
+ }
128
+
129
+ .foogallery-admin-help nav {
130
+ background: #101517;/*#1d2327*/;
131
+ clear: both;
132
+ padding-top: 0;
133
+ color: #9ca2a7;
134
+ display: flex;
135
+ width: 100%;
136
+ max-width: 100%;
137
+ justify-content: stretch;
138
+ align-items: stretch;
139
+ flex-wrap: nowrap;
140
+ }
141
+
142
+ .foogallery-admin-help nav a {
143
+ display: block;
144
+ flex-grow: 1;
145
+ margin-left: 0;
146
+ padding: 24px 32px 18px 32px;
147
+ font-size: 1.3em;
148
+ line-height: 1.4;
149
+ border-width: 0 0 6px;
150
+ border-style: solid;
151
+ border-color: transparent;
152
+ background: transparent;
153
+ color: inherit;
154
+ text-decoration: none;
155
+ font-weight: 600;
156
+ box-shadow: none;
157
+ text-align: center;
158
+ }
159
+
160
+ .foogallery-admin-help nav a.foogallery-admin-help-tab-active {
161
+ background-color: #2271b1;
162
+ color: #ffffff;
163
+ border-color: #ffffff;
164
+ }
165
+
166
+ .fgah-feature {
167
+ display: block;
168
+ position: relative;
169
+ max-width: 100%;
170
+ margin: 0;
171
+ padding: 16px;
172
+ font-size: 14px;
173
+ }
174
+ .fgah-feature:nth-child(odd) {
175
+ background-color: #2c3338;
176
+ }
177
+
178
+ .fgah-feature > * {
179
+ margin: 16px;
180
+ }
181
+ .fgah-feature > header + * {
182
+ margin-top: 32px;
183
+ }
184
+ .fgah-feature > * + footer {
185
+ margin-top: 32px;
186
+ }
187
+
188
+ .fgah-feature > header {
189
+ text-align: left;
190
+ }
191
+
192
+ .fgah-feature > header > h3 {
193
+ font-size: 1.5em;
194
+ margin: 0;
195
+ padding: 0;
196
+ font-weight: 600;
197
+ }
198
+ .fgah-feature > header > h3 + p {
199
+ margin-top: 24px;
200
+ }
201
+
202
+ .fgah-feature > footer {
203
+ text-align: center;
204
+ padding: 0;
205
+ }
206
+
207
+ .fgah-feature > footer > small {
208
+ display: block;
209
+ margin: 16px 0;
210
+ color: #c3c4c7;
211
+ }
212
+
213
+ .fgah-feature > footer > *:last-child {
214
+ margin-bottom: 0;
215
+ }
216
+
217
+ .fgah-feature > div {
218
+ display: flex;
219
+ flex-direction: row;
220
+ justify-content: center;
221
+ align-items: flex-start;
222
+ max-width: 100%;
223
+ }
224
+ .fgah-feature-right > div {
225
+ flex-direction: row-reverse;
226
+ }
227
+ .fgah-feature > div > * {
228
+ padding: 0;
229
+ margin: 0;
230
+ width: 33.33%;
231
+ }
232
+ .fgah-feature > div > figure {
233
+ width: 66.66%;
234
+ text-align: center;
235
+ padding-right: 32px;
236
+ }
237
+ .fgah-feature-right > div > figure {
238
+ padding-right: 0;
239
+ padding-left: 32px;
240
+ }
241
+
242
+ .fgah-feature > div > ol {
243
+
244
+ }
245
+ .fgah-feature > div > ol > li {
246
+ list-style-type: decimal;
247
+ margin: 0 2em;
248
+ padding: 0;
249
+ }
250
+
251
+ .fgah-feature > div > dl {
252
+
253
+ }
254
+ .fgah-feature > div > dl > dt {
255
+ font-size: large;
256
+ margin: 0 0 16px 0;
257
+ font-weight: 600;
258
+ }
259
+ .fgah-feature > div > dl > dt > code {
260
+ background-color: transparent;
261
+ font-size: inherit;
262
+ padding: 0;
263
+ margin: 0;
264
+ }
265
+ .fgah-feature > div > dl > dd {
266
+ font-size: inherit;
267
+ margin: 16px 0;
268
+ }
269
+ .fgah-feature > div > dl > dd + dt {
270
+ margin: 32px 0 16px 0;
271
+ }
272
+
273
+ .fgah-feature-pro > div > dl > dt {
274
+
275
+ }
276
+
277
+ .fgah-feature-pro > div > dl > dt::before {
278
+ content: "\2713";
279
+ display: inline-block;
280
+ background-color: #008a20;
281
+ color: #FFFFFF;
282
+ border-radius: 50%;
283
+ line-height: 1;
284
+ width: 1em;
285
+ height: 1em;
286
+ padding: 0.14em;
287
+ text-align: center;
288
+ margin-right: 0.4em;
289
+ transform: rotate(9deg);
290
+ border: solid 2px #FFFFFF;
291
+ }
292
+
293
+ .fgah-help-list {
294
+ list-style-type: none;
295
+ }
296
+ .fgah-help-list li {
297
+ list-style-type: none;
298
+ margin: 0 0 16px 0;
299
+ padding: 0;
300
+ }
301
+ .fgah-help-list li:last-child {
302
+ margin-bottom: 0;
303
+ }
304
+ .fgah-help-list li::before {
305
+ content: "\003F";
306
+ display: inline-block;
307
+ background-color: #2271b1;
308
+ color: #FFFFFF;
309
+ border-radius: 50%;
310
+ line-height: 1;
311
+ width: 1em;
312
+ height: 1em;
313
+ padding: 0.14em;
314
+ text-align: center;
315
+ margin-right: 0.4em;
316
+ border: solid 2px #FFFFFF;
317
+ float: left;
318
+ }
319
+
320
+ .fgah-demo {
321
+ display: block;
322
+ position: relative;
323
+ max-width: 100%;
324
+ margin: 0;
325
+ padding: 16px;
326
+ font-size: 14px;
327
+ background-color: #2c3338;
328
+ }
329
+ .fgah-demo > header {
330
+ text-align: left;
331
+ margin: 16px;
332
+ }
333
+ .fgah-demo > header + * {
334
+ margin-top: 32px;
335
+ }
336
+ .fgah-demo > header > h3 {
337
+ font-size: 1.5em;
338
+ margin: 0;
339
+ padding: 0;
340
+ font-weight: 600;
341
+ }
342
+ .fgah-demo > header > h3 + p {
343
+ margin-top: 24px;
344
+ }
345
+ .fgah-demo > div.foogallery {
346
+ margin-bottom: 15px;
347
+ }
348
+
349
+ .foogallery-admin-help-button {
350
+ position: relative;
351
+ background-color: #007017;
352
+ color: #ffffff !important;
353
+ padding: 10px 20px;
354
+ font-size: 1em;
355
+ border-radius: 3px;
356
+ text-decoration: none;
357
+ font-weight: 400;
358
+ display: inline-block;
359
+ text-align: center;
360
+ line-height: 1.2;
361
+ border: none;
362
+ box-shadow: none;
363
+ outline: none;
364
+ cursor: pointer;
365
+ transition: background-color .1s ease-in-out;
366
+ }
367
+
368
+ .foogallery-admin-help-button-active {
369
+ background-color: #2271b1;
370
+ }
371
+
372
+ .foogallery-admin-help-button-cta {
373
+ position: relative;
374
+ background-color: #007017;
375
+ color: #ffffff !important;
376
+ padding: 12px 36px;
377
+ font-size: 1.3em;
378
+ border-radius: 3px;
379
+ text-decoration: none;
380
+ font-weight: 600;
381
+ display: inline-block;
382
+ min-width: 250px;
383
+ text-align: center;
384
+ line-height: 1.4;
385
+ border: none;
386
+ box-shadow: none;
387
+ outline: none;
388
+ cursor: pointer;
389
+ transition: background-color .1s ease-in-out;
390
+ }
391
+
392
+ .foogallery-admin-help-button-cta:hover,
393
+ .foogallery-admin-help-button-cta:focus {
394
+ background-color: #008a20;
395
+ }
396
+
397
+ .foogallery-admin-help-button-cta.foogallery-admin-help-loading {
398
+ position: relative;
399
+ cursor: wait;
400
+ }
401
+
402
+ .foogallery-admin-help-button-cta .progress {
403
+ border-radius: 3px;
404
+ width: 0;
405
+ background: #2271b1;
406
+ opacity: 0;
407
+ transition: all 0.3s ease;
408
+ position: absolute;
409
+ left: 0;
410
+ top: 0;
411
+ right: 0;
412
+ bottom: 0;
413
+ }
414
+ .foogallery-admin-help-button-cta.foogallery-admin-help-loading .progress {
415
+ opacity: 1;
416
+ animation: progress-anim 5s ease 0s;
417
+ animation-fill-mode: both;
418
+ }
419
+
420
+ @keyframes progress-anim {
421
+ 0% {
422
+ width: 0%;
423
+ }
424
+ 5% {
425
+ width: 0%;
426
+ }
427
+ 10% {
428
+ width: 15%;
429
+ }
430
+ 30% {
431
+ width: 40%;
432
+ }
433
+ 50% {
434
+ width: 55%;
435
+ }
436
+ 80% {
437
+ width: 70%;
438
+ }
439
+ 90% {
440
+ width: 80%;
441
+ }
442
+ 100% {
443
+ width: 95%;
444
+ }
445
+ }
446
+
447
+ .foogallery-admin-help-footer {
448
+ margin: 0;
449
+ color: #ffffff;
450
+ text-align: center;
451
+ padding: 20px;
452
+ font-size: 1.3em;
453
+ }
454
+
455
+ .foogallery-admin-help-column .foogallery-admin-help-button-cta {
456
+ min-width: auto;
457
+ padding: 12px 24px;
458
+ }
459
+
460
+
461
+ @media screen and (max-width: 782px){
462
+ .foogallery-admin-help nav {
463
+ flex-wrap: wrap;
464
+ }
465
+ .foogallery-admin-help nav a {
466
+ padding: 24px 24px 18px 24px;
467
+ width: 50%;
468
+ }
469
+ }
470
+
471
+ @media screen and (max-width: 600px){
472
+ .fgah-feature > div,
473
+ .fgah-feature-right > div {
474
+ flex-direction: column;
475
+ }
476
+ .fgah-feature > div > *,
477
+ .fgah-feature > div > figure {
478
+ width: 100%;
479
+ }
480
+ .fgah-feature > div > figure + * {
481
+ margin-top: 32px;
482
+ }
483
+ .fgah-feature > div > figure,
484
+ .fgah-feature-right > div > figure {
485
+ padding-right: 0;
486
+ padding-left: 0;
487
+ }
488
+ }
489
+
490
+ @media screen and (max-width: 400px){
491
+ .foogallery-admin-help-button-cta {
492
+ min-width: 150px;
493
+ }
494
+ }
495
+
496
+
497
+ @media (hover: hover){
498
+
499
+ .foogallery-admin-help a:hover {
500
+ color: #0097de;
501
+ }
502
+ .foogallery-admin-help nav a:hover {
503
+ background-color: #2271b1;
504
+ color: #ffffff;
505
+ border-width: 0;
506
+ }
507
+
508
  }
css/foogallery.admin.min.css CHANGED
@@ -1 +1 @@
1
- .foogallery-settings *{box-sizing:border-box}.foogallery-settings{position:relative;display:flex;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:13px}.foogallery-settings:after{display:table;content:"";clear:both}.foogallery-vertical-tabs{display:inline-block;position:relative;width:150px;background-color:#f5f5f5;border-right:solid 1px #ccd0d4}.foogallery-vertical-tab{position:relative;font-size:14px;margin:0;padding:7px 0;display:block;box-shadow:none;text-decoration:none;line-height:18px;color:#0073aa;cursor:pointer}.foogallery-settings.can-hover .foogallery-vertical-tab:not(.foogallery-tab-active):hover{color:#00a0d2}.foogallery-settings .foogallery-vertical-tab.foogallery-tab-active{color:#fff;background-color:#0073aa}.foogallery-vertical-tab:after{right:-1px;border:solid 8px transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none;border-right-color:#fff;top:17px;margin-top:-8px;visibility:hidden;opacity:0}.foogallery-settings.is-mobile .foogallery-vertical-tab.foogallery-tab-active:not(.foogallery-show-child-menu):after,.foogallery-settings:not(.is-mobile) .foogallery-vertical-tab.foogallery-tab-active:after{visibility:visible;opacity:1}.foogallery-vertical-tab .dashicons{font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;font-size:16px;width:16px;height:16px;vertical-align:middle;margin:0 3px 3px 8px}.foogallery-vertical-child-tabs{display:none;margin:7px 0 -7px;color:#555;background-color:#ddd;border-top:1px solid #eee;width:150px;text-align:left}.foogallery-settings:not(.is-mobile) .foogallery-tab-active .foogallery-vertical-child-tabs{display:block}.foogallery-settings.can-hover:not(.is-mobile) .foogallery-vertical-tab.foogallery-show-child-menu:not(.foogallery-tab-active) .foogallery-vertical-child-tabs,.foogallery-settings.is-mobile .foogallery-vertical-tab.foogallery-show-child-menu .foogallery-vertical-child-tabs{display:block;position:absolute;top:-8px;right:0;transform:translateX(100%);z-index:11}.foogallery-vertical-child-tabs:after{left:-16px;border:solid 8px transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none;border-right-color:#ddd;top:17px;margin-top:-8px;visibility:hidden;opacity:0}.foogallery-settings:not(.is-mobile) .foogallery-vertical-tab:not(.foogallery-tab-active):hover .foogallery-vertical-child-tabs:after{visibility:visible;opacity:1}.foogallery-vertical-child-header{position:relative;padding:8px 12px;font-size:14px;font-weight:600;display:none}.foogallery-vertical-child-tab{position:relative;padding:4px 12px;font-size:13px;font-weight:400}.foogallery-vertical-child-tab:first-child{padding:8px 12px 4px}.foogallery-vertical-child-tab:last-child{padding:4px 12px 8px}.foogallery-vertical-child-tab:not(.foogallery-tab-active):hover{color:#0073aa}.foogallery-vertical-child-tab.foogallery-tab-active{font-weight:600}.foogallery-tab-contents{display:inline-block;float:right;width:calc(100% - 150px);background-color:#fff;min-height:400px}.foogallery-tab-content{display:none}.foogallery-tab-content.foogallery-tab-active{display:block}.foogallery-settings.is-mobile .foogallery-vertical-tabs{width:36px}.foogallery-settings.is-mobile .foogallery-vertical-tab{text-align:center}.foogallery-settings.is-mobile .foogallery-vertical-tab:after{border-width:4px;margin-top:-4px}.foogallery-settings.is-mobile .foogallery-vertical-tab .dashicons{margin-right:0}.foogallery-settings.is-mobile .foogallery-vertical-tab>.foogallery-tab-text{display:none}.foogallery-settings.is-mobile .foogallery-vertical-tab>.dashicons{margin:0 3px 2px 4px}.foogallery-settings.is-mobile .foogallery-tab-contents{width:calc(100% - 36px)}.foogallery-settings.is-mobile .foogallery-vertical-child-header{display:block}.foogallery-settings.is-mobile .foogallery-vertical-tab.foogallery-show-child-menu:not(.foogallery-tab-active){color:#555;background-color:#ddd}.foogallery-settings.is-mobile .foogallery-vertical-tab.foogallery-tab-active .foogallery-vertical-child-header{color:#fff;background-color:#0073aa}
1
+ .foogallery-settings *{box-sizing:border-box}.foogallery-settings{position:relative;display:flex;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:13px}.foogallery-settings:after{display:table;content:"";clear:both}.foogallery-vertical-tabs{display:inline-block;position:relative;width:150px;background-color:#f5f5f5;border-right:solid 1px #ccd0d4}.foogallery-vertical-tab{position:relative;font-size:14px;margin:0;padding:7px 0;display:block;box-shadow:none;text-decoration:none;line-height:18px;color:#2271b1;cursor:pointer}.foogallery-settings.can-hover .foogallery-vertical-tab:not(.foogallery-tab-active):hover{color:#4f94d4}.foogallery-settings .foogallery-vertical-tab.foogallery-tab-active{color:#fff;background-color:#2271b1}.foogallery-vertical-tab:after{right:-1px;border:solid 8px transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none;border-right-color:#fff;top:17px;margin-top:-8px;visibility:hidden;opacity:0}.foogallery-settings.is-mobile .foogallery-vertical-tab.foogallery-tab-active:not(.foogallery-show-child-menu):after,.foogallery-settings:not(.is-mobile) .foogallery-vertical-tab.foogallery-tab-active:after{visibility:visible;opacity:1}.foogallery-vertical-tab .dashicons{font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;font-size:20px;width:20px;height:20px;vertical-align:middle;margin:0 3px 0 8px}.foogallery-vertical-tab .foogallery-tab-text{vertical-align:middle}.foogallery-vertical-child-tabs{display:none;margin:7px 0 -7px;color:#555;background-color:#ddd;border-top:1px solid #eee;width:150px;text-align:left}.foogallery-settings:not(.is-mobile) .foogallery-tab-active .foogallery-vertical-child-tabs{display:block}.foogallery-settings.can-hover:not(.is-mobile) .foogallery-vertical-tab.foogallery-show-child-menu:not(.foogallery-tab-active) .foogallery-vertical-child-tabs,.foogallery-settings.is-mobile .foogallery-vertical-tab.foogallery-show-child-menu .foogallery-vertical-child-tabs{display:block;position:absolute;top:-8px;right:0;transform:translateX(100%);z-index:11}.foogallery-vertical-child-tabs:after{left:-16px;border:solid 8px transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none;border-right-color:#ddd;top:17px;margin-top:-8px;visibility:hidden;opacity:0}.foogallery-settings:not(.is-mobile) .foogallery-vertical-tab:not(.foogallery-tab-active):hover .foogallery-vertical-child-tabs:after{visibility:visible;opacity:1}.foogallery-vertical-child-header{position:relative;padding:8px 12px;font-size:14px;font-weight:600;display:none}.foogallery-vertical-child-tab{position:relative;padding:4px 12px;font-size:13px;font-weight:400}.foogallery-vertical-child-tab:first-child{padding:8px 12px 4px}.foogallery-vertical-child-tab:last-child{padding:4px 12px 8px}.foogallery-vertical-child-tab:not(.foogallery-tab-active):hover{color:#0073aa}.foogallery-vertical-child-tab.foogallery-tab-active{font-weight:600}.foogallery-tab-contents{display:inline-block;float:right;width:calc(100% - 150px);background-color:#fff;min-height:400px}.foogallery-tab-content{display:none}.foogallery-tab-content.foogallery-tab-active{display:block}.foogallery-settings.is-mobile .foogallery-vertical-tabs{width:36px}.foogallery-settings.is-mobile .foogallery-vertical-tab{text-align:center}.foogallery-settings.is-mobile .foogallery-vertical-tab:after{border-width:4px;margin-top:-4px}.foogallery-settings.is-mobile .foogallery-vertical-tab .dashicons{margin-right:0}.foogallery-settings.is-mobile .foogallery-vertical-tab>.foogallery-tab-text{display:none}.foogallery-settings.is-mobile .foogallery-vertical-tab>.dashicons{margin:0 3px 0 4px}.foogallery-settings.is-mobile .foogallery-tab-contents{width:calc(100% - 36px)}.foogallery-settings.is-mobile .foogallery-vertical-child-header{display:block}.foogallery-settings.is-mobile .foogallery-vertical-tab.foogallery-show-child-menu:not(.foogallery-tab-active){color:#555;background-color:#ddd}.foogallery-settings.is-mobile .foogallery-vertical-tab.foogallery-tab-active .foogallery-vertical-child-header{color:#fff;background-color:#0073aa}
extensions/albums/class-albums-extension.php CHANGED
@@ -21,9 +21,6 @@ if ( ! class_exists( 'FooGallery_Albums_Extension' ) ) {
21
  new FooGallery_Albums_Admin_Columns();
22
  new FooGallery_Admin_Album_MetaBoxes();
23
 
24
- //add language settings
25
- add_filter( 'foogallery_admin_settings_override', array( $this, 'include_album_language_settings' ) );
26
-
27
  //add some global settings for albums
28
  add_filter( 'foogallery_admin_settings_override', array($this, 'add_album_settings' ) );
29
 
@@ -88,18 +85,6 @@ if ( ! class_exists( 'FooGallery_Albums_Extension' ) ) {
88
  flush_rewrite_rules();
89
  }
90
 
91
- function include_album_language_settings( $settings ) {
92
- $settings['settings'][] = array(
93
- 'id' => 'language_back_to_album_text',
94
- 'title' => __( 'Back To Album Text', 'foogallery' ),
95
- 'type' => 'text',
96
- 'default' => __( '« back to album', 'foogallery' ),
97
- 'tab' => 'language'
98
- );
99
-
100
- return $settings;
101
- }
102
-
103
  function add_album_settings( $settings ) {
104
 
105
  $settings['tabs']['albums'] = __( 'Albums', 'foogallery' );
@@ -113,6 +98,14 @@ if ( ! class_exists( 'FooGallery_Albums_Extension' ) ) {
113
  'tab' => 'albums'
114
  );
115
 
 
 
 
 
 
 
 
 
116
  return $settings;
117
  }
118
 
21
  new FooGallery_Albums_Admin_Columns();
22
  new FooGallery_Admin_Album_MetaBoxes();
23
 
 
 
 
24
  //add some global settings for albums
25
  add_filter( 'foogallery_admin_settings_override', array($this, 'add_album_settings' ) );
26
 
85
  flush_rewrite_rules();
86
  }
87
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  function add_album_settings( $settings ) {
89
 
90
  $settings['tabs']['albums'] = __( 'Albums', 'foogallery' );
98
  'tab' => 'albums'
99
  );
100
 
101
+ $settings['settings'][] = array(
102
+ 'id' => 'language_back_to_album_text',
103
+ 'title' => __( 'Back To Album Text', 'foogallery' ),
104
+ 'type' => 'text',
105
+ 'default' => __( '« back to album', 'foogallery' ),
106
+ 'tab' => 'albums'
107
+ );
108
+
109
  return $settings;
110
  }
111
 
extensions/default-templates/class-default-templates.php CHANGED
@@ -26,6 +26,7 @@ if ( ! class_exists( 'FooGallery_Default_Templates' ) ) {
26
  new FooGallery_Default_Gallery_Template();
27
  new FooGallery_Image_Viewer_Gallery_Template();
28
  new FooGallery_Justified_Gallery_Template();
 
29
  new FooGallery_Masonry_Gallery_Template();
30
  new FooGallery_Simple_Portfolio_Gallery_Template();
31
  new FooGallery_Thumbnail_Gallery_Template();
26
  new FooGallery_Default_Gallery_Template();
27
  new FooGallery_Image_Viewer_Gallery_Template();
28
  new FooGallery_Justified_Gallery_Template();
29
+ //new FooGallery_Justified_CSS_Gallery_Template();
30
  new FooGallery_Masonry_Gallery_Template();
31
  new FooGallery_Simple_Portfolio_Gallery_Template();
32
  new FooGallery_Thumbnail_Gallery_Template();
extensions/default-templates/default/class-default-gallery-template.php CHANGED
@@ -11,8 +11,6 @@ if ( ! class_exists( 'FooGallery_Default_Gallery_Template' ) ) {
11
  function __construct() {
12
  add_filter( 'foogallery_gallery_templates', array( $this, 'add_template' ) );
13
 
14
- add_action( 'foogallery_located_template-default', array( $this, 'enqueue_dependencies' ) );
15
-
16
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
17
 
18
  //build up the thumb dimensions from some arguments
@@ -65,6 +63,7 @@ if ( ! class_exists( 'FooGallery_Default_Gallery_Template' ) ) {
65
  'mandatory_classes' => 'fg-default',
66
  'thumbnail_dimensions' => true,
67
  'filtering_support' => true,
 
68
  'fields' => array(
69
  array(
70
  'id' => 'thumbnail_dimensions',
@@ -81,9 +80,27 @@ if ( ! class_exists( 'FooGallery_Default_Gallery_Template' ) ) {
81
  'data-foogallery-preview' => 'shortcode'
82
  )
83
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  array(
85
  'id' => 'thumbnail_link',
86
- 'title' => __( 'Link To', 'foogallery' ),
87
  'section' => __( 'General', 'foogallery' ),
88
  'default' => 'image',
89
  'type' => 'thumb_link',
@@ -141,15 +158,6 @@ if ( ! class_exists( 'FooGallery_Default_Gallery_Template' ) ) {
141
  return $gallery_templates;
142
  }
143
 
144
- /**
145
- * Enqueue scripts that the default gallery template relies on
146
- */
147
- function enqueue_dependencies( $gallery ) {
148
- //enqueue core files
149
- foogallery_enqueue_core_gallery_template_style();
150
- foogallery_enqueue_core_gallery_template_script();
151
- }
152
-
153
  /**
154
  * Builds thumb dimensions from arguments
155
  *
11
  function __construct() {
12
  add_filter( 'foogallery_gallery_templates', array( $this, 'add_template' ) );
13
 
 
 
14
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
15
 
16
  //build up the thumb dimensions from some arguments
63
  'mandatory_classes' => 'fg-default',
64
  'thumbnail_dimensions' => true,
65
  'filtering_support' => true,
66
+ 'enqueue_core' => true,
67
  'fields' => array(
68
  array(
69
  'id' => 'thumbnail_dimensions',
80
  'data-foogallery-preview' => 'shortcode'
81
  )
82
  ),
83
+ array(
84
+ 'id' => 'mobile_columns',
85
+ 'title' => __( 'Mobile Layout', 'foogallery' ),
86
+ 'desc' => __( 'Number of columns to show on mobile (screen widths less than 600px)', 'foogallery' ),
87
+ 'section' => __( 'General', 'foogallery' ),
88
+ 'default' => '',
89
+ 'type' => 'radio',
90
+ 'choices' => array(
91
+ '' => __( 'Default', 'foogallery' ),
92
+ 'fg-m-col1' => __( '1 Column', 'foogallery' ),
93
+ 'fg-m-col2' => __( '2 Columns', 'foogallery' ),
94
+ 'fg-m-col3' => __( '3 Columns', 'foogallery' ),
95
+ ),
96
+ 'row_data' => array(
97
+ 'data-foogallery-change-selector' => 'input:radio',
98
+ 'data-foogallery-preview' => 'shortcode'
99
+ )
100
+ ),
101
  array(
102
  'id' => 'thumbnail_link',
103
+ 'title' => __( 'Thumbnail Link', 'foogallery' ),
104
  'section' => __( 'General', 'foogallery' ),
105
  'default' => 'image',
106
  'type' => 'thumb_link',
158
  return $gallery_templates;
159
  }
160
 
 
 
 
 
 
 
 
 
 
161
  /**
162
  * Builds thumb dimensions from arguments
163
  *
extensions/default-templates/default/gallery-default.php CHANGED
@@ -6,9 +6,10 @@ global $current_foogallery;
6
 
7
  $lightbox = foogallery_gallery_template_setting( 'lightbox', 'unknown' );
8
  $spacing = foogallery_gallery_template_setting( 'spacing', 'spacing-width-10' );
 
9
  $alignment = foogallery_gallery_template_setting( 'alignment', 'fg-center' );
10
 
11
- $foogallery_default_classes = foogallery_build_class_attribute_safe( $current_foogallery, 'foogallery-lightbox-' . $lightbox, $spacing, $alignment );
12
  $foogallery_default_attributes = foogallery_build_container_attributes_safe( $current_foogallery, array( 'class' => $foogallery_default_classes ) );
13
 
14
  ?><div <?php echo $foogallery_default_attributes; ?>>
6
 
7
  $lightbox = foogallery_gallery_template_setting( 'lightbox', 'unknown' );
8
  $spacing = foogallery_gallery_template_setting( 'spacing', 'spacing-width-10' );
9
+ $mobile_columns = foogallery_gallery_template_setting( 'mobile_columns', '' );
10
  $alignment = foogallery_gallery_template_setting( 'alignment', 'fg-center' );
11
 
12
+ $foogallery_default_classes = foogallery_build_class_attribute_safe( $current_foogallery, 'foogallery-lightbox-' . $lightbox, $spacing, $alignment, $mobile_columns );
13
  $foogallery_default_attributes = foogallery_build_container_attributes_safe( $current_foogallery, array( 'class' => $foogallery_default_classes ) );
14
 
15
  ?><div <?php echo $foogallery_default_attributes; ?>>
extensions/default-templates/functions.php CHANGED
@@ -21,11 +21,21 @@ function foogallery_enqueue_core_gallery_template_style() {
21
 
22
  /**
23
  * Enqueue the core FooGallery script used by all default templates
 
 
24
  */
25
- function foogallery_enqueue_core_gallery_template_script() {
 
 
 
 
 
 
 
 
26
  $filename = foogallery_is_debug() ? '' : '.min';
27
  $js = apply_filters( 'foogallery_core_gallery_script', FOOGALLERY_DEFAULT_TEMPLATES_EXTENSION_SHARED_URL . 'js/foogallery' . $filename . '.js' );
28
- wp_enqueue_script( 'foogallery-core', $js, array('jquery'), FOOGALLERY_VERSION );
29
  do_action( 'foogallery_enqueue_script-core', $js );
30
 
31
  if ( foogallery_get_setting( 'custom_js', '' ) !== '' ) {
21
 
22
  /**
23
  * Enqueue the core FooGallery script used by all default templates
24
+ *
25
+ * @param string[] $deps
26
  */
27
+ function foogallery_enqueue_core_gallery_template_script( $deps = null ) {
28
+ if ( isset( $deps ) ) {
29
+ //ensure we deregister the previous one
30
+ wp_deregister_script( 'foogallery-core' );
31
+ } else {
32
+ //set the default
33
+ $deps = array( 'jquery' );
34
+ }
35
+
36
  $filename = foogallery_is_debug() ? '' : '.min';
37
  $js = apply_filters( 'foogallery_core_gallery_script', FOOGALLERY_DEFAULT_TEMPLATES_EXTENSION_SHARED_URL . 'js/foogallery' . $filename . '.js' );
38
+ wp_enqueue_script( 'foogallery-core', $js, $deps, FOOGALLERY_VERSION );
39
  do_action( 'foogallery_enqueue_script-core', $js );
40
 
41
  if ( foogallery_get_setting( 'custom_js', '' ) !== '' ) {
extensions/default-templates/image-viewer/class-image-viewer-gallery-template.php CHANGED
@@ -14,8 +14,6 @@ if ( !class_exists( 'FooGallery_Image_Viewer_Gallery_Template' ) ) {
14
  //add extra fields to the templates
15
  add_filter( 'foogallery_override_gallery_template_fields-image-viewer', array( $this, 'add_common_thumbnail_fields' ), 10, 2 );
16
 
17
- add_action( 'foogallery_located_template-image-viewer', array( $this, 'enqueue_dependencies' ) );
18
-
19
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
20
 
21
  add_filter( 'foogallery_template_thumbnail_dimensions-image-viewer', array( $this, 'get_thumbnail_dimensions' ), 10, 2 );
@@ -74,6 +72,7 @@ if ( !class_exists( 'FooGallery_Image_Viewer_Gallery_Template' ) ) {
74
  'lazyload_support' => true,
75
  'mandatory_classes' => 'fg-image-viewer',
76
  'thumbnail_dimensions' => true,
 
77
  'fields' => array(
78
  array(
79
  'id' => 'thumbnail-help',
@@ -100,11 +99,11 @@ if ( !class_exists( 'FooGallery_Image_Viewer_Gallery_Template' ) ) {
100
  ),
101
  array(
102
  'id' => 'thumbnail_link',
103
- 'title' => __( 'Thumb Link', 'foogallery' ),
104
  'section' => __( 'General', 'foogallery' ),
105
  'default' => 'image' ,
106
  'type' => 'thumb_link',
107
- 'desc' => __( 'You can choose to either link each thumbnail to the full size image or to the image\'s attachment page', 'foogallery')
108
  ),
109
  array(
110
  'id' => 'lightbox',
@@ -112,7 +111,7 @@ if ( !class_exists( 'FooGallery_Image_Viewer_Gallery_Template' ) ) {
112
  'section' => __( 'General', 'foogallery' ),
113
  'desc' => __( 'Choose which lightbox you want to use in the gallery', 'foogallery' ),
114
  'default' => 'none',
115
- 'type' => 'lightbox'
116
  ),
117
  array(
118
  'id' => 'alignment',
@@ -183,15 +182,6 @@ if ( !class_exists( 'FooGallery_Image_Viewer_Gallery_Template' ) ) {
183
  return $fields;
184
  }
185
 
186
- /**
187
- * Enqueue scripts that the default gallery template relies on
188
- */
189
- function enqueue_dependencies( $gallery ) {
190
- //enqueue core files
191
- foogallery_enqueue_core_gallery_template_style();
192
- foogallery_enqueue_core_gallery_template_script();
193
- }
194
-
195
  /**
196
  * Get the thumb dimensions arguments saved for the gallery for this gallery template
197
  *
14
  //add extra fields to the templates
15
  add_filter( 'foogallery_override_gallery_template_fields-image-viewer', array( $this, 'add_common_thumbnail_fields' ), 10, 2 );
16
 
 
 
17
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
18
 
19
  add_filter( 'foogallery_template_thumbnail_dimensions-image-viewer', array( $this, 'get_thumbnail_dimensions' ), 10, 2 );
72
  'lazyload_support' => true,
73
  'mandatory_classes' => 'fg-image-viewer',
74
  'thumbnail_dimensions' => true,
75
+ 'enqueue_core' => true,
76
  'fields' => array(
77
  array(
78
  'id' => 'thumbnail-help',
99
  ),
100
  array(
101
  'id' => 'thumbnail_link',
102
+ 'title' => __( 'Thumbnail Link', 'foogallery' ),
103
  'section' => __( 'General', 'foogallery' ),
104
  'default' => 'image' ,
105
  'type' => 'thumb_link',
106
+ 'desc' => __( 'You can choose to either link each thumbnail to the full size image or to the image\'s attachment page', 'foogallery'),
107
  ),
108
  array(
109
  'id' => 'lightbox',
111
  'section' => __( 'General', 'foogallery' ),
112
  'desc' => __( 'Choose which lightbox you want to use in the gallery', 'foogallery' ),
113
  'default' => 'none',
114
+ 'type' => 'lightbox',
115
  ),
116
  array(
117
  'id' => 'alignment',
182
  return $fields;
183
  }
184
 
 
 
 
 
 
 
 
 
 
185
  /**
186
  * Get the thumb dimensions arguments saved for the gallery for this gallery template
187
  *
extensions/default-templates/justified/class-justified-gallery-template.php CHANGED
@@ -5,6 +5,9 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
5
  define('FOOGALLERY_JUSTIFIED_GALLERY_TEMPLATE_URL', plugin_dir_url( __FILE__ ));
6
 
7
  class FooGallery_Justified_Gallery_Template {
 
 
 
8
  /**
9
  * Wire up everything we need to run the extension
10
  */
@@ -13,8 +16,6 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
13
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
14
  add_filter( 'foogallery_template_thumbnail_dimensions-justified', array( $this, 'get_thumbnail_dimensions' ), 10, 2 );
15
 
16
- add_action( 'foogallery_located_template-justified', array( $this, 'enqueue_dependencies' ) );
17
-
18
  //add the data options needed for justified
19
  add_filter( 'foogallery_build_container_data_options-justified', array( $this, 'add_justified_options' ), 10, 3 );
20
 
@@ -25,8 +26,37 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
25
  add_filter( 'foogallery_gallery_template_arguments-justified', array( $this, 'build_gallery_template_arguments' ) );
26
 
27
  add_filter( 'foogallery_override_gallery_template_fields-justified', array( $this, 'adjust_default_field_values' ), 10, 2 );
 
 
 
28
  }
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  /**
31
  * Register myself so that all associated JS and CSS files can be found and automatically included
32
  * @param $extensions
@@ -46,7 +76,7 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
46
  */
47
  function add_template( $gallery_templates ) {
48
  $gallery_templates[] = array(
49
- 'slug' => 'justified',
50
  'name' => __( 'Justified Gallery', 'foogallery' ),
51
  'preview_support' => true,
52
  'common_fields_support' => true,
@@ -55,15 +85,32 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
55
  'mandatory_classes' => 'fg-justified',
56
  'thumbnail_dimensions' => true,
57
  'filtering_support' => true,
 
58
  'fields' => array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  array(
60
  'id' => 'thumb_height',
61
- 'title' => __( 'Thumb Height', 'foogallery' ),
62
- 'desc' => __( 'Choose the height of your thumbnails. Thumbnails will be generated on the fly and cached once generated', 'foogallery' ),
63
  'section' => __( 'General', 'foogallery' ),
64
  'type' => 'number',
65
  'class' => 'small-text',
66
- 'default' => 250,
67
  'step' => '10',
68
  'min' => '0',
69
  'row_data'=> array(
@@ -71,36 +118,6 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
71
  'data-foogallery-change-selector' => 'input',
72
  )
73
  ),
74
- array(
75
- 'id' => 'row_height',
76
- 'title' => __( 'Row Height', 'foogallery' ),
77
- 'desc' => __( 'The preferred height of your gallery rows. This can be different from the thumbnail height', 'foogallery' ),
78
- 'section' => __( 'General', 'foogallery' ),
79
- 'type' => 'number',
80
- 'class' => 'small-text',
81
- 'default' => 200,
82
- 'step' => '10',
83
- 'min' => '0',
84
- 'row_data'=> array(
85
- 'data-foogallery-change-selector' => 'input',
86
- 'data-foogallery-value-selector' => 'input',
87
- 'data-foogallery-preview' => 'shortcode',
88
- )
89
- ),
90
- array(
91
- 'id' => 'max_row_height',
92
- 'title' => __( 'Max Row Height', 'foogallery' ),
93
- 'desc' => __( 'A number (e.g 200) which specifies the maximum row height in pixels. A negative value for no limits. Alternatively, use a percentage (e.g. 200% which means that the row height cannot exceed 2 * rowHeight)', 'foogallery' ),
94
- 'section' => __( 'General', 'foogallery' ),
95
- 'type' => 'text',
96
- 'class' => 'small-text',
97
- 'default' => '150%',
98
- 'row_data'=> array(
99
- 'data-foogallery-change-selector' => 'input',
100
- 'data-foogallery-value-selector' => 'input',
101
- 'data-foogallery-preview' => 'shortcode',
102
- )
103
- ),
104
  array(
105
  'id' => 'margins',
106
  'title' => __( 'Margins', 'foogallery' ),
@@ -133,28 +150,25 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
133
  'default' => 'none',
134
  'type' => 'lightbox',
135
  ),
136
- array(
137
- 'id' => 'lastrow',
138
- 'title' => __( 'Last Row', 'foogallery' ),
139
- 'desc' => __( 'What should be done with the last row in the gallery?', 'foogallery' ),
140
- 'section' => __( 'General', 'foogallery' ),
141
- 'type' => 'radio',
142
- 'spacer' => '<span class="spacer"></span>',
143
- 'default' => 'justify',
144
- 'choices' => array(
145
- 'hide' => __( 'Hide', 'foogallery' ),
146
- 'justify' => __( 'Justify', 'foogallery' ),
147
- 'nojustify' => __( 'No Justify', 'foogallery' ),
148
- 'right' => __( 'Right', 'foogallery' ),
149
- 'center' => __( 'Center', 'foogallery' ),
150
- 'left' => __( 'Left', 'foogallery' ),
151
- ),
152
- 'row_data'=> array(
153
- 'data-foogallery-change-selector' => 'input:radio',
154
- 'data-foogallery-value-selector' => 'input:checked',
155
- 'data-foogallery-preview' => 'shortcode',
156
- )
157
- ),
158
  ),
159
  );
160
 
@@ -170,23 +184,13 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
170
  * @return mixed
171
  */
172
  function get_thumbnail_dimensions( $dimensions, $foogallery ) {
173
- $height = $foogallery->get_meta( 'justified_thumb_height', false );
174
  return array(
175
- 'height' => intval( $height ),
176
  'width' => 0,
177
  'crop' => false
178
  );
179
  }
180
 
181
- /**
182
- * Enqueue scripts that the default gallery template relies on
183
- */
184
- function enqueue_dependencies( $gallery ) {
185
- //enqueue core files
186
- foogallery_enqueue_core_gallery_template_style();
187
- foogallery_enqueue_core_gallery_template_script();
188
- }
189
-
190
  /**
191
  * Add the required justified options if needed
192
  *
@@ -198,23 +202,54 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
198
  * @return array
199
  */
200
  function add_justified_options($options, $gallery, $attributes) {
 
 
 
201
 
202
- $row_height = foogallery_gallery_template_setting( 'row_height', '150' );
203
- $max_row_height = foogallery_gallery_template_setting( 'max_row_height', '200%' );
204
- if ( strpos( $max_row_height, '%' ) === false ) {
205
- $max_row_height = intval( $max_row_height );
206
- }
207
  $margins = foogallery_gallery_template_setting( 'margins', '1' );
208
- $lastRow = foogallery_gallery_template_setting( 'lastrow', 'center' );
209
 
210
- $options['template']['rowHeight'] = intval($row_height);
211
- $options['template']['maxRowHeight'] = $max_row_height;
212
- $options['template']['margins'] = intval($margins);
213
- $options['template']['lastRow'] = $lastRow;
214
 
215
  return $options;
216
  }
217
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  /**
219
  * Builds thumb dimensions from arguments
220
  *
@@ -224,15 +259,22 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
224
  * @return mixed
225
  */
226
  function build_thumbnail_dimensions_from_arguments( $dimensions, $arguments ) {
227
- if ( array_key_exists( 'thumbnail_height', $arguments) ) {
228
- return array(
229
- 'height' => intval($arguments['thumbnail_height']),
230
- 'width' => 0,
231
- 'crop' => false
232
- );
233
- }
234
-
235
- return null;
 
 
 
 
 
 
 
236
  }
237
 
238
  /**
@@ -242,9 +284,8 @@ if ( !class_exists( 'FooGallery_Justified_Gallery_Template' ) ) {
242
  * @return array
243
  */
244
  function build_gallery_template_arguments( $args ) {
245
- $height = foogallery_gallery_template_setting( 'thumb_height', '250' );
246
  $args = array(
247
- 'height' => $height,
248
  'link' => foogallery_gallery_template_setting( 'thumbnail_link', 'image' ),
249
  'crop' => false
250
  );
5
  define('FOOGALLERY_JUSTIFIED_GALLERY_TEMPLATE_URL', plugin_dir_url( __FILE__ ));
6
 
7
  class FooGallery_Justified_Gallery_Template {
8
+
9
+ const template_id = 'justified';
10
+
11
  /**
12
  * Wire up everything we need to run the extension
13
  */
16
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
17
  add_filter( 'foogallery_template_thumbnail_dimensions-justified', array( $this, 'get_thumbnail_dimensions' ), 10, 2 );
18
 
 
 
19
  //add the data options needed for justified
20
  add_filter( 'foogallery_build_container_data_options-justified', array( $this, 'add_justified_options' ), 10, 3 );
21
 
26
  add_filter( 'foogallery_gallery_template_arguments-justified', array( $this, 'build_gallery_template_arguments' ) );
27
 
28
  add_filter( 'foogallery_override_gallery_template_fields-justified', array( $this, 'adjust_default_field_values' ), 10, 2 );
29
+
30
+ //add a style block for the gallery based on the field settings
31
+ add_action( 'foogallery_loaded_template_before', array( $this, 'add_style_block' ), 10, 1 );
32
  }
33
 
34
+ /**
35
+ * Add a style block based on the field settings
36
+ *
37
+ * @param $gallery FooGallery
38
+ */
39
+ function add_style_block( $gallery ) {
40
+ if ( self::template_id !== $gallery->gallery_template ) {
41
+ return;
42
+ }
43
+
44
+ $id = $gallery->container_id();
45
+ $margins = intval( foogallery_gallery_template_setting( 'margins', 2 ) );
46
+ $row_height = intval( foogallery_gallery_template_setting( 'row_height', 250 ) );
47
+ ?>
48
+ <style>
49
+ #<?php echo $id; ?>.fg-justified .fg-item {
50
+ margin-right: <?php echo $margins; ?>px;
51
+ margin-bottom: <?php echo $margins; ?>px;
52
+ }
53
+ #<?php echo $id; ?>.fg-justified .fg-image {
54
+ height: <?php echo $row_height; ?>px;
55
+ }
56
+ </style>
57
+ <?php
58
+ }
59
+
60
  /**
61
  * Register myself so that all associated JS and CSS files can be found and automatically included
62
  * @param $extensions
76
  */
77
  function add_template( $gallery_templates ) {
78
  $gallery_templates[] = array(
79
+ 'slug' => self::template_id,
80
  'name' => __( 'Justified Gallery', 'foogallery' ),
81
  'preview_support' => true,
82
  'common_fields_support' => true,
85
  'mandatory_classes' => 'fg-justified',
86
  'thumbnail_dimensions' => true,
87
  'filtering_support' => true,
88
+ 'enqueue_core' => true,
89
  'fields' => array(
90
+ array(
91
+ 'id' => 'row_height',
92
+ 'title' => __( 'Row Height', 'foogallery' ),
93
+ 'desc' => __( 'The preferred height of your gallery rows. Depending on the aspect ratio of your images and the viewport, the row height might increase up to Max Row Height.', 'foogallery' ),
94
+ 'section' => __( 'General', 'foogallery' ),
95
+ 'type' => 'number',
96
+ 'class' => 'small-text',
97
+ 'default' => 200,
98
+ 'step' => '10',
99
+ 'min' => '0',
100
+ 'row_data'=> array(
101
+ 'data-foogallery-change-selector' => 'input',
102
+ 'data-foogallery-value-selector' => 'input',
103
+ 'data-foogallery-preview' => 'shortcode',
104
+ )
105
+ ),
106
  array(
107
  'id' => 'thumb_height',
108
+ 'title' => __( 'Max Row Height', 'foogallery' ),
109
+ 'desc' => __( 'Choose the max height of your gallery rows. It should always be larger than Row Height by about 150%.', 'foogallery' ),
110
  'section' => __( 'General', 'foogallery' ),
111
  'type' => 'number',
112
  'class' => 'small-text',
113
+ 'default' => 300,
114
  'step' => '10',
115
  'min' => '0',
116
  'row_data'=> array(
118
  'data-foogallery-change-selector' => 'input',
119
  )
120
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  array(
122
  'id' => 'margins',
123
  'title' => __( 'Margins', 'foogallery' ),
150
  'default' => 'none',
151
  'type' => 'lightbox',
152
  ),
153
+ array(
154
+ 'id' => 'align',
155
+ 'title' => __( 'Alignment', 'foogallery' ),
156
+ 'desc' => __( 'For rows that cannot be justified, what alignment should be used?', 'foogallery' ),
157
+ 'section' => __( 'General', 'foogallery' ),
158
+ 'type' => 'radio',
159
+ 'spacer' => '<span class="spacer"></span>',
160
+ 'default' => 'center',
161
+ 'choices' => array(
162
+ 'left' => __( 'Left', 'foogallery' ),
163
+ 'center' => __( 'Center', 'foogallery' ),
164
+ 'right' => __( 'Right', 'foogallery' ),
165
+ ),
166
+ 'row_data'=> array(
167
+ 'data-foogallery-change-selector' => 'input:radio',
168
+ 'data-foogallery-value-selector' => 'input:checked',
169
+ 'data-foogallery-preview' => 'shortcode',
170
+ )
171
+ ),
 
 
 
172
  ),
173
  );
174
 
184
  * @return mixed
185
  */
186
  function get_thumbnail_dimensions( $dimensions, $foogallery ) {
 
187
  return array(
188
+ 'height' => $this->max_row_height_from_current_gallery(),
189
  'width' => 0,
190
  'crop' => false
191
  );
192
  }
193
 
 
 
 
 
 
 
 
 
 
194
  /**
195
  * Add the required justified options if needed
196
  *
202
  * @return array
203
  */
204
  function add_justified_options($options, $gallery, $attributes) {
205
+ $this->calculate_row_heights_for_current_gallery();
206
+
207
+ $values = foogallery_current_gallery_get_cached_value( 'justified_row_height' );
208
 
 
 
 
 
 
209
  $margins = foogallery_gallery_template_setting( 'margins', '1' );
210
+ $align = foogallery_gallery_template_setting( 'align', 'center' );
211
 
212
+ $options['template']['rowHeight'] = intval( $values['row_height'] );
213
+ $options['template']['maxRowHeight'] = intval( $values['max_row_height'] );
214
+ $options['template']['margins'] = intval( $margins );
215
+ $options['template']['align'] = $align;
216
 
217
  return $options;
218
  }
219
 
220
+ /**
221
+ * Calculates the row heights for the current gallery, also taking into account legacy settings
222
+ */
223
+ function calculate_row_heights_for_current_gallery() {
224
+ if ( !foogallery_current_gallery_has_cached_value( 'justified_row_height') ) {
225
+ $row_height = foogallery_gallery_template_setting( 'row_height', '200' );
226
+
227
+ //check to see if there is a legacy max_row_height
228
+ $max_row_height = foogallery_gallery_template_setting( 'max_row_height', false );
229
+
230
+ if ( false === $max_row_height ) {
231
+ //we do not have a legacy max_row_height, so use the thumb_height
232
+ $max_row_height = intval( foogallery_gallery_template_setting( 'thumb_height', '300' ) );
233
+ } else {
234
+ if ( strpos( $max_row_height, '%' ) === false ) {
235
+ $max_row_height = intval( $max_row_height );
236
+ } else {
237
+ $max_row_height = intval( $row_height * intval( $max_row_height ) / 100 );
238
+ }
239
+ }
240
+
241
+ //check for a negative max_row_height
242
+ if ( $max_row_height < 0 ) {
243
+ $max_row_height = $row_height * 2;
244
+ }
245
+
246
+ foogallery_current_gallery_set_cached_value( 'justified_row_height', array(
247
+ 'row_height' => intval( $row_height ),
248
+ 'max_row_height' => $max_row_height
249
+ ) );
250
+ }
251
+ }
252
+
253
  /**
254
  * Builds thumb dimensions from arguments
255
  *
259
  * @return mixed
260
  */
261
  function build_thumbnail_dimensions_from_arguments( $dimensions, $arguments ) {
262
+ return array(
263
+ 'height' => $this->max_row_height_from_current_gallery(),
264
+ 'width' => 0,
265
+ 'crop' => false
266
+ );
267
+ }
268
+
269
+ /**
270
+ * Returns the max_row_height for the current gallery
271
+ *
272
+ * @return int
273
+ */
274
+ function max_row_height_from_current_gallery() {
275
+ $this->calculate_row_heights_for_current_gallery();
276
+ $values = foogallery_current_gallery_get_cached_value( 'justified_row_height' );
277
+ return intval( $values['max_row_height'] );
278
  }
279
 
280
  /**
284
  * @return array
285
  */
286
  function build_gallery_template_arguments( $args ) {
 
287
  $args = array(
288
+ 'height' => $this->max_row_height_from_current_gallery(),
289
  'link' => foogallery_gallery_template_setting( 'thumbnail_link', 'image' ),
290
  'crop' => false
291
  );
extensions/default-templates/masonry/class-masonry-gallery-template.php CHANGED
@@ -5,6 +5,9 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
5
  define('FOOGALLERY_MASONRY_GALLERY_TEMPLATE_URL', plugin_dir_url( __FILE__ ));
6
 
7
  class FooGallery_Masonry_Gallery_Template {
 
 
 
8
  /**
9
  * Wire up everything we need to run the extension
10
  */
@@ -32,8 +35,62 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
32
 
33
  //remove the captions if the captions are below thumbs
34
  add_filter( 'foogallery_build_attachment_html_caption', array( $this, 'remove_captions' ), 10, 3 );
 
 
 
 
 
35
  }
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  /**
38
  * Register myself so that all associated JS and CSS files can be found and automatically included
39
  * @param $extensions
@@ -53,7 +110,7 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
53
  */
54
  function add_template( $gallery_templates ) {
55
  $gallery_templates[] = array(
56
- 'slug' => 'masonry',
57
  'name' => __( 'Masonry Image Gallery', 'foogallery' ),
58
  'preview_support' => true,
59
  'common_fields_support' => true,
@@ -70,7 +127,7 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
70
  'section' => __( 'General', 'foogallery' ),
71
  'type' => 'number',
72
  'class' => 'small-text',
73
- 'default' => 150,
74
  'step' => '1',
75
  'min' => '0',
76
  'row_data'=> array(
@@ -86,10 +143,11 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
86
  'type' => 'radio',
87
  'choices' => array(
88
  'fixed' => __( 'Fixed Width', 'foogallery' ),
89
- 'col2' => __( '2 Columns', 'foogallery' ),
90
- 'col3' => __( '3 Columns', 'foogallery' ),
91
  'col4' => __( '4 Columns', 'foogallery' ),
92
- 'col5' => __( '5 Columns', 'foogallery' )
 
93
  ),
94
  'default' => 'fixed',
95
  'row_data'=> array(
@@ -98,6 +156,23 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
98
  'data-foogallery-preview' => 'shortcode'
99
  )
100
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  array(
102
  'id' => 'gutter_width',
103
  'title' => __( 'Gutter Width', 'foogallery' ),
@@ -161,7 +236,7 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
161
  ),
162
  array(
163
  'id' => 'thumbnail_link',
164
- 'title' => __( 'Thumb Link', 'foogallery' ),
165
  'default' => 'image' ,
166
  'type' => 'thumb_link',
167
  'desc' => __( 'You can choose to link each thumbnail to the full size image, or to the image\'s attachment page, or you can choose to not link to anything', 'foogallery' ),
@@ -195,7 +270,7 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
195
 
196
  //enqueue core files
197
  foogallery_enqueue_core_gallery_template_style();
198
- foogallery_enqueue_core_gallery_template_script();
199
  }
200
 
201
  /**
@@ -227,13 +302,16 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
227
  */
228
  function add_masonry_options($options, $gallery, $attributes) {
229
  $layout = foogallery_gallery_template_setting( 'layout', 'fixed' );
230
- $options['template']['layout'] = $layout;
231
  if ( 'fixed' === $layout ) {
232
- $width = foogallery_gallery_template_setting( 'thumbnail_width', '150' );
233
  $gutter_width = foogallery_gallery_template_setting( 'gutter_width', '10' );
234
  $options['template']['columnWidth'] = intval($width);
235
  $options['template']['gutter'] = intval($gutter_width);
236
  }
 
 
 
 
237
  return $options;
238
  }
239
 
@@ -264,7 +342,7 @@ if ( !class_exists( 'FooGallery_Masonry_Gallery_Template' ) ) {
264
  */
265
  function build_gallery_template_arguments( $args ) {
266
  $args = array(
267
- 'width' => foogallery_gallery_template_setting( 'thumbnail_width', '150' ),
268
  'link' => foogallery_gallery_template_setting( 'thumbnail_link', 'image' ),
269
  'crop' => false
270
  );
5
  define('FOOGALLERY_MASONRY_GALLERY_TEMPLATE_URL', plugin_dir_url( __FILE__ ));
6
 
7
  class FooGallery_Masonry_Gallery_Template {
8
+
9
+ const template_id = 'masonry';
10
+
11
  /**
12
  * Wire up everything we need to run the extension
13
  */
35
 
36
  //remove the captions if the captions are below thumbs
37
  add_filter( 'foogallery_build_attachment_html_caption', array( $this, 'remove_captions' ), 10, 3 );
38
+
39
+ //add a style block for the gallery based on the field settings
40
+ add_action( 'foogallery_loaded_template_before', array( $this, 'add_style_block' ), 10, 1 );
41
+
42
+ add_filter( 'foogallery_build_class_attribute', array( $this, 'override_class_attributes' ), 99, 2 );
43
  }
44
 
45
+ /**
46
+ * Override the classes for the layout
47
+ *
48
+ * @param $classes array
49
+ * @param $gallery FooGallery
50
+ *
51
+ * @return array
52
+ */
53
+ function override_class_attributes( $classes, $gallery ) {
54
+ if ( self::template_id === $gallery->gallery_template ) {
55
+ $classes[] = 'fg-' . foogallery_gallery_template_setting( 'layout', 'fixed' );
56
+ }
57
+
58
+ return $classes;
59
+ }
60
+
61
+ /**
62
+ * Add a style block based on the field settings
63
+ *
64
+ * @param $gallery FooGallery
65
+ */
66
+ function add_style_block( $gallery ) {
67
+ if ( self::template_id !== $gallery->gallery_template ) {
68
+ return;
69
+ }
70
+
71
+ $id = $gallery->container_id();
72
+ $layout = foogallery_gallery_template_setting( 'layout', 'fixed' );
73
+
74
+ //get out early if the layout is not fixed
75
+ if ( 'fixed' !== $layout ) {
76
+ return;
77
+ }
78
+
79
+ $thumbnail_width = intval( foogallery_gallery_template_setting( 'thumbnail_width', 250 ) );
80
+ $gutter_width = intval( foogallery_gallery_template_setting( 'gutter_width', 10 ) );
81
+
82
+ ?>
83
+ <style>
84
+ #<?php echo $id; ?>.fg-masonry .fg-item {
85
+ width: <?php echo $thumbnail_width; ?>px;
86
+ margin-right: <?php echo $gutter_width; ?>px;
87
+ margin-bottom: <?php echo $gutter_width; ?>px;
88
+ }
89
+ </style>
90
+ <?php
91
+ }
92
+
93
+
94
  /**
95
  * Register myself so that all associated JS and CSS files can be found and automatically included
96
  * @param $extensions
110
  */
111
  function add_template( $gallery_templates ) {
112
  $gallery_templates[] = array(
113
+ 'slug' => self::template_id,
114
  'name' => __( 'Masonry Image Gallery', 'foogallery' ),
115
  'preview_support' => true,
116
  'common_fields_support' => true,
127
  'section' => __( 'General', 'foogallery' ),
128
  'type' => 'number',
129
  'class' => 'small-text',
130
+ 'default' => 250,
131
  'step' => '1',
132
  'min' => '0',
133
  'row_data'=> array(
143
  'type' => 'radio',
144
  'choices' => array(
145
  'fixed' => __( 'Fixed Width', 'foogallery' ),
146
+ 'col6' => __( '6 Columns', 'foogallery' ),
147
+ 'col5' => __( '5 Columns', 'foogallery' ),
148
  'col4' => __( '4 Columns', 'foogallery' ),
149
+ 'col3' => __( '3 Columns', 'foogallery' ),
150
+ 'col2' => __( '2 Columns', 'foogallery' ),
151
  ),
152
  'default' => 'fixed',
153
  'row_data'=> array(
156
  'data-foogallery-preview' => 'shortcode'
157
  )
158
  ),
159
+ array(
160
+ 'id' => 'horizontal',
161
+ 'title' => __( 'Horizontal Layout', 'foogallery' ),
162
+ 'desc' => __( 'You can choose to lay out items to (mostly) maintain horizontal left-to-right order.', 'foogallery' ),
163
+ 'section' => __( 'General', 'foogallery' ),
164
+ 'type' => 'radio',
165
+ 'choices' => array(
166
+ '' => __( 'Disabled', 'foogallery' ),
167
+ 'yes' => __( 'Try to maintain lef-to-right order', 'foogallery' ),
168
+ ),
169
+ 'default' => '',
170
+ 'row_data'=> array(
171
+ 'data-foogallery-change-selector' => 'input:radio',
172
+ 'data-foogallery-value-selector' => 'input:checked',
173
+ 'data-foogallery-preview' => 'shortcode'
174
+ )
175
+ ),
176
  array(
177
  'id' => 'gutter_width',
178
  'title' => __( 'Gutter Width', 'foogallery' ),
236
  ),
237
  array(
238
  'id' => 'thumbnail_link',
239
+ 'title' => __( 'Thumbnail Link', 'foogallery' ),
240
  'default' => 'image' ,
241
  'type' => 'thumb_link',
242
  'desc' => __( 'You can choose to link each thumbnail to the full size image, or to the image\'s attachment page, or you can choose to not link to anything', 'foogallery' ),
270
 
271
  //enqueue core files
272
  foogallery_enqueue_core_gallery_template_style();
273
+ foogallery_enqueue_core_gallery_template_script( array('jquery', 'masonry' ) );
274
  }
275
 
276
  /**
302
  */
303
  function add_masonry_options($options, $gallery, $attributes) {
304
  $layout = foogallery_gallery_template_setting( 'layout', 'fixed' );
 
305
  if ( 'fixed' === $layout ) {
306
+ $width = foogallery_gallery_template_setting( 'thumbnail_width', '250' );
307
  $gutter_width = foogallery_gallery_template_setting( 'gutter_width', '10' );
308
  $options['template']['columnWidth'] = intval($width);
309
  $options['template']['gutter'] = intval($gutter_width);
310
  }
311
+ $horizontal = foogallery_gallery_template_setting( 'horizontal', '' );
312
+ if ( 'yes' === $horizontal ) {
313
+ $options['template']['horizontalOrder'] = true;
314
+ }
315
  return $options;
316
  }
317
 
342
  */
343
  function build_gallery_template_arguments( $args ) {
344
  $args = array(
345
+ 'width' => foogallery_gallery_template_setting( 'thumbnail_width', '250' ),
346
  'link' => foogallery_gallery_template_setting( 'thumbnail_link', 'image' ),
347
  'crop' => false
348
  );
extensions/default-templates/masonry/gallery-masonry.php CHANGED
@@ -16,6 +16,10 @@ $foogallery_masonry_classes = foogallery_build_class_attribute_safe( $current_fo
16
  $foogallery_masonry_attributes = foogallery_build_container_attributes_safe( $current_foogallery, array( 'class' => $foogallery_masonry_classes) );
17
  ?>
18
  <div <?php echo $foogallery_masonry_attributes; ?>>
 
 
 
 
19
  <?php foreach ( foogallery_current_gallery_attachments_for_rendering() as $attachment ) {
20
  echo foogallery_attachment_html( $attachment );
21
  } ?>
16
  $foogallery_masonry_attributes = foogallery_build_container_attributes_safe( $current_foogallery, array( 'class' => $foogallery_masonry_classes) );
17
  ?>
18
  <div <?php echo $foogallery_masonry_attributes; ?>>
19
+ <?php if ( 'fixed' !== $layout ) { ?>
20
+ <div class="fg-column-width"></div>
21
+ <div class="fg-gutter-width"></div>
22
+ <?php } ?>
23
  <?php foreach ( foogallery_current_gallery_attachments_for_rendering() as $attachment ) {
24
  echo foogallery_attachment_html( $attachment );
25
  } ?>
extensions/default-templates/shared/css/admin-foogallery.css CHANGED
@@ -57,39 +57,6 @@
57
  background-color: #eee;
58
  }
59
 
60
- .foogallery-setting-loading_icon .fg-loader {
61
- position: absolute;
62
- top: 50%;
63
- left: 50%;
64
- transform: translateX(-50%) translateY(-50%);
65
- width: 1em;
66
- height: 1em;
67
- font-size: 5px;
68
- }
69
-
70
- .foogallery-setting-loading_icon.fg-loading-bars .fg-loader {
71
- font-size: 4px;
72
- width: 1em;
73
- height: 4em;
74
- }
75
-
76
- .foogallery-setting-loading_icon.fg-loading-partial .fg-loader {
77
- font-size: 4px;
78
- width: 10em;
79
- height: 10em;
80
- }
81
-
82
- .foogallery-setting-loading_icon.fg-loading-pulse .fg-loader {
83
- font-size: 4px;
84
- width: 2.5em;
85
- height: 2.5em;
86
- transform: translateX(-50%) translateY(-150%);
87
- }
88
-
89
- .foogallery-setting-loading_icon.fg-loading-trail .fg-loader {
90
- font-size: 20px;
91
- }
92
-
93
  .fg-item-inner {
94
  margin: 0;
95
  }
57
  background-color: #eee;
58
  }
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  .fg-item-inner {
61
  margin: 0;
62
  }
extensions/default-templates/shared/css/foogallery.css CHANGED
@@ -21,6 +21,9 @@
21
  -ms-user-select: none;
22
  user-select: none;
23
  }
 
 
 
24
  .foogallery .fg-item-inner {
25
  display: block;
26
  position: relative;
@@ -298,12 +301,14 @@
298
  position: absolute;
299
  top: 50%;
300
  left: 50%;
301
- transform: translateX(-50%) translateY(-50%);
 
302
  width: 1em;
303
  height: 1em;
304
  font-size: 5px;
305
  visibility: hidden;
306
  opacity: 0;
 
307
  }
308
 
309
  .foogallery .fg-loading .fg-loader {
@@ -321,8 +326,12 @@
321
  -1.8em 1.8em 0 0 rgba(130, 130, 130, 0.2),
322
  -2.6em 0 0 0 rgba(130, 130, 130, 0.5),
323
  -1.8em -1.8em 0 0 rgba(130, 130, 130, 0.7);
324
- -webkit-animation: loading-default 1.1s infinite steps(8, start);
325
- animation: loading-default 1.1s infinite steps(8, start);
 
 
 
 
326
  }
327
 
328
  @-webkit-keyframes loading-default {
@@ -346,15 +355,23 @@
346
  .fg-loading-bars .fg-loader:before,
347
  .fg-loading-bars .fg-loader:after {
348
  background: rgba(130, 130, 130, 1);
349
- -webkit-animation: loading-bars 1s infinite ease-in-out;
350
- animation: loading-bars 1s infinite ease-in-out;
351
  width: 1em;
352
  height: 4em;
 
 
 
 
 
 
 
 
353
  }
354
  .fg-loading-bars .fg-loader {
355
  color: rgba(130, 130, 130, 1);
356
  text-indent: -9999em;
357
  font-size: 4px;
 
 
358
  -webkit-animation-delay: -0.16s;
359
  animation-delay: -0.16s;
360
  }
@@ -398,13 +415,20 @@
398
  }
399
  .fg-loading-trail .fg-loader {
400
  color: #828282;
 
 
401
  font-size: 20px;
402
  text-indent: -9999em;
403
  overflow: hidden;
404
  border-radius: 50%;
405
- -webkit-animation: loading-trail-1 1.7s infinite ease, loading-trail-2 1.7s infinite ease;
406
- animation: loading-trail-1 1.7s infinite ease, loading-trail-2 1.7s infinite ease;
407
  }
 
 
 
 
 
408
  @-webkit-keyframes loading-trail-1 {
409
  0% {
410
  box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;
@@ -475,16 +499,22 @@
475
  border-radius: 50%;
476
  width: 2.5em;
477
  height: 2.5em;
478
- -webkit-animation-fill-mode: both;
479
- animation-fill-mode: both;
480
- -webkit-animation: loading-pulse 1.8s infinite ease-in-out;
481
- animation: loading-pulse 1.8s infinite ease-in-out;
 
 
 
 
482
  }
 
483
  .fg-loading-pulse .fg-loader {
484
  color: #828282;
485
  font-size: 4px;
 
 
486
  text-indent: -9999em;
487
- transform: translateX(-50%) translateY(-150%);
488
  -webkit-animation-delay: -0.16s;
489
  animation-delay: -0.16s;
490
  }
@@ -527,9 +557,14 @@
527
  font-size: 5px;
528
  border-radius: 50%;
529
  text-indent: -9999em;
530
- -webkit-animation: loading-dots 1.3s infinite linear;
531
- animation: loading-dots 1.3s infinite linear;
 
 
 
 
532
  }
 
533
  @-webkit-keyframes loading-dots {
534
  0%,
535
  100% {
@@ -593,13 +628,20 @@
593
  .fg-loading-partial .fg-loader {
594
  font-size: 4px;
595
  text-indent: -9999em;
 
 
596
  border-top: 1.1em solid rgba(130,130,130, 0.2);
597
  border-right: 1.1em solid rgba(130,130,130, 0.2);
598
  border-bottom: 1.1em solid rgba(130,130,130, 0.2);
599
  border-left: 1.1em solid #828282;
600
- -webkit-animation: loading-partial 1.1s infinite linear;
601
- animation: loading-partial 1.1s infinite linear;
 
 
 
 
602
  }
 
603
  @-webkit-keyframes loading-partial {
604
  0% {
605
  -webkit-transform: translateX(-50%) translateY(-50%) rotate(0deg);
@@ -621,30 +663,30 @@
621
  }
622
  }
623
  /* Loaded Effects */
624
- .foogallery.fg-loaded-fade-in .fg-item,
625
- .foogallery.fg-loaded-slide-up .fg-item,
626
- .foogallery.fg-loaded-slide-down .fg-item,
627
- .foogallery.fg-loaded-slide-left .fg-item,
628
- .foogallery.fg-loaded-slide-right .fg-item,
629
- .foogallery.fg-loaded-scale-up .fg-item,
630
- .foogallery.fg-loaded-swing-down .fg-item,
631
- .foogallery.fg-loaded-drop .fg-item,
632
- .foogallery.fg-loaded-fly .fg-item,
633
- .foogallery.fg-loaded-flip .fg-item {
634
  transition-timing-function: ease;
635
  transition-duration: 650ms;
636
  transition-property: background-color, transform;
637
  }
638
- .foogallery.fg-loaded-fade-in .fg-item-inner,
639
- .foogallery.fg-loaded-slide-up .fg-item-inner,
640
- .foogallery.fg-loaded-slide-down .fg-item-inner,
641
- .foogallery.fg-loaded-slide-left .fg-item-inner,
642
- .foogallery.fg-loaded-slide-right .fg-item-inner,
643
- .foogallery.fg-loaded-scale-up .fg-item-inner,
644
- .foogallery.fg-loaded-swing-down .fg-item-inner,
645
- .foogallery.fg-loaded-drop .fg-item-inner,
646
- .foogallery.fg-loaded-fly .fg-item-inner,
647
- .foogallery.fg-loaded-flip .fg-item-inner {
648
  transition-timing-function: ease;
649
  transition-duration: 650ms;
650
  }
@@ -655,10 +697,89 @@
655
  .foogallery.fg-loaded-flip .fg-item.fg-loaded {
656
  perspective: 1300px;
657
  }
 
 
 
 
 
 
 
 
 
658
  /* Fade In */
659
  .foogallery.fg-loaded-fade-in .fg-item-inner {
660
  transition-property: visibility, opacity;
661
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
  /* Caption Styles */
663
  .foogallery .fg-caption {
664
  visibility: hidden;
@@ -712,6 +833,8 @@
712
  transition-property: visibility, opacity;
713
  visibility: visible;
714
  opacity: 1;
 
 
715
  text-align: left;
716
  }
717
 
@@ -727,6 +850,24 @@
727
  .foogallery.fg-caption-hover .fg-item.fg-loaded .fg-image-overlay {
728
  display: none;
729
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
730
  /* Icon & Overlay */
731
  .foogallery .fg-image-overlay:before {
732
  content: "";
@@ -747,7 +888,7 @@
747
  position: relative;
748
  width: 32px;
749
  height: 32px;
750
- margin: 10px 0 5px 0;
751
  background-size: 32px 32px;
752
  vertical-align: middle;
753
  background-position: center center;
@@ -766,7 +907,7 @@
766
  .foogallery.fg-video-2:not(.fg-preset) .fg-caption-inner:before,
767
  .foogallery.fg-video-3:not(.fg-preset) .fg-caption-inner:before,
768
  .foogallery.fg-video-4:not(.fg-preset) .fg-caption-inner:before {
769
- display: inline-block;
770
  }
771
 
772
  .foogallery.fg-hover-zoom:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,
@@ -903,30 +1044,30 @@
903
  background-image: url('../img/icons.svg#video-4-dark');
904
  }
905
  /* Transitions */
906
- .foogallery.fg-caption-hover.fg-hover-instant .fg-caption,
907
- .foogallery.fg-caption-hover.fg-hover-fade .fg-caption,
908
- .foogallery.fg-caption-hover.fg-hover-slide-up .fg-caption,
909
- .foogallery.fg-caption-hover.fg-hover-slide-down .fg-caption,
910
- .foogallery.fg-caption-hover.fg-hover-slide-left .fg-caption,
911
- .foogallery.fg-caption-hover.fg-hover-slide-right .fg-caption,
912
- .foogallery.fg-caption-hover.fg-hover-push .fg-caption,
913
- .foogallery.fg-caption-hover.fg-hover-colorize .fg-caption,
914
- .foogallery.fg-caption-hover.fg-hover-grayscale .fg-caption,
915
- .foogallery.fg-caption-hover.fg-hover-scale .fg-caption,
916
- .foogallery.fg-hover-instant .fg-image-overlay,
917
- .foogallery.fg-hover-fade .fg-image-overlay,
918
- .foogallery.fg-hover-slide-up .fg-image-overlay,
919
- .foogallery.fg-hover-slide-down .fg-image-overlay,
920
- .foogallery.fg-hover-slide-left .fg-image-overlay,
921
- .foogallery.fg-hover-slide-right .fg-image-overlay,
922
- .foogallery.fg-hover-push .fg-thumb,
923
- .foogallery.fg-hover-colorize .fg-image-overlay,
924
- .foogallery.fg-hover-grayscale .fg-image-overlay,
925
- .foogallery.fg-hover-scale .fg-item,
926
- .foogallery.fg-hover-scale .fg-image-overlay,
927
- .foogallery.fg-hover-zoomed .fg-image,
928
- .foogallery.fg-hover-colorize .fg-image,
929
- .foogallery.fg-hover-grayscale .fg-image {
930
  transition-timing-function: ease;
931
  transition-duration: 300ms;
932
  backface-visibility: hidden;
@@ -1145,6 +1286,158 @@
1145
  .fg-paging-container {
1146
  display: block;
1147
  padding: 15px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1148
  text-align: center;
1149
  font-family: -apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
1150
  -webkit-user-select: none;
@@ -1163,6 +1456,13 @@
1163
  clip: rect(0,0,0,0);
1164
  border: 0;
1165
  }
 
 
 
 
 
 
 
1166
  .fg-paging-container .fg-dots,
1167
  .fg-paging-container .fg-dot-item {
1168
  display: inline-block;
@@ -1283,10 +1583,14 @@
1283
  clear: both;
1284
  }
1285
 
1286
- .fg-default .fg-item,
 
 
 
 
1287
  .fg-default .fg-item-inner,
1288
  .fg-default .fg-thumb {
1289
- display: inline-block;
1290
  vertical-align: top;
1291
  max-width: 100%;
1292
  }
@@ -1362,34 +1666,132 @@
1362
  margin-right: 25px;
1363
  margin-bottom: 25px;
1364
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1365
  /* Base styles */
1366
  .fg-masonry * {
1367
  box-sizing: border-box;
1368
  }
1369
- .foogallery.fg-masonry.fg-center {
1370
  margin: 0 auto;
 
1371
  }
1372
  .fg-masonry .fg-thumb {
1373
  display: block;
1374
  }
1375
- .fg-masonry.fg-masonry-fixed .fg-thumb {
1376
  display: inline-block;
1377
  }
1378
- .fg-masonry.fg-masonry-fixed .fg-image {
 
 
1379
  max-width: 100%;
1380
  }
1381
 
1382
  .fg-masonry .fg-column-width {
1383
  display: inline-block;
1384
- visibility: hidden;
1385
- height: 0;
1386
  border: solid 0 transparent;
1387
  }
 
 
 
 
 
 
 
 
1388
 
1389
- .fg-masonry.fg-masonry-5col .fg-image,
1390
- .fg-masonry.fg-masonry-4col .fg-image,
1391
- .fg-masonry.fg-masonry-3col .fg-image,
1392
- .fg-masonry.fg-masonry-2col .fg-image {
 
1393
  width: 100%;
1394
  height: auto;
1395
  max-width: 100%;
@@ -1398,183 +1800,268 @@
1398
  .fg-masonry .fg-item {
1399
  line-height: 0;
1400
  font-size: 0;
1401
- }
1402
- .fg-masonry.fg-masonry-fixed .fg-item,
1403
- .fg-masonry.fg-masonry-fixed .fg-column-width {
1404
- max-width: 100%;
1405
  }
1406
 
1407
  /* 2 column layouts */
1408
  /* 2 column layout - normal gutter */
1409
- .fg-masonry.fg-masonry-2col .fg-item { margin-bottom: 1%; width: 49%; }
1410
- .fg-masonry.fg-masonry-2col .fg-column-width { width: 49%; }
1411
- .fg-masonry.fg-masonry-2col .fg-gutter-width { width: 1%; }
1412
 
1413
  /* 2 column layout - no gutter */
1414
- .fg-masonry.fg-masonry-2col.fg-gutter-none .fg-item { margin-bottom: 0; width: 50%; }
1415
- .fg-masonry.fg-masonry-2col.fg-gutter-none .fg-column-width { width: 50%; }
1416
- .fg-masonry.fg-masonry-2col.fg-gutter-none .fg-gutter-width { width: 0; }
1417
 
1418
  /* 2 column layout - large gutter */
1419
- .fg-masonry.fg-masonry-2col.fg-gutter-large .fg-item { margin-bottom: 3%; width: 47%; }
1420
- .fg-masonry.fg-masonry-2col.fg-gutter-large .fg-column-width { width: 47%; }
1421
- .fg-masonry.fg-masonry-2col.fg-gutter-large .fg-gutter-width { width: 3%; }
1422
 
1423
  /* 3 column layouts */
1424
  /* 3 column layout - normal gutter */
1425
- .fg-masonry.fg-masonry-3col .fg-item { margin-bottom: 1%; width: 32%; }
1426
- .fg-masonry.fg-masonry-3col .fg-column-width { width: 32%; }
1427
- .fg-masonry.fg-masonry-3col .fg-gutter-width { width: 1%; }
1428
 
1429
  /* 3 column layout - no gutter */
1430
- .fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item { margin-bottom: 0; width: 33%; }
1431
- .fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width { width: 33%; }
1432
- .fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width { width: 0; }
1433
 
1434
  /* 3 column layout - large gutter */
1435
- .fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item { margin-bottom: 3%; width: 30%; }
1436
- .fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width { width: 30%; }
1437
- .fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width { width: 3%; }
1438
 
1439
  /* 4 column layouts */
1440
  /* 4 column layout - normal gutter */
1441
- .fg-masonry.fg-masonry-4col .fg-item { margin-bottom: 1%; width: 24%; }
1442
- .fg-masonry.fg-masonry-4col .fg-column-width { width: 24%; }
1443
- .fg-masonry.fg-masonry-4col .fg-gutter-width { width: 1%; }
1444
 
1445
  /* 4 column layout - no gutter */
1446
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item { margin-bottom: 0; width: 25%; }
1447
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width { width: 25%; }
1448
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width { width: 0; }
1449
 
1450
  /* 4 column layout - large gutter */
1451
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item { margin-bottom: 3%; width: 22%; }
1452
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width { width: 22%; }
1453
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width { width: 3%; }
1454
 
1455
  /* 5 column layouts */
1456
  /* 5 column layout - normal gutter */
1457
- .fg-masonry.fg-masonry-5col .fg-item { margin-bottom: 1%; width: 19%; }
1458
- .fg-masonry.fg-masonry-5col .fg-column-width { width: 19%; }
1459
- .fg-masonry.fg-masonry-5col .fg-gutter-width { width: 1%; }
1460
 
1461
  /* 5 column layout - no gutter */
1462
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item { margin-bottom: 0; width: 20%; }
1463
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width { width: 20%; }
1464
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width { width: 0; }
1465
 
1466
  /* 5 column layout - large gutter */
1467
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item { margin-bottom: 3%; width: 17%; }
1468
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width { width: 17%; }
1469
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width { width: 3%; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1470
 
1471
  /* Force 3 column layout < 720px */
1472
  @media screen and (max-width: 720px) {
1473
  /* default gutter */
1474
- .fg-masonry.fg-masonry-5col .fg-item,
1475
- .fg-masonry.fg-masonry-4col .fg-item { margin-bottom: 1%; width: 32%; }
1476
- .fg-masonry.fg-masonry-5col .fg-column-width,
1477
- .fg-masonry.fg-masonry-4col .fg-column-width { width: 32%; }
1478
- .fg-masonry.fg-masonry-5col .fg-gutter-width,
1479
- .fg-masonry.fg-masonry-4col .fg-gutter-width { width: 1%; }
 
 
 
1480
 
1481
  /* no gutter */
1482
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item,
1483
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item { margin-bottom: 0; width: 33%; }
1484
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width,
1485
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width { width: 33%; }
1486
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width,
1487
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width { width: 0; }
 
 
 
1488
 
1489
  /* large gutter */
1490
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item,
1491
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item { margin-bottom: 3%; width: 30%; }
1492
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width,
1493
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width { width: 30%; }
1494
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width,
1495
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width { width: 3%; }
 
 
 
1496
 
1497
  }
1498
 
1499
  /* Force 2 column layout < 480px */
1500
  @media screen and (max-width: 480px) {
1501
  /* default gutter */
1502
- .fg-masonry.fg-masonry-5col .fg-item,
1503
- .fg-masonry.fg-masonry-4col .fg-item,
1504
- .fg-masonry.fg-masonry-3col .fg-item { margin-bottom: 1%; width: 49%; }
1505
- .fg-masonry.fg-masonry-5col .fg-column-width,
1506
- .fg-masonry.fg-masonry-4col .fg-column-width,
1507
- .fg-masonry.fg-masonry-3col .fg-column-width { width: 49%; }
1508
- .fg-masonry.fg-masonry-5col .fg-gutter-width,
1509
- .fg-masonry.fg-masonry-4col .fg-gutter-width,
1510
- .fg-masonry.fg-masonry-3col .fg-gutter-width { width: 1%; }
 
 
 
1511
 
1512
  /* no gutter */
1513
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item,
1514
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,
1515
- .fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item { margin-bottom: 0; width: 50%; }
1516
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width,
1517
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,
1518
- .fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width { width: 50%; }
1519
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width,
1520
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,
1521
- .fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width { width: 0; }
 
 
 
1522
 
1523
  /* large gutter */
1524
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item,
1525
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,
1526
- .fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item { margin-bottom: 3%; width: 47%; }
1527
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width,
1528
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,
1529
- .fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width { width: 47%; }
1530
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width,
1531
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,
1532
- .fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width { width: 3%; }
 
 
 
1533
  }
1534
 
1535
  /* Force 1 column layout < 320px */
1536
  @media screen and (max-width: 320px) {
1537
  /* default gutter */
1538
- .fg-masonry.fg-masonry-5col .fg-item,
1539
- .fg-masonry.fg-masonry-4col .fg-item,
1540
- .fg-masonry.fg-masonry-3col .fg-item,
1541
- .fg-masonry.fg-masonry-2col .fg-item { margin-bottom: 1%; width: 100%; }
1542
- .fg-masonry.fg-masonry-5col .fg-column-width,
1543
- .fg-masonry.fg-masonry-4col .fg-column-width,
1544
- .fg-masonry.fg-masonry-3col .fg-column-width,
1545
- .fg-masonry.fg-masonry-2col .fg-column-width { width: 100%; }
1546
- .fg-masonry.fg-masonry-5col .fg-gutter-width,
1547
- .fg-masonry.fg-masonry-4col .fg-gutter-width,
1548
- .fg-masonry.fg-masonry-3col .fg-gutter-width,
1549
- .fg-masonry.fg-masonry-2col .fg-gutter-width { width: 0; }
 
 
 
1550
 
1551
  /* no gutter */
1552
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item,
1553
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,
1554
- .fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item,
1555
- .fg-masonry.fg-masonry-2col.fg-gutter-none .fg-item { margin-bottom: 0; width: 100%; }
1556
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width,
1557
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,
1558
- .fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width,
1559
- .fg-masonry.fg-masonry-2col.fg-gutter-none .fg-column-width { width: 100%; }
1560
- .fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width,
1561
- .fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,
1562
- .fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width,
1563
- .fg-masonry.fg-masonry-2col.fg-gutter-none .fg-gutter-width { width: 0; }
 
 
 
1564
 
1565
  /* large gutter */
1566
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item,
1567
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,
1568
- .fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item,
1569
- .fg-masonry.fg-masonry-2col.fg-gutter-large .fg-item { margin-bottom: 3%; width: 100%; }
1570
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width,
1571
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,
1572
- .fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width,
1573
- .fg-masonry.fg-masonry-2col.fg-gutter-large .fg-column-width { width: 100%; }
1574
- .fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width,
1575
- .fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,
1576
- .fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width,
1577
- .fg-masonry.fg-masonry-2col.fg-gutter-large .fg-gutter-width { width: 0; }
 
 
 
1578
  }
1579
 
1580
  /* Border Styles - We must apply width changing border styles to the fg-column-width element so that the plugin can correctly determine the item widths. */
@@ -1607,6 +2094,19 @@
1607
  background-color: transparent;
1608
  border-style: solid;
1609
  border-color: transparent;
 
 
 
 
 
 
 
 
 
 
 
 
 
1610
  }
1611
  .foogallery.fg-masonry.fg-captions-bottom .fg-item-inner:hover .fg-caption {
1612
  transform: none;
@@ -1637,10 +2137,6 @@
1637
  opacity: 1;
1638
  }
1639
 
1640
- .fg-masonry.fg-captions-bottom .fg-caption-title,
1641
- .fg-masonry.fg-captions-bottom .fg-caption-desc {
1642
- text-align: left;
1643
- }
1644
  .fg-masonry.fg-captions-bottom.fg-light .fg-caption,
1645
  .fg-masonry.fg-captions-bottom.fg-dark .fg-caption {
1646
  color: #828282;
@@ -1791,8 +2287,14 @@
1791
  .fg-justified {
1792
  box-sizing: border-box;
1793
  position: relative;
 
 
 
 
 
 
 
1794
  }
1795
- .foogallery.fg-justified .fg-item,
1796
  .foogallery.fg-justified .fg-item-inner,
1797
  .foogallery.fg-justified .fg-thumb,
1798
  .foogallery.fg-justified .fg-image {
@@ -1803,7 +2305,7 @@
1803
  }
1804
  .fg-justified .fg-item {
1805
  visibility: visible;
1806
- position: absolute;
1807
  }
1808
  .fg-justified .fg-item-inner {
1809
  position: relative;
@@ -1823,14 +2325,50 @@
1823
  height: 100%;
1824
  }
1825
  .fg-justified .fg-item.fg-positioned .fg-image {
1826
- width: 100%;
1827
- height: auto;
1828
  min-height: 100%;
1829
- top: 50%;
1830
- transform: translateY(-50%);
1831
  }
1832
- .fg-justified.fg-hover-zoomed .fg-item.fg-positioned:hover .fg-image {
1833
- transform: translateY(-50%) scale(1.15);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1834
  }
1835
  .fg-simple_portfolio {
1836
  display: flex;
@@ -1841,10 +2379,11 @@
1841
  }
1842
  .fg-simple_portfolio .fg-item {
1843
  position: relative;
1844
- flex: 1;
 
 
1845
  margin: 10px;
1846
- min-width: 250px;
1847
- max-width: 250px;
1848
  }
1849
  .fg-simple_portfolio .fg-item-inner {
1850
  display: flex;
@@ -1885,6 +2424,19 @@
1885
  background-color: transparent;
1886
  border-style: solid;
1887
  border-color: transparent;
 
 
 
 
 
 
 
 
 
 
 
 
 
1888
  }
1889
  .foogallery.fg-simple_portfolio .fg-item-inner:hover .fg-caption {
1890
  transform: none;
@@ -1912,13 +2464,10 @@
1912
  visibility: visible;
1913
  opacity: 1;
1914
  }
1915
-
1916
  .fg-simple_portfolio .fg-caption-title {
1917
- text-align: left;
1918
- }
1919
- .fg-simple_portfolio .fg-caption-desc {
1920
- text-align: left;
1921
  }
 
1922
  .fg-simple_portfolio.fg-light .fg-caption,
1923
  .fg-simple_portfolio.fg-dark .fg-caption {
1924
  color: #828282;
@@ -2294,51 +2843,11 @@
2294
  margin: 0 4px;
2295
  }
2296
 
2297
- /*!* Theme - Default (Light) *!*/
2298
- /*.fg-image-viewer .fiv-inner,*/
2299
- /*.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev,*/
2300
- /*.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next {*/
2301
- /*background-color: #FFFFFF;*/
2302
- /*color: #1b1b1b;*/
2303
- /*}*/
2304
- /*.fg-image-viewer .fiv-inner,*/
2305
- /*.fg-image-viewer .fiv-inner .fiv-inner-container,*/
2306
- /*.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev,*/
2307
- /*.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next {*/
2308
- /*border-color: #e6e6e6;*/
2309
- /*}*/
2310
- /*.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:hover,*/
2311
- /*.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:hover {*/
2312
- /*background-color: #F2F2F2;*/
2313
- /*}*/
2314
-
2315
- /*!* Theme - Dark *!*/
2316
- /*.fg-image-viewer.fiv-dark .fiv-inner,*/
2317
- /*.fg-image-viewer.fiv-dark .fiv-inner .fiv-ctrls .fiv-prev,*/
2318
- /*.fg-image-viewer.fiv-dark .fiv-inner .fiv-ctrls .fiv-next {*/
2319
- /*background-color: #151515;*/
2320
- /*color: #FFFFFF;*/
2321
- /*}*/
2322
- /*.fg-image-viewer.fiv-dark .fiv-inner,*/
2323
- /*.fg-image-viewer.fiv-dark .fiv-inner .fiv-inner-container,*/
2324
- /*.fg-image-viewer.fiv-dark .fiv-inner .fiv-ctrls .fiv-prev,*/
2325
- /*.fg-image-viewer.fiv-dark .fiv-inner .fiv-ctrls .fiv-next {*/
2326
- /*border-color: #2E2E2E;*/
2327
- /*}*/
2328
- /*.fg-image-viewer.fiv-dark .fiv-inner .fiv-ctrls .fiv-prev:hover,*/
2329
- /*.fg-image-viewer.fiv-dark .fiv-inner .fiv-ctrls .fiv-next:hover {*/
2330
- /*background-color: #000000;*/
2331
- /*}*/
2332
-
2333
  /* Captions */
2334
 
2335
  .foogallery.fg-image-viewer.fg-caption-always .fg-item-inner .fg-caption {
2336
  padding: 0;
2337
  border: none;
2338
- background: #000; /* Old browsers */
2339
- background: -moz-linear-gradient(left, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.8) 60%, rgba(0,0,0,0) 100%); /* FF3.6-15 */
2340
- background: -webkit-linear-gradient(left, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.8) 60%,rgba(0,0,0,0) 100%); /* Chrome10-25,Safari5.1-6 */
2341
- background: linear-gradient(to right, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.8) 60%,rgba(0,0,0,0) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
2342
  }
2343
  .foogallery.fg-image-viewer.fg-caption-always .fg-caption-title {
2344
  padding: 10px 10px 10px 10px;
21
  -ms-user-select: none;
22
  user-select: none;
23
  }
24
+ .foogallery .fg-item.fg-hidden {
25
+ display: none!important;
26
+ }
27
  .foogallery .fg-item-inner {
28
  display: block;
29
  position: relative;
301
  position: absolute;
302
  top: 50%;
303
  left: 50%;
304
+ margin-top: -0.5em;
305
+ margin-left: -0.5em;
306
  width: 1em;
307
  height: 1em;
308
  font-size: 5px;
309
  visibility: hidden;
310
  opacity: 0;
311
+ pointer-events: none;
312
  }
313
 
314
  .foogallery .fg-loading .fg-loader {
326
  -1.8em 1.8em 0 0 rgba(130, 130, 130, 0.2),
327
  -2.6em 0 0 0 rgba(130, 130, 130, 0.5),
328
  -1.8em -1.8em 0 0 rgba(130, 130, 130, 0.7);
329
+ -webkit-animation: loading-default 1.1s infinite paused steps(8, start);
330
+ animation: loading-default 1.1s infinite paused steps(8, start);
331
+ }
332
+ .fg-loading-default .fg-loading .fg-loader {
333
+ -webkit-animation-play-state: running;
334
+ animation-play-state: running;
335
  }
336
 
337
  @-webkit-keyframes loading-default {
355
  .fg-loading-bars .fg-loader:before,
356
  .fg-loading-bars .fg-loader:after {
357
  background: rgba(130, 130, 130, 1);
 
 
358
  width: 1em;
359
  height: 4em;
360
+ -webkit-animation: loading-bars 1s infinite paused ease-in-out;
361
+ animation: loading-bars 1s infinite paused ease-in-out;
362
+ }
363
+ .fg-loading-bars .fg-loading .fg-loader,
364
+ .fg-loading-bars .fg-loading .fg-loader:before,
365
+ .fg-loading-bars .fg-loading .fg-loader:after {
366
+ -webkit-animation-play-state: running;
367
+ animation-play-state: running;
368
  }
369
  .fg-loading-bars .fg-loader {
370
  color: rgba(130, 130, 130, 1);
371
  text-indent: -9999em;
372
  font-size: 4px;
373
+ margin-top: -2em;
374
+ margin-left: -0.5em;
375
  -webkit-animation-delay: -0.16s;
376
  animation-delay: -0.16s;
377
  }
415
  }
416
  .fg-loading-trail .fg-loader {
417
  color: #828282;
418
+ margin-top: 0;
419
+ margin-left: 0;
420
  font-size: 20px;
421
  text-indent: -9999em;
422
  overflow: hidden;
423
  border-radius: 50%;
424
+ -webkit-animation: loading-trail-1 1.7s infinite paused ease, loading-trail-2 1.7s infinite paused ease;
425
+ animation: loading-trail-1 1.7s infinite paused ease, loading-trail-2 1.7s infinite paused ease;
426
  }
427
+ .fg-loading-trail .fg-loading .fg-loader {
428
+ -webkit-animation-play-state: running;
429
+ animation-play-state: running;
430
+ }
431
+
432
  @-webkit-keyframes loading-trail-1 {
433
  0% {
434
  box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em;
499
  border-radius: 50%;
500
  width: 2.5em;
501
  height: 2.5em;
502
+ -webkit-animation: loading-pulse 1.8s infinite both paused ease-in-out;
503
+ animation: loading-pulse 1.8s infinite both paused ease-in-out;
504
+ }
505
+ .fg-loading-pulse .fg-loading .fg-loader,
506
+ .fg-loading-pulse .fg-loading .fg-loader:before,
507
+ .fg-loading-pulse .fg-loading .fg-loader:after {
508
+ -webkit-animation-play-state: running;
509
+ animation-play-state: running;
510
  }
511
+
512
  .fg-loading-pulse .fg-loader {
513
  color: #828282;
514
  font-size: 4px;
515
+ margin-top: -3.75em;
516
+ margin-left: -1.25em;
517
  text-indent: -9999em;
 
518
  -webkit-animation-delay: -0.16s;
519
  animation-delay: -0.16s;
520
  }
557
  font-size: 5px;
558
  border-radius: 50%;
559
  text-indent: -9999em;
560
+ -webkit-animation: loading-dots 1.3s infinite paused linear;
561
+ animation: loading-dots 1.3s infinite paused linear;
562
+ }
563
+ .fg-loading-dots .fg-loading .fg-loader {
564
+ -webkit-animation-play-state: running;
565
+ animation-play-state: running;
566
  }
567
+
568
  @-webkit-keyframes loading-dots {
569
  0%,
570
  100% {
628
  .fg-loading-partial .fg-loader {
629
  font-size: 4px;
630
  text-indent: -9999em;
631
+ margin-top: 0;
632
+ margin-left: 0;
633
  border-top: 1.1em solid rgba(130,130,130, 0.2);
634
  border-right: 1.1em solid rgba(130,130,130, 0.2);
635
  border-bottom: 1.1em solid rgba(130,130,130, 0.2);
636
  border-left: 1.1em solid #828282;
637
+ -webkit-animation: loading-partial 1.1s infinite paused linear;
638
+ animation: loading-partial 1.1s infinite paused linear;
639
+ }
640
+ .fg-loading-partial .fg-loading .fg-loader {
641
+ -webkit-animation-play-state: running;
642
+ animation-play-state: running;
643
  }
644
+
645
  @-webkit-keyframes loading-partial {
646
  0% {
647
  -webkit-transform: translateX(-50%) translateY(-50%) rotate(0deg);
663
  }
664
  }
665
  /* Loaded Effects */
666
+ .foogallery.fg-loaded-fade-in .fg-item.fg-loaded,
667
+ .foogallery.fg-loaded-slide-up .fg-item.fg-loaded,
668
+ .foogallery.fg-loaded-slide-down .fg-item.fg-loaded,
669
+ .foogallery.fg-loaded-slide-left .fg-item.fg-loaded,
670
+ .foogallery.fg-loaded-slide-right .fg-item.fg-loaded,
671
+ .foogallery.fg-loaded-scale-up .fg-item.fg-loaded,
672
+ .foogallery.fg-loaded-swing-down .fg-item.fg-loaded,
673
+ .foogallery.fg-loaded-drop .fg-item.fg-loaded,
674
+ .foogallery.fg-loaded-fly .fg-item.fg-loaded,
675
+ .foogallery.fg-loaded-flip .fg-item.fg-loaded {
676
  transition-timing-function: ease;
677
  transition-duration: 650ms;
678
  transition-property: background-color, transform;
679
  }
680
+ .foogallery.fg-loaded-fade-in .fg-loaded .fg-item-inner,
681
+ .foogallery.fg-loaded-slide-up .fg-loaded .fg-item-inner,
682
+ .foogallery.fg-loaded-slide-down .fg-loaded .fg-item-inner,
683
+ .foogallery.fg-loaded-slide-left .fg-loaded .fg-item-inner,
684
+ .foogallery.fg-loaded-slide-right .fg-loaded .fg-item-inner,
685
+ .foogallery.fg-loaded-scale-up .fg-loaded .fg-item-inner,
686
+ .foogallery.fg-loaded-swing-down .fg-loaded .fg-item-inner,
687
+ .foogallery.fg-loaded-drop .fg-loaded .fg-item-inner,
688
+ .foogallery.fg-loaded-fly .fg-loaded .fg-item-inner,
689
+ .foogallery.fg-loaded-flip .fg-loaded .fg-item-inner {
690
  transition-timing-function: ease;
691
  transition-duration: 650ms;
692
  }
697
  .foogallery.fg-loaded-flip .fg-item.fg-loaded {
698
  perspective: 1300px;
699
  }
700
+ /* Drop */
701
+ .foogallery.fg-loaded-drop .fg-item-inner {
702
+ transition-property: visibility, opacity, transform;
703
+ transform-style: preserve-3d;
704
+ transform: translateZ(400px) translateY(100%) rotateX(-90deg);
705
+ }
706
+ .foogallery.fg-loaded-drop .fg-loaded .fg-item-inner {
707
+ transform: translateZ(0px) translateY(0px) rotateX(0deg);
708
+ }
709
  /* Fade In */
710
  .foogallery.fg-loaded-fade-in .fg-item-inner {
711
  transition-property: visibility, opacity;
712
  }
713
+ /* Flip */
714
+ .foogallery.fg-loaded-flip .fg-item-inner {
715
+ transition-property: visibility, opacity, transform;
716
+ backface-visibility: hidden;
717
+ transform-style: preserve-3d;
718
+ transform: rotateY(-180deg);
719
+ }
720
+ .foogallery.fg-loaded-flip .fg-loaded .fg-item-inner {
721
+ transform: rotateY(0deg);
722
+ }
723
+ /* Fly */
724
+ .foogallery.fg-loaded-fly .fg-item-inner {
725
+ transition-property: visibility, opacity, transform;
726
+ transform-style: preserve-3d;
727
+ transform-origin: 50% 50% -300px;
728
+ transform: rotateX(-180deg);
729
+ }
730
+ .foogallery.fg-loaded-fly .fg-loaded .fg-item-inner {
731
+ transform: rotateX(0deg);
732
+ }
733
+ /* Scale Up */
734
+ .foogallery.fg-loaded-scale-up .fg-item-inner {
735
+ transition-property: visibility, opacity, transform;
736
+ transform: scale(0.6);
737
+ }
738
+ .foogallery.fg-loaded-scale-up .fg-loaded .fg-item-inner {
739
+ transform: scale(1);
740
+ }
741
+ /* Slide Up */
742
+ .foogallery.fg-loaded-slide-up .fg-item-inner {
743
+ transition-property: visibility, opacity, transform;
744
+ transform: translateY(50%);
745
+ }
746
+ .foogallery.fg-loaded-slide-up .fg-loaded .fg-item-inner {
747
+ transform: translateY(0);
748
+ }
749
+ /* Slide Down */
750
+ .foogallery.fg-loaded-slide-down .fg-item-inner {
751
+ transition-property: visibility, opacity, transform;
752
+ transform: translateY(-50%);
753
+ }
754
+ .foogallery.fg-loaded-slide-down .fg-loaded .fg-item-inner {
755
+ transform: translateY(0);
756
+ }
757
+ /* Slide Left */
758
+ .foogallery.fg-loaded-slide-left .fg-item-inner {
759
+ transition-property: visibility, opacity, transform;
760
+ transform: translateX(50%);
761
+ }
762
+ .foogallery.fg-loaded-slide-left .fg-loaded .fg-item-inner {
763
+ transform: translateX(0);
764
+ }
765
+ /* Slide Right */
766
+ .foogallery.fg-loaded-slide-right .fg-item-inner {
767
+ transition-property: visibility, opacity, transform;
768
+ transform: translateX(-50%);
769
+ }
770
+ .foogallery.fg-loaded-slide-right .fg-loaded .fg-item-inner {
771
+ transform: translateX(0);
772
+ }
773
+ /* Swing Down */
774
+ .foogallery.fg-loaded-swing-down .fg-item-inner {
775
+ transition-property: visibility, opacity, transform;
776
+ transform-style: preserve-3d;
777
+ transform-origin: 0 0;
778
+ transform: rotateX(-80deg);
779
+ }
780
+ .foogallery.fg-loaded-swing-down .fg-loaded .fg-item-inner {
781
+ transform: rotateX(0deg);
782
+ }
783
  /* Caption Styles */
784
  .foogallery .fg-caption {
785
  visibility: hidden;
833
  transition-property: visibility, opacity;
834
  visibility: visible;
835
  opacity: 1;
836
+ }
837
+ .foogallery.fg-caption-always .fg-caption {
838
  text-align: left;
839
  }
840
 
850
  .foogallery.fg-caption-hover .fg-item.fg-loaded .fg-image-overlay {
851
  display: none;
852
  }
853
+
854
+ /* Alignment */
855
+ .foogallery.fg-c-l .fg-caption,
856
+ .foogallery.fg-caption-always.fg-c-l .fg-caption {
857
+ text-align: left;
858
+ }
859
+ .foogallery.fg-c-c .fg-caption,
860
+ .foogallery.fg-caption-always.fg-c-c .fg-caption {
861
+ text-align: center;
862
+ }
863
+ .foogallery.fg-c-r .fg-caption,
864
+ .foogallery.fg-caption-always.fg-c-r .fg-caption {
865
+ text-align: right;
866
+ }
867
+ .foogallery.fg-c-j .fg-caption,
868
+ .foogallery.fg-caption-always.fg-c-j .fg-caption {
869
+ text-align: justify;
870
+ }
871
  /* Icon & Overlay */
872
  .foogallery .fg-image-overlay:before {
873
  content: "";
888
  position: relative;
889
  width: 32px;
890
  height: 32px;
891
+ margin: 10px auto 5px auto;
892
  background-size: 32px 32px;
893
  vertical-align: middle;
894
  background-position: center center;
907
  .foogallery.fg-video-2:not(.fg-preset) .fg-caption-inner:before,
908
  .foogallery.fg-video-3:not(.fg-preset) .fg-caption-inner:before,
909
  .foogallery.fg-video-4:not(.fg-preset) .fg-caption-inner:before {
910
+ display: block;
911
  }
912
 
913
  .foogallery.fg-hover-zoom:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,
1044
  background-image: url('../img/icons.svg#video-4-dark');
1045
  }
1046
  /* Transitions */
1047
+ .foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-caption,
1048
+ .foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-caption,
1049
+ .foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,
1050
+ .foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,
1051
+ .foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,
1052
+ .foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,
1053
+ .foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,
1054
+ .foogallery.fg-caption-hover.fg-hover-colorize .fg-loaded .fg-caption,
1055
+ .foogallery.fg-caption-hover.fg-hover-grayscale .fg-loaded .fg-caption,
1056
+ .foogallery.fg-caption-hover.fg-hover-scale .fg-loaded .fg-caption,
1057
+ .foogallery.fg-hover-instant .fg-loaded .fg-image-overlay,
1058
+ .foogallery.fg-hover-fade .fg-loaded .fg-image-overlay,
1059
+ .foogallery.fg-hover-slide-up .fg-loaded .fg-image-overlay,
1060
+ .foogallery.fg-hover-slide-down .fg-loaded .fg-image-overlay,
1061
+ .foogallery.fg-hover-slide-left .fg-loaded .fg-image-overlay,
1062
+ .foogallery.fg-hover-slide-right .fg-loaded .fg-image-overlay,
1063
+ .foogallery.fg-hover-push .fg-loaded .fg-thumb,
1064
+ .foogallery.fg-hover-colorize .fg-loaded .fg-image-overlay,
1065
+ .foogallery.fg-hover-grayscale .fg-loaded .fg-image-overlay,
1066
+ .foogallery.fg-hover-scale .fg-item.fg-loaded,
1067
+ .foogallery.fg-hover-scale .fg-loaded .fg-image-overlay,
1068
+ .foogallery.fg-hover-zoomed .fg-loaded .fg-image,
1069
+ .foogallery.fg-hover-colorize .fg-loaded .fg-image,
1070
+ .foogallery.fg-hover-grayscale .fg-loaded .fg-image {
1071
  transition-timing-function: ease;
1072
  transition-duration: 300ms;
1073
  backface-visibility: hidden;
1286
  .fg-paging-container {
1287
  display: block;
1288
  padding: 15px;
1289
+ margin-top: 0!important;
1290
+ margin-bottom: 0!important;
1291
+ margin-left: auto;
1292
+ margin-right: auto;
1293
+ text-align: center;
1294
+ font-family: -apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
1295
+ -webkit-user-select: none;
1296
+ -moz-user-select: none;
1297
+ -ms-user-select: none;
1298
+ user-select: none;
1299
+ }
1300
+ /* Utility */
1301
+ .fg-sr-only {
1302
+ position: absolute;
1303
+ width: 1px;
1304
+ height: 1px;
1305
+ padding: 0;
1306
+ margin: -1px;
1307
+ overflow: hidden;
1308
+ clip: rect(0,0,0,0);
1309
+ border: 0;
1310
+ }
1311
+ .fg-ph-dots:after {
1312
+ display: block;
1313
+ content: '';
1314
+ width: 0;
1315
+ height: 22px;
1316
+ }
1317
+
1318
+ .fg-paging-container .fg-dots,
1319
+ .fg-paging-container .fg-dot-item {
1320
+ display: inline-block;
1321
+ margin: 0;
1322
+ padding: 0;
1323
+ outline: none;
1324
+ list-style: none;
1325
+ }
1326
+ .fg-paging-container .fg-dot-item .fg-dot-link {
1327
+ display: inline-block;
1328
+ margin: 3px;
1329
+ font-weight: 400;
1330
+ line-height: 1.42857143;
1331
+ text-align: center;
1332
+ white-space: nowrap;
1333
+ vertical-align: middle;
1334
+ cursor: pointer;
1335
+ user-select: none;
1336
+ background-image: none;
1337
+ text-decoration: none;
1338
+ border: 1px solid transparent;
1339
+ position: relative;
1340
+ border-radius: 50%;
1341
+ padding: 0;
1342
+ font-size: 0;
1343
+ outline: none;
1344
+ color: transparent;
1345
+ box-shadow: none;
1346
+ }
1347
+ .fg-paging-container .fg-dot-item .fg-dot-link:before {
1348
+ content: "";
1349
+ background-color: transparent;
1350
+ border: 1px solid transparent;
1351
+ display: block;
1352
+ border-radius: 50%;
1353
+ width: 9px;
1354
+ height: 9px;
1355
+ padding: 0;
1356
+ margin: 2px;
1357
+ }
1358
+ .fg-paging-container .fg-dot-item .fg-dot-link:active,
1359
+ .fg-paging-container .fg-dot-item .fg-dot-link:hover,
1360
+ .fg-paging-container .fg-dot-item .fg-dot-link:focus {
1361
+ text-decoration: none;
1362
+ box-shadow: none;
1363
+ outline: none;
1364
+ }
1365
+ .fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link,
1366
+ .fg-paging-container .fg-dot-item.fg-selected .fg-dot-link {
1367
+ cursor: not-allowed;
1368
+ pointer-events: none;
1369
+ }
1370
+ .fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link {
1371
+ cursor: not-allowed;
1372
+ pointer-events: none;
1373
+ outline: none;
1374
+ }
1375
+
1376
+ /* Light - Dots */
1377
+ .fg-paging-container.fg-light .fg-dot-item .fg-dot-link,
1378
+ .fg-paging-container.fg-light .fg-dot-item .fg-dot-link:before {
1379
+ transition-timing-function: ease-out;
1380
+ transition-duration: 0.3s;
1381
+ transition-property: color, border-color, background-color;
1382
+ }
1383
+ .fg-paging-container.fg-light .fg-dot-item .fg-dot-link {
1384
+ background-color: #eee;
1385
+ border-color: #9d9d9d;
1386
+ }
1387
+ .fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link {
1388
+ border-color: #888;
1389
+ }
1390
+ .fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link:before,
1391
+ .fg-paging-container.fg-light .fg-dot-item .fg-dot-link:hover:before,
1392
+ .fg-paging-container.fg-light .fg-dot-item .fg-dot-link:focus:before {
1393
+ background-color: #666;
1394
+ border-color: #888;
1395
+ }
1396
+ .fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link,
1397
+ .fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:hover,
1398
+ .fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:focus {
1399
+ background-color: #eee;
1400
+ border-color: #9d9d9d;
1401
+ opacity: 0.5;
1402
+ }
1403
+
1404
+ /* Dark - Dots */
1405
+ .fg-paging-container.fg-dark .fg-dot-item .fg-dot-link,
1406
+ .fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:before {
1407
+ transition-timing-function: ease-out;
1408
+ transition-duration: 0.3s;
1409
+ transition-property: color, border-color, background-color;
1410
+ }
1411
+ .fg-paging-container.fg-dark .fg-dot-item .fg-dot-link {
1412
+ background-color: #666;
1413
+ border-color: #333;
1414
+ }
1415
+ .fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link {
1416
+ border-color: #444;
1417
+ }
1418
+ .fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link:before,
1419
+ .fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:hover:before,
1420
+ .fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:focus:before {
1421
+ background-color: #333;
1422
+ border-color: #444;
1423
+ }
1424
+ .fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link,
1425
+ .fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:hover,
1426
+ .fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:focus {
1427
+ background-color: #666;
1428
+ border-color: #333;
1429
+ opacity: 0.5;
1430
+ }
1431
+ .fg-paging-container, .fg-paging-container *, .fg-paging-container *:before, .fg-paging-container *:after {
1432
+ box-sizing: border-box;
1433
+ }
1434
+ .fg-paging-container {
1435
+ display: block;
1436
+ padding: 15px;
1437
+ margin-top: 0!important;
1438
+ margin-bottom: 0!important;
1439
+ margin-left: auto;
1440
+ margin-right: auto;
1441
  text-align: center;
1442
  font-family: -apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
1443
  -webkit-user-select: none;
1456
  clip: rect(0,0,0,0);
1457
  border: 0;
1458
  }
1459
+ .fg-ph-dots:after {
1460
+ display: block;
1461
+ content: '';
1462
+ width: 0;
1463
+ height: 22px;
1464
+ }
1465
+
1466
  .fg-paging-container .fg-dots,
1467
  .fg-paging-container .fg-dot-item {
1468
  display: inline-block;
1583
  clear: both;
1584
  }
1585
 
1586
+ .fg-default .fg-item {
1587
+ display: inline-block;
1588
+ vertical-align: top;
1589
+ max-width: 100%;
1590
+ }
1591
  .fg-default .fg-item-inner,
1592
  .fg-default .fg-thumb {
1593
+ display: block;
1594
  vertical-align: top;
1595
  max-width: 100%;
1596
  }
1666
  margin-right: 25px;
1667
  margin-bottom: 25px;
1668
  }
1669
+
1670
+
1671
+ @media only screen and (max-width: 600px){
1672
+ .fg-default.fg-m-col1 .fg-image,
1673
+ .fg-default.fg-m-col2 .fg-image,
1674
+ .fg-default.fg-m-col3 .fg-image {
1675
+ width: 100%;
1676
+ }
1677
+ .fg-default.fg-m-col1.fg-gutter-5 .fg-item {
1678
+ width: calc(100% - 10px);
1679
+ min-width: calc(100% - 10px);
1680
+ max-width: calc(100% - 10px);
1681
+ }
1682
+ .fg-default.fg-m-col2.fg-gutter-5 .fg-item {
1683
+ width: calc(50% - 10px);
1684
+ min-width: calc(50% - 10px);
1685
+ max-width: calc(50% - 10px);
1686
+ }
1687
+ .fg-default.fg-m-col3.fg-gutter-5 .fg-item {
1688
+ width: calc(33.33% - 10px);
1689
+ min-width: calc(33.33% - 10px);
1690
+ max-width: calc(33.33% - 10px);
1691
+ }
1692
+
1693
+ .fg-default.fg-m-col1.fg-gutter-10 .fg-item {
1694
+ width: calc(100% - 20px);
1695
+ min-width: calc(100% - 20px);
1696
+ max-width: calc(100% - 20px);
1697
+ }
1698
+ .fg-default.fg-m-col2.fg-gutter-10 .fg-item {
1699
+ width: calc(50% - 20px);
1700
+ min-width: calc(50% - 20px);
1701
+ max-width: calc(50% - 20px);
1702
+ }
1703
+ .fg-default.fg-m-col3.fg-gutter-10 .fg-item {
1704
+ width: calc(33.33% - 20px);
1705
+ min-width: calc(33.33% - 20px);
1706
+ max-width: calc(33.33% - 20px);
1707
+ }
1708
+
1709
+ .fg-default.fg-m-col1.fg-gutter-15 .fg-item {
1710
+ width: calc(100% - 30px);
1711
+ min-width: calc(100% - 30px);
1712
+ max-width: calc(100% - 30px);
1713
+ }
1714
+ .fg-default.fg-m-col2.fg-gutter-15 .fg-item {
1715
+ width: calc(50% - 30px);
1716
+ min-width: calc(50% - 30px);
1717
+ max-width: calc(50% - 30px);
1718
+ }
1719
+ .fg-default.fg-m-col3.fg-gutter-15 .fg-item {
1720
+ width: calc(33.33% - 30px);
1721
+ min-width: calc(33.33% - 30px);
1722
+ max-width: calc(33.33% - 30px);
1723
+ }
1724
+
1725
+ .fg-default.fg-m-col1.fg-gutter-20 .fg-item {
1726
+ width: calc(100% - 40px);
1727
+ min-width: calc(100% - 40px);
1728
+ max-width: calc(100% - 40px);
1729
+ }
1730
+ .fg-default.fg-m-col2.fg-gutter-20 .fg-item {
1731
+ width: calc(50% - 40px);
1732
+ min-width: calc(50% - 40px);
1733
+ max-width: calc(50% - 40px);
1734
+ }
1735
+ .fg-default.fg-m-col3.fg-gutter-20 .fg-item {
1736
+ width: calc(33.33% - 40px);
1737
+ min-width: calc(33.33% - 40px);
1738
+ max-width: calc(33.33% - 40px);
1739
+ }
1740
+
1741
+ .fg-default.fg-m-col1.fg-gutter-25 .fg-item {
1742
+ width: calc(100% - 50px);
1743
+ min-width: calc(100% - 50px);
1744
+ max-width: calc(100% - 50px);
1745
+ }
1746
+ .fg-default.fg-m-col2.fg-gutter-25 .fg-item {
1747
+ width: calc(50% - 50px);
1748
+ min-width: calc(50% - 50px);
1749
+ max-width: calc(50% - 50px);
1750
+ }
1751
+ .fg-default.fg-m-col3.fg-gutter-25 .fg-item {
1752
+ width: calc(33.33% - 50px);
1753
+ min-width: calc(33.33% - 50px);
1754
+ max-width: calc(33.33% - 50px);
1755
+ }
1756
+ }
1757
  /* Base styles */
1758
  .fg-masonry * {
1759
  box-sizing: border-box;
1760
  }
1761
+ .foogallery.fg-masonry {
1762
  margin: 0 auto;
1763
+ text-align: center;
1764
  }
1765
  .fg-masonry .fg-thumb {
1766
  display: block;
1767
  }
1768
+ .fg-masonry.fg-fixed .fg-thumb {
1769
  display: inline-block;
1770
  }
1771
+ .fg-masonry.fg-fixed .fg-item,
1772
+ .fg-masonry.fg-fixed .fg-image,
1773
+ .fg-masonry.fg-fixed .fg-column-width {
1774
  max-width: 100%;
1775
  }
1776
 
1777
  .fg-masonry .fg-column-width {
1778
  display: inline-block;
 
 
1779
  border: solid 0 transparent;
1780
  }
1781
+ .fg-masonry .fg-column-width,
1782
+ .fg-masonry .fg-gutter-width {
1783
+ position: absolute;
1784
+ height: 0;
1785
+ visibility: hidden;
1786
+ opacity: 0;
1787
+ pointer-events: none;
1788
+ }
1789
 
1790
+ .fg-masonry.fg-col6 .fg-image,
1791
+ .fg-masonry.fg-col5 .fg-image,
1792
+ .fg-masonry.fg-col4 .fg-image,
1793
+ .fg-masonry.fg-col3 .fg-image,
1794
+ .fg-masonry.fg-col2 .fg-image {
1795
  width: 100%;
1796
  height: auto;
1797
  max-width: 100%;
1800
  .fg-masonry .fg-item {
1801
  line-height: 0;
1802
  font-size: 0;
1803
+ vertical-align: top;
 
 
 
1804
  }
1805
 
1806
  /* 2 column layouts */
1807
  /* 2 column layout - normal gutter */
1808
+ .fg-masonry.fg-col2 .fg-item { margin-bottom: 1%; width: 49.5%; }
1809
+ .fg-masonry.fg-col2 .fg-column-width { width: 49.5%; }
1810
+ .fg-masonry.fg-col2 .fg-gutter-width { width: 1%; }
1811
 
1812
  /* 2 column layout - no gutter */
1813
+ .fg-masonry.fg-col2.fg-gutter-none .fg-item { margin-bottom: 0; width: 50%; }
1814
+ .fg-masonry.fg-col2.fg-gutter-none .fg-column-width { width: 50%; }
1815
+ .fg-masonry.fg-col2.fg-gutter-none .fg-gutter-width { width: 0; }
1816
 
1817
  /* 2 column layout - large gutter */
1818
+ .fg-masonry.fg-col2.fg-gutter-large .fg-item { margin-bottom: 3%; width: 48.5%; }
1819
+ .fg-masonry.fg-col2.fg-gutter-large .fg-column-width { width: 48.5%; }
1820
+ .fg-masonry.fg-col2.fg-gutter-large .fg-gutter-width { width: 3%; }
1821
 
1822
  /* 3 column layouts */
1823
  /* 3 column layout - normal gutter */
1824
+ .fg-masonry.fg-col3 .fg-item { margin-bottom: 1%; width: 32.66%; }
1825
+ .fg-masonry.fg-col3 .fg-column-width { width: 32.66%; }
1826
+ .fg-masonry.fg-col3 .fg-gutter-width { width: 1%; }
1827
 
1828
  /* 3 column layout - no gutter */
1829
+ .fg-masonry.fg-col3.fg-gutter-none .fg-item { margin-bottom: 0; width: 33.33%; }
1830
+ .fg-masonry.fg-col3.fg-gutter-none .fg-column-width { width: 33.33%; }
1831
+ .fg-masonry.fg-col3.fg-gutter-none .fg-gutter-width { width: 0; }
1832
 
1833
  /* 3 column layout - large gutter */
1834
+ .fg-masonry.fg-col3.fg-gutter-large .fg-item { margin-bottom: 3%; width: 31.33%; }
1835
+ .fg-masonry.fg-col3.fg-gutter-large .fg-column-width { width: 31.33%; }
1836
+ .fg-masonry.fg-col3.fg-gutter-large .fg-gutter-width { width: 3%; }
1837
 
1838
  /* 4 column layouts */
1839
  /* 4 column layout - normal gutter */
1840
+ .fg-masonry.fg-col4 .fg-item { margin-bottom: 1%; width: 24.25%; }
1841
+ .fg-masonry.fg-col4 .fg-column-width { width: 24.25%; }
1842
+ .fg-masonry.fg-col4 .fg-gutter-width { width: 1%; }
1843
 
1844
  /* 4 column layout - no gutter */
1845
+ .fg-masonry.fg-col4.fg-gutter-none .fg-item { margin-bottom: 0; width: 25%; }
1846
+ .fg-masonry.fg-col4.fg-gutter-none .fg-column-width { width: 25%; }
1847
+ .fg-masonry.fg-col4.fg-gutter-none .fg-gutter-width { width: 0; }
1848
 
1849
  /* 4 column layout - large gutter */
1850
+ .fg-masonry.fg-col4.fg-gutter-large .fg-item { margin-bottom: 3%; width: 22.75%; }
1851
+ .fg-masonry.fg-col4.fg-gutter-large .fg-column-width { width: 22.75%; }
1852
+ .fg-masonry.fg-col4.fg-gutter-large .fg-gutter-width { width: 3%; }
1853
 
1854
  /* 5 column layouts */
1855
  /* 5 column layout - normal gutter */
1856
+ .fg-masonry.fg-col5 .fg-item { margin-bottom: 1%; width: 19.2%; }
1857
+ .fg-masonry.fg-col5 .fg-column-width { width: 19.2%; }
1858
+ .fg-masonry.fg-col5 .fg-gutter-width { width: 1%; }
1859
 
1860
  /* 5 column layout - no gutter */
1861
+ .fg-masonry.fg-col5.fg-gutter-none .fg-item { margin-bottom: 0; width: 20%; }
1862
+ .fg-masonry.fg-col5.fg-gutter-none .fg-column-width { width: 20%; }
1863
+ .fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width { width: 0; }
1864
 
1865
  /* 5 column layout - large gutter */
1866
+ .fg-masonry.fg-col5.fg-gutter-large .fg-item { margin-bottom: 3%; width: 17.6%; }
1867
+ .fg-masonry.fg-col5.fg-gutter-large .fg-column-width { width: 17.6%; }
1868
+ .fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width { width: 3%; }
1869
+
1870
+ /* 6 column layouts */
1871
+ /* 6 column layout - normal gutter */
1872
+ .fg-masonry.fg-col6 .fg-item { margin-bottom: 1%; width: 15.83%; }
1873
+ .fg-masonry.fg-col6 .fg-column-width { width: 15.83%; }
1874
+ .fg-masonry.fg-col6 .fg-gutter-width { width: 1%; }
1875
+
1876
+ /* 6 column layout - no gutter */
1877
+ .fg-masonry.fg-col6.fg-gutter-none .fg-item { margin-bottom: 0; width: 16.66%; }
1878
+ .fg-masonry.fg-col6.fg-gutter-none .fg-column-width { width: 16.66%; }
1879
+ .fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width { width: 0; }
1880
+
1881
+ /* 6 column layout - large gutter */
1882
+ .fg-masonry.fg-col6.fg-gutter-large .fg-item { margin-bottom: 3%; width: 14.16%; }
1883
+ .fg-masonry.fg-col6.fg-gutter-large .fg-column-width { width: 14.16%; }
1884
+ .fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width { width: 3%; }
1885
+
1886
+ /* Force 5 column layout < 1280px */
1887
+ @media screen and (max-width: 1280px) {
1888
+ /* default gutter */
1889
+ .fg-masonry.fg-col6 .fg-item { margin-bottom: 1%; width: 19.2%; }
1890
+ .fg-masonry.fg-col6 .fg-column-width { width: 19.2%; }
1891
+ .fg-masonry.fg-col6 .fg-gutter-width { width: 1%; }
1892
+
1893
+ /* no gutter */
1894
+ .fg-masonry.fg-col6.fg-gutter-none .fg-item { margin-bottom: 0; width: 20%; }
1895
+ .fg-masonry.fg-col6.fg-gutter-none .fg-column-width { width: 20%; }
1896
+ .fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width { width: 0; }
1897
+
1898
+ /* large gutter */
1899
+ .fg-masonry.fg-col6.fg-gutter-large .fg-item { margin-bottom: 3%; width: 17.6%; }
1900
+ .fg-masonry.fg-col6.fg-gutter-large .fg-column-width { width: 17.6%; }
1901
+ .fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width { width: 3%; }
1902
+ }
1903
+
1904
+ /* Force 4 column layout < 1024px */
1905
+ @media screen and (max-width: 1024px) {
1906
+ /* default gutter */
1907
+ .fg-masonry.fg-col6 .fg-item,
1908
+ .fg-masonry.fg-col5 .fg-item { margin-bottom: 1%; width: 24.25%; }
1909
+ .fg-masonry.fg-col6 .fg-column-width,
1910
+ .fg-masonry.fg-col5 .fg-column-width { width: 24.25%; }
1911
+ .fg-masonry.fg-col6 .fg-gutter-width,
1912
+ .fg-masonry.fg-col5 .fg-gutter-width { width: 1%; }
1913
+
1914
+ /* no gutter */
1915
+ .fg-masonry.fg-col6.fg-gutter-none .fg-item,
1916
+ .fg-masonry.fg-col5.fg-gutter-none .fg-item { margin-bottom: 0; width: 25%; }
1917
+ .fg-masonry.fg-col6.fg-gutter-none .fg-column-width,
1918
+ .fg-masonry.fg-col5.fg-gutter-none .fg-column-width { width: 25%; }
1919
+ .fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width,
1920
+ .fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width { width: 0; }
1921
+
1922
+ /* large gutter */
1923
+ .fg-masonry.fg-col6.fg-gutter-large .fg-item,
1924
+ .fg-masonry.fg-col5.fg-gutter-large .fg-item { margin-bottom: 3%; width: 22.75%; }
1925
+ .fg-masonry.fg-col6.fg-gutter-large .fg-column-width,
1926
+ .fg-masonry.fg-col5.fg-gutter-large .fg-column-width { width: 22.75%; }
1927
+ .fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width,
1928
+ .fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width { width: 3%; }
1929
+ }
1930
 
1931
  /* Force 3 column layout < 720px */
1932
  @media screen and (max-width: 720px) {
1933
  /* default gutter */
1934
+ .fg-masonry.fg-col6 .fg-item,
1935
+ .fg-masonry.fg-col5 .fg-item,
1936
+ .fg-masonry.fg-col4 .fg-item { margin-bottom: 1%; width: 32.66%; }
1937
+ .fg-masonry.fg-col6 .fg-column-width,
1938
+ .fg-masonry.fg-col5 .fg-column-width,
1939
+ .fg-masonry.fg-col4 .fg-column-width { width: 32.66%; }
1940
+ .fg-masonry.fg-col6 .fg-gutter-width,
1941
+ .fg-masonry.fg-col5 .fg-gutter-width,
1942
+ .fg-masonry.fg-col4 .fg-gutter-width { width: 1%; }
1943
 
1944
  /* no gutter */
1945
+ .fg-masonry.fg-col6.fg-gutter-none .fg-item,
1946
+ .fg-masonry.fg-col5.fg-gutter-none .fg-item,
1947
+ .fg-masonry.fg-col4.fg-gutter-none .fg-item { margin-bottom: 0; width: 33.33%; }
1948
+ .fg-masonry.fg-col6.fg-gutter-none .fg-column-width,
1949
+ .fg-masonry.fg-col5.fg-gutter-none .fg-column-width,
1950
+ .fg-masonry.fg-col4.fg-gutter-none .fg-column-width { width: 33.33%; }
1951
+ .fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width,
1952
+ .fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width,
1953
+ .fg-masonry.fg-col4.fg-gutter-none .fg-gutter-width { width: 0; }
1954
 
1955
  /* large gutter */
1956
+ .fg-masonry.fg-col6.fg-gutter-large .fg-item,
1957
+ .fg-masonry.fg-col5.fg-gutter-large .fg-item,
1958
+ .fg-masonry.fg-col4.fg-gutter-large .fg-item { margin-bottom: 3%; width: 31.33%; }
1959
+ .fg-masonry.fg-col6.fg-gutter-large .fg-column-width,
1960
+ .fg-masonry.fg-col5.fg-gutter-large .fg-column-width,
1961
+ .fg-masonry.fg-col4.fg-gutter-large .fg-column-width { width: 31.33%; }
1962
+ .fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width,
1963
+ .fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width,
1964
+ .fg-masonry.fg-col4.fg-gutter-large .fg-gutter-width { width: 3%; }
1965
 
1966
  }
1967
 
1968
  /* Force 2 column layout < 480px */
1969
  @media screen and (max-width: 480px) {
1970
  /* default gutter */
1971
+ .fg-masonry.fg-col6 .fg-item,
1972
+ .fg-masonry.fg-col5 .fg-item,
1973
+ .fg-masonry.fg-col4 .fg-item,
1974
+ .fg-masonry.fg-col3 .fg-item { margin-bottom: 1%; width: 49.5%; }
1975
+ .fg-masonry.fg-col6 .fg-column-width,
1976
+ .fg-masonry.fg-col5 .fg-column-width,
1977
+ .fg-masonry.fg-col4 .fg-column-width,
1978
+ .fg-masonry.fg-col3 .fg-column-width { width: 49.5%; }
1979
+ .fg-masonry.fg-col6 .fg-gutter-width,
1980
+ .fg-masonry.fg-col5 .fg-gutter-width,
1981
+ .fg-masonry.fg-col4 .fg-gutter-width,
1982
+ .fg-masonry.fg-col3 .fg-gutter-width { width: 1%; }
1983
 
1984
  /* no gutter */
1985
+ .fg-masonry.fg-col6.fg-gutter-none .fg-item,
1986
+ .fg-masonry.fg-col5.fg-gutter-none .fg-item,
1987
+ .fg-masonry.fg-col4.fg-gutter-none .fg-item,
1988
+ .fg-masonry.fg-col3.fg-gutter-none .fg-item { margin-bottom: 0; width: 50%; }
1989
+ .fg-masonry.fg-col6.fg-gutter-none .fg-column-width,
1990
+ .fg-masonry.fg-col5.fg-gutter-none .fg-column-width,
1991
+ .fg-masonry.fg-col4.fg-gutter-none .fg-column-width,
1992
+ .fg-masonry.fg-col3.fg-gutter-none .fg-column-width { width: 50%; }
1993
+ .fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width,
1994
+ .fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width,
1995
+ .fg-masonry.fg-col4.fg-gutter-none .fg-gutter-width,
1996
+ .fg-masonry.fg-col3.fg-gutter-none .fg-gutter-width { width: 0; }
1997
 
1998
  /* large gutter */
1999
+ .fg-masonry.fg-col6.fg-gutter-large .fg-item,
2000
+ .fg-masonry.fg-col5.fg-gutter-large .fg-item,
2001
+ .fg-masonry.fg-col4.fg-gutter-large .fg-item,
2002
+ .fg-masonry.fg-col3.fg-gutter-large .fg-item { margin-bottom: 3%; width: 48.5%; }
2003
+ .fg-masonry.fg-col6.fg-gutter-large .fg-column-width,
2004
+ .fg-masonry.fg-col5.fg-gutter-large .fg-column-width,
2005
+ .fg-masonry.fg-col4.fg-gutter-large .fg-column-width,
2006
+ .fg-masonry.fg-col3.fg-gutter-large .fg-column-width { width: 48.5%; }
2007
+ .fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width,
2008
+ .fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width,
2009
+ .fg-masonry.fg-col4.fg-gutter-large .fg-gutter-width,
2010
+ .fg-masonry.fg-col3.fg-gutter-large .fg-gutter-width { width: 3%; }
2011
  }
2012
 
2013
  /* Force 1 column layout < 320px */
2014
  @media screen and (max-width: 320px) {
2015
  /* default gutter */
2016
+ .fg-masonry.fg-col6 .fg-item,
2017
+ .fg-masonry.fg-col5 .fg-item,
2018
+ .fg-masonry.fg-col4 .fg-item,
2019
+ .fg-masonry.fg-col3 .fg-item,
2020
+ .fg-masonry.fg-col2 .fg-item { margin-bottom: 1%; width: 100%; }
2021
+ .fg-masonry.fg-col6 .fg-column-width,
2022
+ .fg-masonry.fg-col5 .fg-column-width,
2023
+ .fg-masonry.fg-col4 .fg-column-width,
2024
+ .fg-masonry.fg-col3 .fg-column-width,
2025
+ .fg-masonry.fg-col2 .fg-column-width { width: 100%; }
2026
+ .fg-masonry.fg-col6 .fg-gutter-width,
2027
+ .fg-masonry.fg-col5 .fg-gutter-width,
2028
+ .fg-masonry.fg-col4 .fg-gutter-width,
2029
+ .fg-masonry.fg-col3 .fg-gutter-width,
2030
+ .fg-masonry.fg-col2 .fg-gutter-width { width: 0; }
2031
 
2032
  /* no gutter */
2033
+ .fg-masonry.fg-col6.fg-gutter-none .fg-item,
2034
+ .fg-masonry.fg-col5.fg-gutter-none .fg-item,
2035
+ .fg-masonry.fg-col4.fg-gutter-none .fg-item,
2036
+ .fg-masonry.fg-col3.fg-gutter-none .fg-item,
2037
+ .fg-masonry.fg-col2.fg-gutter-none .fg-item { margin-bottom: 0; width: 100%; }
2038
+ .fg-masonry.fg-col6.fg-gutter-none .fg-column-width,
2039
+ .fg-masonry.fg-col5.fg-gutter-none .fg-column-width,
2040
+ .fg-masonry.fg-col4.fg-gutter-none .fg-column-width,
2041
+ .fg-masonry.fg-col3.fg-gutter-none .fg-column-width,
2042
+ .fg-masonry.fg-col2.fg-gutter-none .fg-column-width { width: 100%; }
2043
+ .fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width,
2044
+ .fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width,
2045
+ .fg-masonry.fg-col4.fg-gutter-none .fg-gutter-width,
2046
+ .fg-masonry.fg-col3.fg-gutter-none .fg-gutter-width,
2047
+ .fg-masonry.fg-col2.fg-gutter-none .fg-gutter-width { width: 0; }
2048
 
2049
  /* large gutter */
2050
+ .fg-masonry.fg-col6.fg-gutter-large .fg-item,
2051
+ .fg-masonry.fg-col5.fg-gutter-large .fg-item,
2052
+ .fg-masonry.fg-col4.fg-gutter-large .fg-item,
2053
+ .fg-masonry.fg-col3.fg-gutter-large .fg-item,
2054
+ .fg-masonry.fg-col2.fg-gutter-large .fg-item { margin-bottom: 3%; width: 100%; }
2055
+ .fg-masonry.fg-col6.fg-gutter-large .fg-column-width,
2056
+ .fg-masonry.fg-col5.fg-gutter-large .fg-column-width,
2057
+ .fg-masonry.fg-col4.fg-gutter-large .fg-column-width,
2058
+ .fg-masonry.fg-col3.fg-gutter-large .fg-column-width,
2059
+ .fg-masonry.fg-col2.fg-gutter-large .fg-column-width { width: 100%; }
2060
+ .fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width,
2061
+ .fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width,
2062
+ .fg-masonry.fg-col4.fg-gutter-large .fg-gutter-width,
2063
+ .fg-masonry.fg-col3.fg-gutter-large .fg-gutter-width,
2064
+ .fg-masonry.fg-col2.fg-gutter-large .fg-gutter-width { width: 0; }
2065
  }
2066
 
2067
  /* Border Styles - We must apply width changing border styles to the fg-column-width element so that the plugin can correctly determine the item widths. */
2094
  background-color: transparent;
2095
  border-style: solid;
2096
  border-color: transparent;
2097
+ text-align: left;
2098
+ }
2099
+ .foogallery.fg-masonry.fg-captions-bottom.fg-c-l .fg-item-inner .fg-caption {
2100
+ text-align: left;
2101
+ }
2102
+ .foogallery.fg-masonry.fg-captions-bottom.fg-c-c .fg-item-inner .fg-caption {
2103
+ text-align: center;
2104
+ }
2105
+ .foogallery.fg-masonry.fg-captions-bottom.fg-c-r .fg-item-inner .fg-caption {
2106
+ text-align: right;
2107
+ }
2108
+ .foogallery.fg-masonry.fg-captions-bottom.fg-c-j .fg-item-inner .fg-caption {
2109
+ text-align: justify;
2110
  }
2111
  .foogallery.fg-masonry.fg-captions-bottom .fg-item-inner:hover .fg-caption {
2112
  transform: none;
2137
  opacity: 1;
2138
  }
2139
 
 
 
 
 
2140
  .fg-masonry.fg-captions-bottom.fg-light .fg-caption,
2141
  .fg-masonry.fg-captions-bottom.fg-dark .fg-caption {
2142
  color: #828282;
2287
  .fg-justified {
2288
  box-sizing: border-box;
2289
  position: relative;
2290
+ text-align: center;
2291
+ }
2292
+ .foogallery.fg-justified .fg-item {
2293
+ box-sizing: border-box;
2294
+ display: inline-block;
2295
+ margin: 0;
2296
+ padding: 0;
2297
  }
 
2298
  .foogallery.fg-justified .fg-item-inner,
2299
  .foogallery.fg-justified .fg-thumb,
2300
  .foogallery.fg-justified .fg-image {
2305
  }
2306
  .fg-justified .fg-item {
2307
  visibility: visible;
2308
+ position: relative;
2309
  }
2310
  .fg-justified .fg-item-inner {
2311
  position: relative;
2325
  height: 100%;
2326
  }
2327
  .fg-justified .fg-item.fg-positioned .fg-image {
2328
+ width: 100%!important;
2329
+ height: auto!important;
2330
  min-height: 100%;
 
 
2331
  }
2332
+ /* CSS justified layout. */
2333
+ .foogallery.fg-justified-css {
2334
+ position: relative;
2335
+ display: flex;
2336
+ box-sizing: border-box;
2337
+ align-items: center;
2338
+ justify-content: stretch;
2339
+ flex-wrap: wrap;
2340
+ }
2341
+ .foogallery.fg-justified-css:after {
2342
+ display: block;
2343
+ content: '';
2344
+ flex-shrink: 0;
2345
+ flex-grow: 10;
2346
+ min-width: 60px;
2347
+ }
2348
+ .foogallery.fg-justified-css .fg-item,
2349
+ .foogallery.fg-justified-css .fg-item-inner,
2350
+ .foogallery.fg-justified-css .fg-thumb,
2351
+ .foogallery.fg-justified-css .fg-image {
2352
+ display: block;
2353
+ }
2354
+
2355
+ .foogallery.fg-justified-css .fg-item {
2356
+ flex-shrink: 0;
2357
+ flex-grow: 1;
2358
+ margin: 5px;
2359
+ }
2360
+ .foogallery.fg-justified-css .fg-thumb {
2361
+
2362
+ }
2363
+ .foogallery.fg-justified-css .fg-image-wrap {
2364
+ display: flex;
2365
+ align-items: center;
2366
+ justify-content: stretch;
2367
+ overflow: hidden;
2368
+ }
2369
+ .foogallery.fg-justified-css .fg-image {
2370
+ width: 100%;
2371
+ height: auto;
2372
  }
2373
  .fg-simple_portfolio {
2374
  display: flex;
2379
  }
2380
  .fg-simple_portfolio .fg-item {
2381
  position: relative;
2382
+ flex-grow: 0;
2383
+ flex-shrink: 0;
2384
+ flex-basis: auto;
2385
  margin: 10px;
2386
+ max-width: 100%;
 
2387
  }
2388
  .fg-simple_portfolio .fg-item-inner {
2389
  display: flex;
2424
  background-color: transparent;
2425
  border-style: solid;
2426
  border-color: transparent;
2427
+ text-align: left;
2428
+ }
2429
+ .foogallery.fg-simple_portfolio.fg-c-l .fg-item-inner .fg-caption {
2430
+ text-align: left;
2431
+ }
2432
+ .foogallery.fg-simple_portfolio.fg-c-c .fg-item-inner .fg-caption {
2433
+ text-align: center;
2434
+ }
2435
+ .foogallery.fg-simple_portfolio.fg-c-r .fg-item-inner .fg-caption {
2436
+ text-align: right;
2437
+ }
2438
+ .foogallery.fg-simple_portfolio.fg-c-j .fg-item-inner .fg-caption {
2439
+ text-align: justify;
2440
  }
2441
  .foogallery.fg-simple_portfolio .fg-item-inner:hover .fg-caption {
2442
  transform: none;
2464
  visibility: visible;
2465
  opacity: 1;
2466
  }
 
2467
  .fg-simple_portfolio .fg-caption-title {
2468
+ white-space: normal;
 
 
 
2469
  }
2470
+
2471
  .fg-simple_portfolio.fg-light .fg-caption,
2472
  .fg-simple_portfolio.fg-dark .fg-caption {
2473
  color: #828282;
2843
  margin: 0 4px;
2844
  }
2845
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2846
  /* Captions */
2847
 
2848
  .foogallery.fg-image-viewer.fg-caption-always .fg-item-inner .fg-caption {
2849
  padding: 0;
2850
  border: none;
 
 
 
 
2851
  }
2852
  .foogallery.fg-image-viewer.fg-caption-always .fg-caption-title {
2853
  padding: 10px 10px 10px 10px;
extensions/default-templates/shared/css/foogallery.min.css CHANGED
@@ -1 +1 @@
1
- .foogallery,.foogallery *{box-sizing:border-box}.foogallery{display:block;z-index:1;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;position:relative;line-height:0;font-size:0;width:100%;max-width:100%}.foogallery .fg-item{display:inline-block;position:relative;background-color:transparent;z-index:2;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.foogallery .fg-item-inner{display:block;position:relative;visibility:hidden;overflow:hidden;opacity:0;z-index:3;margin:0;border:solid 0 transparent}.foogallery .fg-item.fg-error:before{content:"";display:block;position:absolute;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);width:32px;height:32px;background-image:url(../img/icons.svg#image);background-color:transparent;background-repeat:no-repeat;background-position:center center;background-size:32px 32px}.foogallery .fg-item.fg-loaded{z-index:4}.foogallery .fg-loaded .fg-item-inner{visibility:visible;opacity:1;z-index:5}.foogallery .fg-error .fg-item-inner{pointer-events:none;cursor:default}.foogallery .fg-thumb{display:block;position:relative;border:none;outline:0;text-decoration:none;z-index:4;box-shadow:none}.foogallery .fg-thumb:focus,.foogallery .fg-thumb:hover{border:none;outline:0;text-decoration:none;box-shadow:none}.foogallery .fg-image-overlay{position:absolute;top:0;right:0;bottom:0;left:0;z-index:8;visibility:hidden;opacity:0}.foogallery .fg-image-wrap{display:block;position:relative}.foogallery .fg-image{display:block;position:relative;border:none;outline:0;text-decoration:none;z-index:5;max-width:none;height:auto;margin:0}.foogallery .fg-loaded .fg-thumb{z-index:6}.foogallery .fg-loaded .fg-image{z-index:7}.foogallery.fg-light .fg-item-inner{background-color:#fff;color:#333;border-color:#fff}.foogallery.fg-dark .fg-item-inner{background-color:#333;color:#fff;border-color:#333}.foogallery.fg-light .fg-item.fg-error,.foogallery.fg-light .fg-item.fg-idle,.foogallery.fg-light .fg-item.fg-loading{background-color:#eee;box-shadow:inset 0 0 0 1px #ddd}.foogallery.fg-dark .fg-item.fg-error,.foogallery.fg-dark .fg-item.fg-idle,.foogallery.fg-dark .fg-item.fg-loading{background-color:#444;box-shadow:inset 0 0 0 1px #333}.foogallery .fg-caption{background-color:rgba(0,0,0,.6);color:#fff}.foogallery .fg-caption a{color:#fff;border-bottom:1px solid #fff}.foogallery.fg-light-overlays .fg-caption{background-color:rgba(255,255,255,.8);color:#333}.foogallery.fg-light-overlays .fg-caption a{color:#333;border-bottom-color:#333}.foogallery.fg-transparent-overlays .fg-caption{background-color:transparent;color:#fff}.foogallery.fg-transparent-overlays .fg-caption a{color:#fff;border-bottom-color:#fff}.foogallery .fg-image-overlay{background-color:rgba(0,0,0,.6);color:#fff}.foogallery.fg-light-overlays .fg-image-overlay{background-color:rgba(255,255,255,.8);color:#333}.foogallery.fg-transparent-overlays .fg-image-overlay{background-color:transparent;color:#fff}.fg-exif-light .fg-item.fg-item-exif .fg-image-wrap:after{background-color:#fff;color:#333}.fg-exif-dark .fg-item.fg-item-exif .fg-image-wrap:after{background-color:#333;color:#fff}.fg-exif-rounded .fg-item.fg-item-exif .fg-image-wrap:after{border-radius:3px}.fg-exif-bottom-left .fg-item.fg-item-exif .fg-image-wrap:after,.fg-exif-bottom-right .fg-item.fg-item-exif .fg-image-wrap:after,.fg-exif-top-left .fg-item.fg-item-exif .fg-image-wrap:after,.fg-exif-top-right .fg-item.fg-item-exif .fg-image-wrap:after{display:inline-block;position:absolute;content:'EXIF';font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:11px;line-height:10px;padding:3px 4px;z-index:7}.fg-exif-bottom-right .fg-item.fg-item-exif .fg-image-wrap:after{bottom:5px;right:5px}.fg-exif-bottom-left .fg-item.fg-item-exif .fg-image-wrap:after{bottom:5px;left:5px}.fg-exif-top-right .fg-item.fg-item-exif .fg-image-wrap:after{top:5px;right:5px}.fg-exif-top-left .fg-item.fg-item-exif .fg-image-wrap:after{top:5px;left:5px}.foogallery.fg-border-thin .fg-item-inner{border-width:4px}.foogallery.fg-border-medium .fg-item-inner{border-width:10px}.foogallery.fg-border-thick .fg-item-inner{border-width:16px}.foogallery.fg-light.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px #ddd}.foogallery.fg-dark.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px #222}.foogallery.fg-dark.fg-shadow-small .fg-item-inner,.foogallery.fg-light.fg-shadow-small .fg-item-inner{box-shadow:0 1px 4px 0 rgba(0,0,0,.5)}.foogallery.fg-dark.fg-shadow-medium .fg-item-inner,.foogallery.fg-light.fg-shadow-medium .fg-item-inner{box-shadow:0 1px 10px 0 rgba(0,0,0,.5)}.foogallery.fg-dark.fg-shadow-large .fg-item-inner,.foogallery.fg-light.fg-shadow-large .fg-item-inner{box-shadow:0 1px 16px 0 rgba(0,0,0,.5)}.foogallery.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-shadow-inset-small .fg-thumb:after{display:block;content:"";position:absolute;top:0;left:0;right:0;bottom:0;z-index:7}.foogallery.fg-dark.fg-shadow-inset-small .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-small .fg-thumb:after{box-shadow:inset 0 1px 4px 0 rgba(0,0,0,.3)}.foogallery.fg-dark.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-medium .fg-thumb:after{box-shadow:inset 0 1px 10px 0 rgba(0,0,0,.3)}.foogallery.fg-dark.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-large .fg-thumb:after{box-shadow:inset 0 1px 16px 0 rgba(0,0,0,.3)}.foogallery.fg-round-full.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-round-full.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-round-full.fg-shadow-inset-small .fg-thumb:after{border-radius:50%}.foogallery.fg-round-small .fg-item,.foogallery.fg-round-small .fg-item-inner{border-radius:5px}.foogallery.fg-round-medium .fg-item,.foogallery.fg-round-medium .fg-item-inner{border-radius:10px}.foogallery.fg-round-large .fg-item,.foogallery.fg-round-large .fg-item-inner{border-radius:15px}.foogallery.fg-round-full .fg-item,.foogallery.fg-round-full .fg-item-inner{border-radius:50%}.foogallery .fg-loader{position:absolute;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);width:1em;height:1em;font-size:5px;visibility:hidden;opacity:0}.foogallery .fg-loading .fg-loader{visibility:visible;opacity:1}.fg-loading-default .fg-loader{border-radius:50%;text-indent:-9999em;box-shadow:0 -2.6em 0 0 rgba(130,130,130,1),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.5),-1.8em -1.8em 0 0 rgba(130,130,130,.7);-webkit-animation:loading-default 1.1s infinite steps(8,start);animation:loading-default 1.1s infinite steps(8,start)}@-webkit-keyframes loading-default{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes loading-default{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.fg-loading-bars .fg-loader,.fg-loading-bars .fg-loader:after,.fg-loading-bars .fg-loader:before{background:rgba(130,130,130,1);-webkit-animation:loading-bars 1s infinite ease-in-out;animation:loading-bars 1s infinite ease-in-out;width:1em;height:4em}.fg-loading-bars .fg-loader{color:rgba(130,130,130,1);text-indent:-9999em;font-size:4px;-webkit-animation-delay:-.16s;animation-delay:-.16s}.fg-loading-bars .fg-loader:after,.fg-loading-bars .fg-loader:before{position:absolute;top:0;content:''}.fg-loading-bars .fg-loader:before{left:-1.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.fg-loading-bars .fg-loader:after{left:1.5em}@-webkit-keyframes loading-bars{0%,100%,80%{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}@keyframes loading-bars{0%,100%,80%{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}.fg-loading-trail .fg-loader{color:#828282;font-size:20px;text-indent:-9999em;overflow:hidden;border-radius:50%;-webkit-animation:loading-trail-1 1.7s infinite ease,loading-trail-2 1.7s infinite ease;animation:loading-trail-1 1.7s infinite ease,loading-trail-2 1.7s infinite ease}@-webkit-keyframes loading-trail-1{0%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}5%,95%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}10%,59%{box-shadow:0 -.83em 0 -.4em,-.087em -.825em 0 -.42em,-.173em -.812em 0 -.44em,-.256em -.789em 0 -.46em,-.297em -.775em 0 -.477em}20%{box-shadow:0 -.83em 0 -.4em,-.338em -.758em 0 -.42em,-.555em -.617em 0 -.44em,-.671em -.488em 0 -.46em,-.749em -.34em 0 -.477em}38%{box-shadow:0 -.83em 0 -.4em,-.377em -.74em 0 -.42em,-.645em -.522em 0 -.44em,-.775em -.297em 0 -.46em,-.82em -.09em 0 -.477em}100%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}}@keyframes loading-trail-1{0%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}5%,95%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}10%,59%{box-shadow:0 -.83em 0 -.4em,-.087em -.825em 0 -.42em,-.173em -.812em 0 -.44em,-.256em -.789em 0 -.46em,-.297em -.775em 0 -.477em}20%{box-shadow:0 -.83em 0 -.4em,-.338em -.758em 0 -.42em,-.555em -.617em 0 -.44em,-.671em -.488em 0 -.46em,-.749em -.34em 0 -.477em}38%{box-shadow:0 -.83em 0 -.4em,-.377em -.74em 0 -.42em,-.645em -.522em 0 -.44em,-.775em -.297em 0 -.46em,-.82em -.09em 0 -.477em}100%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}}@-webkit-keyframes loading-trail-2{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}@keyframes loading-trail-2{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}.fg-loading-pulse .fg-loader,.fg-loading-pulse .fg-loader:after,.fg-loading-pulse .fg-loader:before{border-radius:50%;width:2.5em;height:2.5em;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation:loading-pulse 1.8s infinite ease-in-out;animation:loading-pulse 1.8s infinite ease-in-out}.fg-loading-pulse .fg-loader{color:#828282;font-size:4px;text-indent:-9999em;transform:translateX(-50%) translateY(-150%);-webkit-animation-delay:-.16s;animation-delay:-.16s}.fg-loading-pulse .fg-loader:after,.fg-loading-pulse .fg-loader:before{content:'';position:absolute;top:0}.fg-loading-pulse .fg-loader:before{left:-3.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.fg-loading-pulse .fg-loader:after{left:3.5em}@-webkit-keyframes loading-pulse{0%,100%,80%{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}@keyframes loading-pulse{0%,100%,80%{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}.fg-loading-dots .fg-loader{color:#828282;font-size:5px;border-radius:50%;text-indent:-9999em;-webkit-animation:loading-dots 1.3s infinite linear;animation:loading-dots 1.3s infinite linear}@-webkit-keyframes loading-dots{0%,100%{box-shadow:0 -3em 0 .2em,2em -2em 0 0,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 0}12.5%{box-shadow:0 -3em 0 0,2em -2em 0 .2em,3em 0 0 0,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}25%{box-shadow:0 -3em 0 -.5em,2em -2em 0 0,3em 0 0 .2em,2em 2em 0 0,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}37.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 0,2em 2em 0 .2em,0 3em 0 0,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}50%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 0,0 3em 0 .2em,-2em 2em 0 0,-3em 0 0 -1em,-2em -2em 0 -1em}62.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 0,-2em 2em 0 .2em,-3em 0 0 0,-2em -2em 0 -1em}75%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 .2em,-2em -2em 0 0}87.5%{box-shadow:0 -3em 0 0,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 0,-2em -2em 0 .2em}}@keyframes loading-dots{0%,100%{box-shadow:0 -3em 0 .2em,2em -2em 0 0,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 0}12.5%{box-shadow:0 -3em 0 0,2em -2em 0 .2em,3em 0 0 0,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}25%{box-shadow:0 -3em 0 -.5em,2em -2em 0 0,3em 0 0 .2em,2em 2em 0 0,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}37.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 0,2em 2em 0 .2em,0 3em 0 0,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}50%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 0,0 3em 0 .2em,-2em 2em 0 0,-3em 0 0 -1em,-2em -2em 0 -1em}62.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 0,-2em 2em 0 .2em,-3em 0 0 0,-2em -2em 0 -1em}75%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 .2em,-2em -2em 0 0}87.5%{box-shadow:0 -3em 0 0,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 0,-2em -2em 0 .2em}}.fg-loading-partial .fg-loader,.fg-loading-partial .fg-loader:after{border-radius:50%;width:10em;height:10em}.fg-loading-partial .fg-loader{font-size:4px;text-indent:-9999em;border-top:1.1em solid rgba(130,130,130,.2);border-right:1.1em solid rgba(130,130,130,.2);border-bottom:1.1em solid rgba(130,130,130,.2);border-left:1.1em solid #828282;-webkit-animation:loading-partial 1.1s infinite linear;animation:loading-partial 1.1s infinite linear}@-webkit-keyframes loading-partial{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}@keyframes loading-partial{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}.foogallery.fg-loaded-drop .fg-item,.foogallery.fg-loaded-fade-in .fg-item,.foogallery.fg-loaded-flip .fg-item,.foogallery.fg-loaded-fly .fg-item,.foogallery.fg-loaded-scale-up .fg-item,.foogallery.fg-loaded-slide-down .fg-item,.foogallery.fg-loaded-slide-left .fg-item,.foogallery.fg-loaded-slide-right .fg-item,.foogallery.fg-loaded-slide-up .fg-item,.foogallery.fg-loaded-swing-down .fg-item{transition-timing-function:ease;transition-duration:650ms;transition-property:background-color,transform}.foogallery.fg-loaded-drop .fg-item-inner,.foogallery.fg-loaded-fade-in .fg-item-inner,.foogallery.fg-loaded-flip .fg-item-inner,.foogallery.fg-loaded-fly .fg-item-inner,.foogallery.fg-loaded-scale-up .fg-item-inner,.foogallery.fg-loaded-slide-down .fg-item-inner,.foogallery.fg-loaded-slide-left .fg-item-inner,.foogallery.fg-loaded-slide-right .fg-item-inner,.foogallery.fg-loaded-slide-up .fg-item-inner,.foogallery.fg-loaded-swing-down .fg-item-inner{transition-timing-function:ease;transition-duration:650ms}.foogallery.fg-loaded-drop .fg-item.fg-loaded,.foogallery.fg-loaded-flip .fg-item.fg-loaded,.foogallery.fg-loaded-fly .fg-item.fg-loaded,.foogallery.fg-loaded-swing-down .fg-item.fg-loaded{perspective:1300px}.foogallery.fg-loaded-fade-in .fg-item-inner{transition-property:visibility,opacity}.foogallery .fg-caption{visibility:hidden;opacity:0;position:absolute;z-index:8;width:100%;max-height:100%;overflow:hidden;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:13px;font-weight:400;line-height:1.3;border:none;text-align:center;cursor:pointer;margin:0}.foogallery .fg-caption a{text-decoration:none}.foogallery .fg-caption a:hover{border-bottom:none}.foogallery .fg-caption-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:16px;font-weight:400;padding:5px}.foogallery .fg-caption-desc{padding:5px}.foogallery .fg-caption-title+.fg-caption-desc{padding-top:0}.foogallery.fg-caption-always .fg-item .fg-caption .fg-caption-inner:before{display:none}.foogallery.fg-caption-always .fg-item.fg-loaded .fg-caption{left:0;bottom:0;transition-timing-function:ease;transition-duration:.3s;transition-property:visibility,opacity;visibility:visible;opacity:1;text-align:left}.foogallery.fg-caption-hover .fg-caption .fg-caption-inner{width:100%;max-height:100%;position:absolute;top:50%;left:0;transform:translateY(-50%)}.foogallery.fg-caption-hover .fg-item.fg-loaded .fg-image-overlay{display:none}.foogallery .fg-image-overlay:before{content:"";display:block;position:absolute;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);width:32px;height:32px;background-size:32px 32px;background-position:center center;background-repeat:no-repeat}.foogallery .fg-caption-inner:before{content:"";display:none;position:relative;width:32px;height:32px;margin:10px 0 5px 0;background-size:32px 32px;vertical-align:middle;background-position:center center;background-repeat:no-repeat}.foogallery.fg-hover-circle-plus:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-external:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-eye:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-plus:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-tint:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-zoom2:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-zoom3:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-zoom:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-1:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-2:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-3:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-4:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-default:not(.fg-preset) .fg-caption-inner:before{display:inline-block}.foogallery.fg-hover-circle-plus:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-external:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-eye:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-plus:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-tint:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-zoom2:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-zoom3:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-zoom:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-1:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-2:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-3:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-4:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-default:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-video-sticky .fg-type-video.fg-loaded .fg-item-inner .fg-image-overlay{background-color:transparent;visibility:visible;opacity:1;display:block}.foogallery.fg-video-sticky .fg-type-video .fg-caption-inner:before{display:none}.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom-light)}.foogallery.fg-light-overlays.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-zoom .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom-dark)}.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom2-light)}.foogallery.fg-light-overlays.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-zoom2 .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom2-dark)}.foogallery.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom3-light)}.foogallery.fg-light-overlays.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-zoom3 .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom3-dark)}.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-image-overlay:before{background-image:url(../img/icons.svg#plus-light)}.foogallery.fg-light-overlays.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-plus .fg-image-overlay:before{background-image:url(../img/icons.svg#plus-dark)}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-circle-plus .fg-image-overlay:before{background-image:url(../img/icons.svg#circle-plus-light)}.foogallery.fg-light-overlays.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-circle-plus .fg-image-overlay:before{background-image:url(../img/icons.svg#circle-plus-dark)}.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-image-overlay:before{background-image:url(../img/icons.svg#eye-light)}.foogallery.fg-light-overlays.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-eye .fg-image-overlay:before{background-image:url(../img/icons.svg#eye-dark)}.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-external .fg-image-overlay:before{background-image:url(../img/icons.svg#external-light)}.foogallery.fg-light-overlays.fg-hover-external .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-external .fg-image-overlay:before{background-image:url(../img/icons.svg#external-dark)}.foogallery.fg-video-default .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-default .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-default-light)}.foogallery.fg-light-overlays.fg-video-default .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-default .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-default-dark)}.foogallery.fg-video-1 .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-1 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-1-light)}.foogallery.fg-light-overlays.fg-video-1 .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-1 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-1-dark)}.foogallery.fg-video-2 .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-2 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-2-light)}.foogallery.fg-light-overlays.fg-video-2 .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-2 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-2-dark)}.foogallery.fg-video-3 .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-3 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-3-light)}.foogallery.fg-light-overlays.fg-video-3 .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-3 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-3-dark)}.foogallery.fg-video-4 .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-4 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-4-light)}.foogallery.fg-light-overlays.fg-video-4 .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-4 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-4-dark)}.foogallery.fg-caption-hover.fg-hover-colorize .fg-caption,.foogallery.fg-caption-hover.fg-hover-fade .fg-caption,.foogallery.fg-caption-hover.fg-hover-grayscale .fg-caption,.foogallery.fg-caption-hover.fg-hover-instant .fg-caption,.foogallery.fg-caption-hover.fg-hover-push .fg-caption,.foogallery.fg-caption-hover.fg-hover-scale .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-down .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-caption,.foogallery.fg-hover-colorize .fg-image,.foogallery.fg-hover-colorize .fg-image-overlay,.foogallery.fg-hover-fade .fg-image-overlay,.foogallery.fg-hover-grayscale .fg-image,.foogallery.fg-hover-grayscale .fg-image-overlay,.foogallery.fg-hover-instant .fg-image-overlay,.foogallery.fg-hover-push .fg-thumb,.foogallery.fg-hover-scale .fg-image-overlay,.foogallery.fg-hover-scale .fg-item,.foogallery.fg-hover-slide-down .fg-image-overlay,.foogallery.fg-hover-slide-left .fg-image-overlay,.foogallery.fg-hover-slide-right .fg-image-overlay,.foogallery.fg-hover-slide-up .fg-image-overlay,.foogallery.fg-hover-zoomed .fg-image{transition-timing-function:ease;transition-duration:.3s;backface-visibility:hidden}.foogallery.fg-hover-colorize .fg-image{filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'saturate\' values=\'0\'/></filter></svg>#grayscale");filter:gray;-webkit-filter:grayscale(100%);-webkit-transition-property:-webkit-filter;transition-property:filter}.foogallery.fg-hover-colorize .fg-item-inner:hover .fg-image{-webkit-filter:none;filter:none}.foogallery.fg-caption-hover.fg-hover-colorize .fg-caption,.foogallery.fg-hover-colorize .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-colorize .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-colorize .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-caption,.foogallery.fg-hover-fade .fg-loaded .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-fade .fg-loaded .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-hover-grayscale .fg-image{-webkit-filter:none;filter:none;-webkit-transition-property:-webkit-filter;transition-property:filter}.foogallery.fg-hover-grayscale .fg-item-inner:hover .fg-image{-webkit-filter:grayscale(1);-webkit-filter:grayscale(100%);filter:grayscale(100%);filter:gray;opacity:1}.foogallery.fg-caption-hover.fg-hover-grayscale .fg-caption,.foogallery.fg-hover-grayscale .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-grayscale .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-grayscale .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-caption,.foogallery.fg-hover-instant .fg-loaded .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:none}.foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-instant .fg-loaded .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,.foogallery.fg-hover-push .fg-loaded .fg-image-overlay{display:block;left:0;top:0;bottom:0;transform:translateX(100%);visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,.foogallery.fg-hover-push .fg-loaded .fg-thumb{transition-property:transform}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-caption{transform:translateY(0)}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-thumb,.foogallery.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-thumb{transform:translateX(-100%)}.foogallery.fg-hover-scale .fg-item{transition-property:transform;z-index:4}.foogallery.fg-hover-scale .fg-item:hover{transform:scale(1.048);z-index:10}.foogallery.fg-caption-hover.fg-hover-scale .fg-caption,.foogallery.fg-hover-scale .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-scale .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-scale .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-hover-zoomed .fg-image{transition-property:transform;z-index:4}.foogallery.fg-hover-zoomed .fg-item:hover .fg-image{transform:scale(1.15)}.foogallery.fg-hover-zoomed .fg-image-wrap{overflow:hidden}.foogallery.fg-caption-hover.fg-hover-zoomed .fg-caption,.foogallery.fg-hover-zoomed .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-zoomed .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-zoomed .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-left .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-right .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-up .fg-loaded .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:transform,background-color,opacity,visibility;visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-slide-left .fg-loaded .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-slide-right .fg-loaded .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-slide-up .fg-loaded .fg-item-inner:hover .fg-image-overlay{transform:translateY(0) translateX(0)}.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,.foogallery.fg-hover-slide-up .fg-loaded .fg-image-overlay{transform:translateY(100%)}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-image-overlay{transform:translateY(-100%)}.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,.foogallery.fg-hover-slide-left .fg-loaded .fg-image-overlay{transform:translateX(100%)}.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,.foogallery.fg-hover-slide-right .fg-loaded .fg-image-overlay{transform:translateX(-100%)}.fg-paging-container,.fg-paging-container *,.fg-paging-container :after,.fg-paging-container :before{box-sizing:border-box}.fg-paging-container{display:block;padding:15px;text-align:center;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fg-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.fg-paging-container .fg-dot-item,.fg-paging-container .fg-dots{display:inline-block;margin:0;padding:0;outline:0;list-style:none}.fg-paging-container .fg-dot-item .fg-dot-link{display:inline-block;margin:3px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;user-select:none;background-image:none;text-decoration:none;border:1px solid transparent;position:relative;border-radius:50%;padding:0;font-size:0;outline:0;color:transparent;box-shadow:none}.fg-paging-container .fg-dot-item .fg-dot-link:before{content:"";background-color:transparent;border:1px solid transparent;display:block;border-radius:50%;width:9px;height:9px;padding:0;margin:2px}.fg-paging-container .fg-dot-item .fg-dot-link:active,.fg-paging-container .fg-dot-item .fg-dot-link:focus,.fg-paging-container .fg-dot-item .fg-dot-link:hover{text-decoration:none;box-shadow:none;outline:0}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container .fg-dot-item.fg-selected .fg-dot-link{cursor:not-allowed;pointer-events:none}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link{cursor:not-allowed;pointer-events:none;outline:0}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link{background-color:#eee;border-color:#9d9d9d}.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link{border-color:#888}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#666;border-color:#888}.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#eee;border-color:#9d9d9d;opacity:.5}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link{background-color:#666;border-color:#333}.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link{border-color:#444}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#333;border-color:#444}.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#666;border-color:#333;opacity:.5}.fg-default:after{content:'';display:block;clear:both}.fg-default .fg-item,.fg-default .fg-item-inner,.fg-default .fg-thumb{display:inline-block;vertical-align:top;max-width:100%}.fg-default .fg-image{border-radius:0;display:block;max-width:100%;height:auto;margin:0;padding:0}.fg-default .fg-image{vertical-align:top}.fg-default.fg-left{text-align:left}.fg-default.fg-center{text-align:center}.fg-default.fg-right{text-align:right}.fg-default.fg-gutter-5{padding-left:5px;margin-bottom:-5px}.fg-default.fg-gutter-5 .fg-item{margin-right:5px;margin-bottom:5px}.fg-default.fg-gutter-10{padding-left:10px;margin-bottom:-10px}.fg-default.fg-gutter-10 .fg-item{margin-right:10px;margin-bottom:10px}.fg-default.fg-gutter-15{padding-left:15px;margin-bottom:-15px}.fg-default.fg-gutter-15 .fg-item{margin-right:15px;margin-bottom:15px}.fg-default.fg-gutter-20{padding-left:20px;margin-bottom:-20px}.fg-default.fg-gutter-20 .fg-item{margin-right:20px;margin-bottom:20px}.fg-default.fg-gutter-25{padding-left:25px;margin-bottom:-25px}.fg-default.fg-gutter-25 .fg-item{margin-right:25px;margin-bottom:25px}.fg-masonry *{box-sizing:border-box}.foogallery.fg-masonry.fg-center{margin:0 auto}.fg-masonry .fg-thumb{display:block}.fg-masonry.fg-masonry-fixed .fg-thumb{display:inline-block}.fg-masonry.fg-masonry-fixed .fg-image{max-width:100%}.fg-masonry .fg-column-width{display:inline-block;visibility:hidden;height:0;border:solid 0 transparent}.fg-masonry.fg-masonry-2col .fg-image,.fg-masonry.fg-masonry-3col .fg-image,.fg-masonry.fg-masonry-4col .fg-image,.fg-masonry.fg-masonry-5col .fg-image{width:100%;height:auto;max-width:100%}.fg-masonry .fg-item{line-height:0;font-size:0}.fg-masonry.fg-masonry-fixed .fg-column-width,.fg-masonry.fg-masonry-fixed .fg-item{max-width:100%}.fg-masonry.fg-masonry-2col .fg-item{margin-bottom:1%;width:49%}.fg-masonry.fg-masonry-2col .fg-column-width{width:49%}.fg-masonry.fg-masonry-2col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-item{margin-bottom:0;width:50%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-column-width{width:50%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-item{margin-bottom:3%;width:47%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-column-width{width:47%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-masonry-3col .fg-item{margin-bottom:1%;width:32%}.fg-masonry.fg-masonry-3col .fg-column-width{width:32%}.fg-masonry.fg-masonry-3col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item{margin-bottom:0;width:33%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width{width:33%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item{margin-bottom:3%;width:30%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width{width:30%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-masonry-4col .fg-item{margin-bottom:1%;width:24%}.fg-masonry.fg-masonry-4col .fg-column-width{width:24%}.fg-masonry.fg-masonry-4col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item{margin-bottom:0;width:25%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width{width:25%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item{margin-bottom:3%;width:22%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width{width:22%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:19%}.fg-masonry.fg-masonry-5col .fg-column-width{width:19%}.fg-masonry.fg-masonry-5col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:20%}.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:20%}.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:17%}.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:17%}.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:3%}@media screen and (max-width:720px){.fg-masonry.fg-masonry-4col .fg-item,.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:32%}.fg-masonry.fg-masonry-4col .fg-column-width,.fg-masonry.fg-masonry-5col .fg-column-width{width:32%}.fg-masonry.fg-masonry-4col .fg-gutter-width,.fg-masonry.fg-masonry-5col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:33%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:33%}.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:30%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:30%}.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:480px){.fg-masonry.fg-masonry-3col .fg-item,.fg-masonry.fg-masonry-4col .fg-item,.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:49%}.fg-masonry.fg-masonry-3col .fg-column-width,.fg-masonry.fg-masonry-4col .fg-column-width,.fg-masonry.fg-masonry-5col .fg-column-width{width:49%}.fg-masonry.fg-masonry-3col .fg-gutter-width,.fg-masonry.fg-masonry-4col .fg-gutter-width,.fg-masonry.fg-masonry-5col .fg-gutter-width{width:1%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:50%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:50%}.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:47%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:47%}.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:320px){.fg-masonry.fg-masonry-2col .fg-item,.fg-masonry.fg-masonry-3col .fg-item,.fg-masonry.fg-masonry-4col .fg-item,.fg-masonry.fg-masonry-5col .fg-item{margin-bottom:1%;width:100%}.fg-masonry.fg-masonry-2col .fg-column-width,.fg-masonry.fg-masonry-3col .fg-column-width,.fg-masonry.fg-masonry-4col .fg-column-width,.fg-masonry.fg-masonry-5col .fg-column-width{width:100%}.fg-masonry.fg-masonry-2col .fg-gutter-width,.fg-masonry.fg-masonry-3col .fg-gutter-width,.fg-masonry.fg-masonry-4col .fg-gutter-width,.fg-masonry.fg-masonry-5col .fg-gutter-width{width:0}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-item{margin-bottom:0;width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-column-width{width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-3col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-item,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-item{margin-bottom:3%;width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-column-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-column-width{width:100%}.fg-masonry.fg-masonry-2col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-3col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-4col.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-masonry-5col.fg-gutter-large .fg-gutter-width{width:0}}.foogallery.fg-border-thin .fg-column-width{border-width:4px}.foogallery.fg-border-medium .fg-column-width{border-width:10px}.foogallery.fg-border-thick .fg-column-width{border-width:16px}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption{visibility:visible;opacity:1;font-size:13px;position:relative;display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;text-transform:none;transform:none;transition:none;background-color:transparent;border-style:solid;border-color:transparent}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner:hover .fg-caption{transform:none;transition:none}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption-inner{display:block;position:relative;max-height:none;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;border:none;transform:none;transition:none}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption-inner:before{display:none}.foogallery.fg-masonry.fg-captions-bottom.fg-caption-hover .fg-item-inner .fg-image-overlay{display:block}.foogallery.fg-masonry.fg-captions-bottom.fg-caption-always .fg-item-inner:hover .fg-caption{visibility:visible;opacity:1}.fg-masonry.fg-captions-bottom .fg-caption-desc,.fg-masonry.fg-captions-bottom .fg-caption-title{text-align:left}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption,.fg-masonry.fg-captions-bottom.fg-light .fg-caption{color:#828282}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption a,.fg-masonry.fg-captions-bottom.fg-light .fg-caption a{color:#828282;border-bottom:1px solid #828282}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption a:hover,.fg-masonry.fg-captions-bottom.fg-light .fg-caption a:hover{border-bottom:none}.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title,.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title a{color:#222}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title,.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title a{color:#fff}.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title a{border-bottom:1px solid #222}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title a{border-bottom:1px solid #fff}.fg-masonry.fg-captions-bottom .fg-caption{border-width:10px}.fg-masonry.fg-captions-bottom .fg-caption-title+.fg-caption-desc{margin-top:4px}.fg-masonry.fg-captions-bottom.fg-border-thin .fg-caption{border-width:10px 4px 4px 4px}.fg-masonry.fg-captions-bottom.fg-border-medium .fg-caption{border-width:10px 0 0 0}.fg-masonry.fg-captions-bottom.fg-border-thick .fg-caption{border-width:16px 0 0 0}.fg-masonry.fg-captions-bottom.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-masonry.fg-transparent .fg-item-inner{background-color:transparent;color:#333;border-color:transparent}.fg-masonry.fg-transparent .fg-caption{color:#7f7f7f}.fg-masonry.fg-transparent.fg-captions-bottom .fg-caption{border-width:0;border-top-width:10px;border-bottom-width:10px}.fg-masonry.fg-transparent .fg-caption a{color:#7f7f7f;border-bottom:1px solid #7f7f7f}.fg-masonry.fg-transparent .fg-caption a:hover{border-bottom:none}.fg-masonry.fg-transparent .fg-caption-title,.fg-masonry.fg-transparent .fg-caption-title a{color:#333}.fg-masonry.fg-transparent .fg-caption-title a{border-bottom:1px solid #333}.fg-masonry.fg-transparent.fg-round-full .fg-item,.fg-masonry.fg-transparent.fg-round-full .fg-item-inner{border-radius:15px}.fg-masonry.fg-transparent.fg-round-full .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-full .fg-image-wrap,.fg-masonry.fg-transparent.fg-round-full.fg-shadow-inset-large .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-full.fg-shadow-inset-medium .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-full.fg-shadow-inset-small .fg-thumb:after{border-radius:50%;overflow:hidden}.fg-masonry.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap,.fg-masonry.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap,.fg-masonry.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{overflow:hidden}.fg-masonry.fg-transparent.fg-round-small.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-small.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-small.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:5px}.fg-masonry.fg-transparent.fg-round-medium.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-medium.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-medium.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:10px}.fg-masonry.fg-transparent.fg-round-large.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-large.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-large.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:15px}.fg-masonry.fg-transparent.fg-shadow-inset-small .fg-thumb:after{box-shadow:inset 0 1px 4px 0 rgba(0,0,0,.3)}.fg-masonry.fg-transparent.fg-shadow-inset-medium .fg-thumb:after{box-shadow:inset 0 1px 10px 0 rgba(0,0,0,.3)}.fg-masonry.fg-transparent.fg-shadow-inset-large .fg-thumb:after{box-shadow:inset 0 1px 16px 0 rgba(0,0,0,.3)}.fg-masonry.fg-transparent.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px rgba(128,128,128,.5)}.fg-masonry.fg-transparent.fg-shadow-small .fg-item-inner{box-shadow:0 1px 4px 0 rgba(128,128,128,.5)}.fg-masonry.fg-transparent.fg-shadow-medium .fg-item-inner{box-shadow:0 1px 10px 0 rgba(128,128,128,.5)}.fg-masonry.fg-transparent.fg-shadow-large .fg-item-inner{box-shadow:0 1px 16px 0 rgba(128,128,128,.5)}.fg-justified{box-sizing:border-box;position:relative}.foogallery.fg-justified .fg-image,.foogallery.fg-justified .fg-item,.foogallery.fg-justified .fg-item-inner,.foogallery.fg-justified .fg-thumb{box-sizing:border-box;display:block;margin:0;padding:0}.fg-justified .fg-item{visibility:visible;position:absolute}.fg-justified .fg-item-inner{position:relative;width:100%;height:100%}.fg-justified .fg-thumb{position:relative;overflow:hidden}.fg-justified .fg-image{z-index:1}.fg-justified .fg-item.fg-positioned .fg-image-wrap,.fg-justified .fg-item.fg-positioned .fg-thumb{width:100%;height:100%}.fg-justified .fg-item.fg-positioned .fg-image{width:100%;height:auto;min-height:100%;top:50%;transform:translateY(-50%)}.fg-justified.fg-hover-zoomed .fg-item.fg-positioned:hover .fg-image{transform:translateY(-50%) scale(1.15)}.fg-simple_portfolio{display:flex;flex-wrap:wrap;justify-content:center;align-items:stretch;align-content:center}.fg-simple_portfolio .fg-item{position:relative;flex:1;margin:10px;min-width:250px;max-width:250px}.fg-simple_portfolio .fg-item-inner{display:flex;flex-direction:column;margin:0;height:100%}.fg-simple_portfolio.fg-captions-top .fg-item-inner{flex-direction:column-reverse}.fg-simple_portfolio .fg-image{height:auto;width:100%}.fg-simple_portfolio .fg-thumb{min-width:auto;min-height:auto}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption{visibility:visible;opacity:1;font-size:13px;position:relative;display:block;top:auto;bottom:auto;left:auto;right:auto;width:100%;height:100%;text-transform:none;transform:none;transition:none;background-color:transparent;border-style:solid;border-color:transparent}.foogallery.fg-simple_portfolio .fg-item-inner:hover .fg-caption{transform:none;transition:none}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption-inner{display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;border:none;transform:none;transition:none}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption-inner:before{display:none}.foogallery.fg-simple_portfolio.fg-caption-hover .fg-item-inner .fg-image-overlay{display:block}.foogallery.fg-simple_portfolio.fg-caption-always .fg-item-inner:hover .fg-caption{visibility:visible;opacity:1}.fg-simple_portfolio .fg-caption-title{text-align:left}.fg-simple_portfolio .fg-caption-desc{text-align:left}.fg-simple_portfolio.fg-dark .fg-caption,.fg-simple_portfolio.fg-light .fg-caption{color:#828282}.fg-simple_portfolio.fg-dark .fg-caption a,.fg-simple_portfolio.fg-light .fg-caption a{color:#828282;border-bottom:1px solid #828282}.fg-simple_portfolio.fg-dark .fg-caption a:hover,.fg-simple_portfolio.fg-light .fg-caption a:hover{border-bottom:none}.fg-simple_portfolio.fg-light .fg-caption-title,.fg-simple_portfolio.fg-light .fg-caption-title a{color:#222}.fg-simple_portfolio.fg-dark .fg-caption-title,.fg-simple_portfolio.fg-dark .fg-caption-title a{color:#fff}.fg-simple_portfolio.fg-light .fg-caption-title a{border-bottom:1px solid #222}.fg-simple_portfolio.fg-dark .fg-caption-title a{border-bottom:1px solid #fff}.fg-simple_portfolio .fg-caption{border-width:0}.fg-simple_portfolio .fg-caption-title+.fg-caption-desc{margin-top:4px}.fg-simple_portfolio.fg-border-thin .fg-caption{border-width:10px 4px 4px 4px}.fg-simple_portfolio.fg-captions-top.fg-border-thin .fg-caption{border-width:4px 4px 10px 4px}.fg-simple_portfolio.fg-border-medium .fg-caption{border-width:10px 0 0 0}.fg-simple_portfolio.fg-captions-top.fg-border-medium .fg-caption{border-width:0 0 10px 0}.fg-simple_portfolio.fg-border-thick .fg-caption{border-width:16px 0 0 0}.fg-simple_portfolio.fg-captions-top.fg-border-thick .fg-caption{border-width:0 0 16px 0}.fg-simple_portfolio.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-simple_portfolio.fg-transparent .fg-item-inner{background-color:transparent;color:#333;border-color:transparent}.fg-simple_portfolio.fg-transparent .fg-caption{color:#7f7f7f}.fg-simple_portfolio.fg-transparent .fg-caption a{color:#7f7f7f;border-bottom:1px solid #7f7f7f}.fg-simple_portfolio.fg-transparent .fg-caption a:hover{border-bottom:none}.fg-simple_portfolio.fg-transparent .fg-caption-title,.fg-simple_portfolio.fg-transparent .fg-caption-title a{color:#333}.fg-simple_portfolio.fg-transparent .fg-caption-title a{border-bottom:1px solid #333}.fg-simple_portfolio.fg-transparent.fg-round-full .fg-item,.fg-simple_portfolio.fg-transparent.fg-round-full .fg-item-inner{border-radius:15px}.fg-simple_portfolio.fg-transparent.fg-round-full .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-full .fg-image-wrap,.fg-simple_portfolio.fg-transparent.fg-round-full.fg-shadow-inset-large .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-full.fg-shadow-inset-medium .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-full.fg-shadow-inset-small .fg-thumb:after{border-radius:50%;overflow:hidden}.fg-simple_portfolio.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap,.fg-simple_portfolio.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap,.fg-simple_portfolio.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{overflow:hidden}.fg-simple_portfolio.fg-transparent.fg-round-small.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-small.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-small.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:5px}.fg-simple_portfolio.fg-transparent.fg-round-medium.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-medium.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-medium.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:10px}.fg-simple_portfolio.fg-transparent.fg-round-large.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-large.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-large.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:15px}.fg-simple_portfolio.fg-transparent.fg-shadow-inset-small .fg-thumb:after{box-shadow:inset 0 1px 4px 0 rgba(0,0,0,.3)}.fg-simple_portfolio.fg-transparent.fg-shadow-inset-medium .fg-thumb:after{box-shadow:inset 0 1px 10px 0 rgba(0,0,0,.3)}.fg-simple_portfolio.fg-transparent.fg-shadow-inset-large .fg-thumb:after{box-shadow:inset 0 1px 16px 0 rgba(0,0,0,.3)}.fg-simple_portfolio.fg-transparent.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px rgba(128,128,128,.5)}.fg-simple_portfolio.fg-transparent.fg-shadow-small .fg-item-inner{box-shadow:0 1px 4px 0 rgba(128,128,128,.5)}.fg-simple_portfolio.fg-transparent.fg-shadow-medium .fg-item-inner{box-shadow:0 1px 10px 0 rgba(128,128,128,.5)}.fg-simple_portfolio.fg-transparent.fg-shadow-large .fg-item-inner{box-shadow:0 1px 16px 0 rgba(128,128,128,.5)}.foogallery.fg-preset.fg-polaroid .fg-item{-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .35s,background-color .65s}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(2n+1){-webkit-transform:rotate(3deg);transform:rotate(3deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(2n){-webkit-transform:rotate(-3deg);transform:rotate(-3deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(3n){-webkit-transform:rotate(1deg);transform:rotate(1deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(5n){-webkit-transform:rotate(-2deg);transform:rotate(-2deg)}.foogallery.fg-preset.fg-polaroid .fg-item:hover{-webkit-transform:rotate(0);transform:rotate(0)}.foogallery.fg-preset.fg-polaroid .fg-caption{position:relative;width:auto;font-family:"Segoe Print Regular",-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}.foogallery.fg-preset.fg-polaroid .fg-caption-inner,.foogallery.fg-preset.fg-polaroid .fg-caption-title{position:relative;width:auto}.foogallery.fg-preset.fg-polaroid .fg-caption-title{text-align:center}.foogallery.fg-preset.fg-polaroid .fg-caption-desc{display:none}.foogallery.fg-light.fg-preset.fg-polaroid .fg-caption-title,.foogallery.fg-preset.fg-polaroid .fg-caption-title{color:#333}.foogallery.fg-dark.fg-preset.fg-polaroid .fg-caption-title{color:#fff}.foogallery.fg-preset.fg-polaroid .fg-caption{border-style:solid;border-color:transparent;border-width:10px}.foogallery.fg-preset.fg-polaroid .fg-caption-title+.fg-caption-desc{margin-top:4px}.foogallery.fg-preset.fg-polaroid.fg-border-thin .fg-caption{border-width:10px 4px 4px 4px}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-thin .fg-caption{border-width:4px 4px 10px 4px}.foogallery.fg-preset.fg-polaroid.fg-border-medium .fg-caption{border-width:10px 0 0 0}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-medium .fg-caption{border-width:0 0 10px 0}.foogallery.fg-preset.fg-polaroid.fg-border-thick .fg-caption{border-width:16px 0 0 0}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-thick .fg-caption{border-width:0 0 16px 0}.foogallery.fg-preset.fg-polaroid.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-image-viewer{display:block;font-family:'Open Sans','Helvetica Neue',Arial,sans-serif}.fg-image-viewer.fg-left{text-align:left}.fg-image-viewer.fg-center{text-align:center}.fg-image-viewer.fg-right{text-align:right}.fiv-inner{position:relative;display:inline-block;max-width:100%;overflow:hidden;z-index:6}.fiv-inner .fiv-inner-container{position:relative;overflow:hidden;max-width:100%;border-style:solid;border-width:0;border-bottom-width:4px;z-index:5}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:active,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:hover,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:visited{position:relative;display:block;border:none;outline:0;text-decoration:none;box-shadow:none;max-width:100%}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item{position:absolute;visibility:visible;opacity:1;border:none;outline:0;text-decoration:none;box-shadow:none;max-width:100%}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item:first-of-type{position:relative}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb img{display:block;max-width:100%;height:auto;border:none;outline:0;text-decoration:none}.fg-image-viewer .fiv-inner .fiv-ctrls{display:block;text-align:center;font-size:14px;border-style:solid;line-height:34px}.fg-image-viewer .fiv-inner .fiv-ctrls:after{content:'';display:block;clear:both}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-count{display:inline-block;font-weight:400;margin:0}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;min-width:80px;position:relative;overflow:hidden;transition:background-color .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:before,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:before{display:block;position:absolute;font-size:24px;line-height:30px;top:0;left:0;width:100%;transform:translateY(0);transition:transform .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:hover:before,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:hover:before{transform:translateY(-100%)}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next span,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev span{display:block;width:100%;transform:translateY(100%);transition:transform .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:hover span,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:hover span{transform:translateY(0)}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev{float:left}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:before{content:'\2190'}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next{float:right}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:before{content:'\2192'}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-count span{margin:0 4px}/*!* Theme - Default (Light) *!*//*!* Theme - Dark *!*/.foogallery.fg-image-viewer.fg-caption-always .fg-item-inner .fg-caption{padding:0;border:none;background:#000;background:-moz-linear-gradient(left,rgba(0,0,0,.8) 0,rgba(0,0,0,.8) 60%,rgba(0,0,0,0) 100%);background:-webkit-linear-gradient(left,rgba(0,0,0,.8) 0,rgba(0,0,0,.8) 60%,rgba(0,0,0,0) 100%);background:linear-gradient(to right,rgba(0,0,0,.8) 0,rgba(0,0,0,.8) 60%,rgba(0,0,0,0) 100%)}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-title{padding:10px 10px 10px 10px}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-desc{padding:10px 10px 10px 10px}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-title+.fg-caption-desc{padding:0 10px 10px 10px}.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-count,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-prev,.fg-image-viewer.fg-light .fiv-inner .fiv-inner-container{background-color:#fff;color:#333;border-color:#fff}.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-next:hover,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-prev:hover{background-color:#f2f2f2}.fg-image-viewer.fg-light .fiv-next,.fg-image-viewer.fg-light .fiv-prev{box-shadow:inset 0 0 0 1px #ddd}.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-count,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-prev,.fg-image-viewer.fg-dark .fiv-inner .fiv-inner-container{background-color:#333;color:#fff;border-color:#333}.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-next:hover,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-prev:hover{background-color:#444}.fg-image-viewer.fg-dark .fiv-next,.fg-image-viewer.fg-dark .fiv-prev{box-shadow:inset 0 0 0 1px #222}.foogallery.fg-image-viewer.fg-border-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin .fg-item-inner{border-width:0}.foogallery.fg-image-viewer .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thin .fiv-inner-container{border-width:4px}.foogallery.fg-image-viewer.fg-border-medium .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-medium .fiv-inner-container{border-width:10px}.foogallery.fg-image-viewer.fg-border-thick .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thick .fiv-inner-container{border-width:16px}.foogallery.fg-image-viewer .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-medium .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thick .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thin .fiv-ctrls{border-top-width:1px}.foogallery.fg-image-viewer.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-round-small .fiv-inner{border-radius:5px}.foogallery.fg-image-viewer.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-round-small .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-round-small .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fiv-prev,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fiv-prev,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-round-medium .fiv-inner{border-radius:10px}.foogallery.fg-image-viewer.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-round-medium .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-round-medium .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fiv-prev,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-round-large .fiv-inner{border-radius:15px}.foogallery.fg-image-viewer.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-round-large .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-round-large .fiv-prev{border-radius:11px}.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fiv-prev{border-radius:11px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-full .fiv-inner,.foogallery.fg-image-viewer.fg-round-full .fiv-next,.foogallery.fg-image-viewer.fg-round-full .fiv-prev{border-radius:50%}.foogallery.fg-image-viewer.fg-dark.fg-shadow-large .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-outline .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-small .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-large .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-outline .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-small .fg-item-inner{box-shadow:none}.foogallery.fg-image-viewer.fg-light.fg-shadow-outline .fiv-inner{box-shadow:0 0 0 1px #ddd}.foogallery.fg-image-viewer.fg-dark.fg-shadow-outline .fiv-inner{box-shadow:0 0 0 1px #222}.foogallery.fg-image-viewer.fg-dark.fg-shadow-small .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-small .fiv-inner{box-shadow:0 1px 4px 0 rgba(0,0,0,.5)}.foogallery.fg-image-viewer.fg-dark.fg-shadow-medium .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-medium .fiv-inner{box-shadow:0 1px 10px 0 rgba(0,0,0,.5)}.foogallery.fg-image-viewer.fg-dark.fg-shadow-large .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-large .fiv-inner{box-shadow:0 1px 16px 0 rgba(0,0,0,.5)}.foogallery.fg-thumbnail,.foogallery.fg-thumbnail.fg-center{text-align:center}.foogallery.fg-thumbnail.fg-left{text-align:left}.foogallery.fg-thumbnail.fg-right{text-align:right}.foogallery.fg-thumbnail.fg-float-left{float:left;width:auto}.foogallery.fg-thumbnail.fg-float-right{float:right;width:auto}.foogallery.fg-thumbnail .fg-item{display:inline-block;vertical-align:top;max-width:100%}.foogallery.fg-thumbnail .fg-image{max-width:100%}.foogallery.fg-thumbnail .fg-st-hidden{display:none}.foogallery-stack-album{text-align:center;overflow:hidden;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:13px;font-weight:400;line-height:1.3}.foogallery-stack-album,.foogallery-stack-album *{box-sizing:border-box}.foogallery-stack-album.fg-align-left{text-align:left}.foogallery-stack-album.fg-align-center{text-align:center}.foogallery-stack-album.fg-align-right{text-align:right}.foogallery-stack-album.fg-disable-transitions,.foogallery-stack-album.fg-disable-transitions *{transition:none!important}.fg-header{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;position:relative;padding:0;margin:0;border-top:solid 1px #aaa;border-bottom:solid 1px #aaa}.fg-header-title{display:block;margin:0;padding:0 20px;width:100%;text-align:left}.fg-header-active{display:block;margin:0;padding:0 20px;visibility:hidden;opacity:0;width:100%;text-align:right;transition-property:opacity,visibility;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-header-back{display:block;padding:0;margin:5px;visibility:hidden;opacity:0;min-width:40px;width:40px;height:40px;border-radius:50%;text-align:center;line-height:38px;color:#999;background:#ddd;background:rgba(200,200,200,.5);cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition-property:opacity,visibility;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-has-active .fg-header-active,.fg-has-active .fg-header-back{visibility:visible;opacity:1}.fg-piles{display:inline-block;position:relative;transition-property:width,height;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-pile{display:block;position:absolute;top:0;left:0;list-style:none;padding:0;margin:0;visibility:visible;opacity:1;transition-property:opacity,visibility,top,left,width,height;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-pile.fg-hidden{visibility:hidden;opacity:0}.fg-pile-item{display:block;position:absolute;top:25px;left:25px;visibility:visible;opacity:1;cursor:pointer;border:10px solid #fff;background-color:#fff;box-shadow:0 1px 4px rgba(0,0,0,.2);transition-property:opacity,visibility,top,left,transform;transition-duration:.3s;transition-timing-function:ease-in-out;z-index:1;transform:rotate(0)}.fg-expanded .fg-pile-item{z-index:2;transform:rotate(0)!important}.fg-pile-item.fg-has-cover{z-index:10;transform:rotate(0)!important}.fg-pile-item:nth-child(2){z-index:9}.fg-pile-item:nth-child(3){z-index:8}.fg-pile-item:nth-child(4){z-index:7}.fg-pile-item:nth-child(1n+5){visibility:hidden;opacity:0}.fg-expanded .fg-pile-item:nth-child(1n+4){visibility:visible;opacity:1}.fg-pile-item-thumb{display:block}.fg-pile-item-image{display:block}.fg-pile-item-caption{display:flex;justify-content:center;flex-direction:column;position:absolute;top:0;left:0;bottom:0;right:0;width:100%;height:100%;margin:0;padding:10px;background-color:rgba(68,68,68,.5);color:#fff;text-align:center;visibility:hidden;opacity:0;transition-property:opacity,visibility;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-pile-item-title{display:block;width:100%;padding:0 0 10px}.fg-pile-item-desc{display:block;width:100%;max-height:100%;border-top:solid 1px currentColor;padding:10px 0 0;overflow:hidden}.fg-pile-item-thumb:hover .fg-pile-item-caption{visibility:visible;opacity:1}.fg-pile-cover{display:flex;justify-content:left;align-items:center;position:absolute;top:0;left:0;bottom:0;right:0;width:100%;height:100%;visibility:visible;opacity:1;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition-property:opacity,visibility;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-expanded .fg-pile-cover{visibility:hidden;opacity:0;pointer-events:none}.fg-pile-cover-content{display:flex;position:relative;background:#fff;color:#333;width:75%;font-weight:700;box-shadow:1px 1px 1px rgba(0,0,0,.1),5px 0 5px -3px rgba(0,0,0,.4),inset 0 0 5px rgba(0,0,0,.04)}.fg-pile-cover-title{text-align:center;padding:10px;width:100%}.fg-pile-cover-count{color:#aaa;padding:10px 5px;background:#f7f7f7;height:100%}
1
+ .foogallery,.foogallery *{box-sizing:border-box}.foogallery{display:block;z-index:1;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;position:relative;line-height:0;font-size:0;width:100%;max-width:100%}.foogallery .fg-item{display:inline-block;position:relative;background-color:transparent;z-index:2;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.foogallery .fg-item.fg-hidden{display:none!important}.foogallery .fg-item-inner{display:block;position:relative;visibility:hidden;overflow:hidden;opacity:0;z-index:3;margin:0;border:solid 0 transparent}.foogallery .fg-item.fg-error:before{content:"";display:block;position:absolute;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);width:32px;height:32px;background-image:url(../img/icons.svg#image);background-color:transparent;background-repeat:no-repeat;background-position:center center;background-size:32px 32px}.foogallery .fg-item.fg-loaded{z-index:4}.foogallery .fg-loaded .fg-item-inner{visibility:visible;opacity:1;z-index:5}.foogallery .fg-error .fg-item-inner{pointer-events:none;cursor:default}.foogallery .fg-thumb{display:block;position:relative;border:none;outline:0;text-decoration:none;z-index:4;box-shadow:none}.foogallery .fg-thumb:focus,.foogallery .fg-thumb:hover{border:none;outline:0;text-decoration:none;box-shadow:none}.foogallery .fg-image-overlay{position:absolute;top:0;right:0;bottom:0;left:0;z-index:8;visibility:hidden;opacity:0}.foogallery .fg-image-wrap{display:block;position:relative}.foogallery .fg-image{display:block;position:relative;border:none;outline:0;text-decoration:none;z-index:5;max-width:none;height:auto;margin:0}.foogallery .fg-loaded .fg-thumb{z-index:6}.foogallery .fg-loaded .fg-image{z-index:7}.foogallery.fg-light .fg-item-inner{background-color:#fff;color:#333;border-color:#fff}.foogallery.fg-dark .fg-item-inner{background-color:#333;color:#fff;border-color:#333}.foogallery.fg-light .fg-item.fg-error,.foogallery.fg-light .fg-item.fg-idle,.foogallery.fg-light .fg-item.fg-loading{background-color:#eee;box-shadow:inset 0 0 0 1px #ddd}.foogallery.fg-dark .fg-item.fg-error,.foogallery.fg-dark .fg-item.fg-idle,.foogallery.fg-dark .fg-item.fg-loading{background-color:#444;box-shadow:inset 0 0 0 1px #333}.foogallery .fg-caption{background-color:rgba(0,0,0,.6);color:#fff}.foogallery .fg-caption a{color:#fff;border-bottom:1px solid #fff}.foogallery.fg-light-overlays .fg-caption{background-color:rgba(255,255,255,.8);color:#333}.foogallery.fg-light-overlays .fg-caption a{color:#333;border-bottom-color:#333}.foogallery.fg-transparent-overlays .fg-caption{background-color:transparent;color:#fff}.foogallery.fg-transparent-overlays .fg-caption a{color:#fff;border-bottom-color:#fff}.foogallery .fg-image-overlay{background-color:rgba(0,0,0,.6);color:#fff}.foogallery.fg-light-overlays .fg-image-overlay{background-color:rgba(255,255,255,.8);color:#333}.foogallery.fg-transparent-overlays .fg-image-overlay{background-color:transparent;color:#fff}.fg-exif-light .fg-item.fg-item-exif .fg-image-wrap:after{background-color:#fff;color:#333}.fg-exif-dark .fg-item.fg-item-exif .fg-image-wrap:after{background-color:#333;color:#fff}.fg-exif-rounded .fg-item.fg-item-exif .fg-image-wrap:after{border-radius:3px}.fg-exif-bottom-left .fg-item.fg-item-exif .fg-image-wrap:after,.fg-exif-bottom-right .fg-item.fg-item-exif .fg-image-wrap:after,.fg-exif-top-left .fg-item.fg-item-exif .fg-image-wrap:after,.fg-exif-top-right .fg-item.fg-item-exif .fg-image-wrap:after{display:inline-block;position:absolute;content:'EXIF';font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:11px;line-height:10px;padding:3px 4px;z-index:7}.fg-exif-bottom-right .fg-item.fg-item-exif .fg-image-wrap:after{bottom:5px;right:5px}.fg-exif-bottom-left .fg-item.fg-item-exif .fg-image-wrap:after{bottom:5px;left:5px}.fg-exif-top-right .fg-item.fg-item-exif .fg-image-wrap:after{top:5px;right:5px}.fg-exif-top-left .fg-item.fg-item-exif .fg-image-wrap:after{top:5px;left:5px}.foogallery.fg-border-thin .fg-item-inner{border-width:4px}.foogallery.fg-border-medium .fg-item-inner{border-width:10px}.foogallery.fg-border-thick .fg-item-inner{border-width:16px}.foogallery.fg-light.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px #ddd}.foogallery.fg-dark.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px #222}.foogallery.fg-dark.fg-shadow-small .fg-item-inner,.foogallery.fg-light.fg-shadow-small .fg-item-inner{box-shadow:0 1px 4px 0 rgba(0,0,0,.5)}.foogallery.fg-dark.fg-shadow-medium .fg-item-inner,.foogallery.fg-light.fg-shadow-medium .fg-item-inner{box-shadow:0 1px 10px 0 rgba(0,0,0,.5)}.foogallery.fg-dark.fg-shadow-large .fg-item-inner,.foogallery.fg-light.fg-shadow-large .fg-item-inner{box-shadow:0 1px 16px 0 rgba(0,0,0,.5)}.foogallery.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-shadow-inset-small .fg-thumb:after{display:block;content:"";position:absolute;top:0;left:0;right:0;bottom:0;z-index:7}.foogallery.fg-dark.fg-shadow-inset-small .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-small .fg-thumb:after{box-shadow:inset 0 1px 4px 0 rgba(0,0,0,.3)}.foogallery.fg-dark.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-medium .fg-thumb:after{box-shadow:inset 0 1px 10px 0 rgba(0,0,0,.3)}.foogallery.fg-dark.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-light.fg-shadow-inset-large .fg-thumb:after{box-shadow:inset 0 1px 16px 0 rgba(0,0,0,.3)}.foogallery.fg-round-full.fg-shadow-inset-large .fg-thumb:after,.foogallery.fg-round-full.fg-shadow-inset-medium .fg-thumb:after,.foogallery.fg-round-full.fg-shadow-inset-small .fg-thumb:after{border-radius:50%}.foogallery.fg-round-small .fg-item,.foogallery.fg-round-small .fg-item-inner{border-radius:5px}.foogallery.fg-round-medium .fg-item,.foogallery.fg-round-medium .fg-item-inner{border-radius:10px}.foogallery.fg-round-large .fg-item,.foogallery.fg-round-large .fg-item-inner{border-radius:15px}.foogallery.fg-round-full .fg-item,.foogallery.fg-round-full .fg-item-inner{border-radius:50%}.foogallery .fg-loader{position:absolute;top:50%;left:50%;margin-top:-.5em;margin-left:-.5em;width:1em;height:1em;font-size:5px;visibility:hidden;opacity:0;pointer-events:none}.foogallery .fg-loading .fg-loader{visibility:visible;opacity:1}.fg-loading-default .fg-loader{border-radius:50%;text-indent:-9999em;box-shadow:0 -2.6em 0 0 rgba(130,130,130,1),1.8em -1.8em 0 0 rgba(130,130,130,.2),2.5em 0 0 0 rgba(130,130,130,.2),1.75em 1.75em 0 0 rgba(130,130,130,.2),0 2.5em 0 0 rgba(130,130,130,.2),-1.8em 1.8em 0 0 rgba(130,130,130,.2),-2.6em 0 0 0 rgba(130,130,130,.5),-1.8em -1.8em 0 0 rgba(130,130,130,.7);-webkit-animation:loading-default 1.1s infinite paused steps(8,start);animation:loading-default 1.1s infinite paused steps(8,start)}.fg-loading-default .fg-loading .fg-loader{-webkit-animation-play-state:running;animation-play-state:running}@-webkit-keyframes loading-default{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes loading-default{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.fg-loading-bars .fg-loader,.fg-loading-bars .fg-loader:after,.fg-loading-bars .fg-loader:before{background:rgba(130,130,130,1);width:1em;height:4em;-webkit-animation:loading-bars 1s infinite paused ease-in-out;animation:loading-bars 1s infinite paused ease-in-out}.fg-loading-bars .fg-loading .fg-loader,.fg-loading-bars .fg-loading .fg-loader:after,.fg-loading-bars .fg-loading .fg-loader:before{-webkit-animation-play-state:running;animation-play-state:running}.fg-loading-bars .fg-loader{color:rgba(130,130,130,1);text-indent:-9999em;font-size:4px;margin-top:-2em;margin-left:-.5em;-webkit-animation-delay:-.16s;animation-delay:-.16s}.fg-loading-bars .fg-loader:after,.fg-loading-bars .fg-loader:before{position:absolute;top:0;content:''}.fg-loading-bars .fg-loader:before{left:-1.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.fg-loading-bars .fg-loader:after{left:1.5em}@-webkit-keyframes loading-bars{0%,100%,80%{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}@keyframes loading-bars{0%,100%,80%{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}.fg-loading-trail .fg-loader{color:#828282;margin-top:0;margin-left:0;font-size:20px;text-indent:-9999em;overflow:hidden;border-radius:50%;-webkit-animation:loading-trail-1 1.7s infinite paused ease,loading-trail-2 1.7s infinite paused ease;animation:loading-trail-1 1.7s infinite paused ease,loading-trail-2 1.7s infinite paused ease}.fg-loading-trail .fg-loading .fg-loader{-webkit-animation-play-state:running;animation-play-state:running}@-webkit-keyframes loading-trail-1{0%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}5%,95%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}10%,59%{box-shadow:0 -.83em 0 -.4em,-.087em -.825em 0 -.42em,-.173em -.812em 0 -.44em,-.256em -.789em 0 -.46em,-.297em -.775em 0 -.477em}20%{box-shadow:0 -.83em 0 -.4em,-.338em -.758em 0 -.42em,-.555em -.617em 0 -.44em,-.671em -.488em 0 -.46em,-.749em -.34em 0 -.477em}38%{box-shadow:0 -.83em 0 -.4em,-.377em -.74em 0 -.42em,-.645em -.522em 0 -.44em,-.775em -.297em 0 -.46em,-.82em -.09em 0 -.477em}100%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}}@keyframes loading-trail-1{0%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}5%,95%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}10%,59%{box-shadow:0 -.83em 0 -.4em,-.087em -.825em 0 -.42em,-.173em -.812em 0 -.44em,-.256em -.789em 0 -.46em,-.297em -.775em 0 -.477em}20%{box-shadow:0 -.83em 0 -.4em,-.338em -.758em 0 -.42em,-.555em -.617em 0 -.44em,-.671em -.488em 0 -.46em,-.749em -.34em 0 -.477em}38%{box-shadow:0 -.83em 0 -.4em,-.377em -.74em 0 -.42em,-.645em -.522em 0 -.44em,-.775em -.297em 0 -.46em,-.82em -.09em 0 -.477em}100%{box-shadow:0 -.83em 0 -.4em,0 -.83em 0 -.42em,0 -.83em 0 -.44em,0 -.83em 0 -.46em,0 -.83em 0 -.477em}}@-webkit-keyframes loading-trail-2{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}@keyframes loading-trail-2{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}.fg-loading-pulse .fg-loader,.fg-loading-pulse .fg-loader:after,.fg-loading-pulse .fg-loader:before{border-radius:50%;width:2.5em;height:2.5em;-webkit-animation:loading-pulse 1.8s infinite both paused ease-in-out;animation:loading-pulse 1.8s infinite both paused ease-in-out}.fg-loading-pulse .fg-loading .fg-loader,.fg-loading-pulse .fg-loading .fg-loader:after,.fg-loading-pulse .fg-loading .fg-loader:before{-webkit-animation-play-state:running;animation-play-state:running}.fg-loading-pulse .fg-loader{color:#828282;font-size:4px;margin-top:-3.75em;margin-left:-1.25em;text-indent:-9999em;-webkit-animation-delay:-.16s;animation-delay:-.16s}.fg-loading-pulse .fg-loader:after,.fg-loading-pulse .fg-loader:before{content:'';position:absolute;top:0}.fg-loading-pulse .fg-loader:before{left:-3.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.fg-loading-pulse .fg-loader:after{left:3.5em}@-webkit-keyframes loading-pulse{0%,100%,80%{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}@keyframes loading-pulse{0%,100%,80%{box-shadow:0 2.5em 0 -1.3em}40%{box-shadow:0 2.5em 0 0}}.fg-loading-dots .fg-loader{color:#828282;font-size:5px;border-radius:50%;text-indent:-9999em;-webkit-animation:loading-dots 1.3s infinite paused linear;animation:loading-dots 1.3s infinite paused linear}.fg-loading-dots .fg-loading .fg-loader{-webkit-animation-play-state:running;animation-play-state:running}@-webkit-keyframes loading-dots{0%,100%{box-shadow:0 -3em 0 .2em,2em -2em 0 0,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 0}12.5%{box-shadow:0 -3em 0 0,2em -2em 0 .2em,3em 0 0 0,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}25%{box-shadow:0 -3em 0 -.5em,2em -2em 0 0,3em 0 0 .2em,2em 2em 0 0,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}37.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 0,2em 2em 0 .2em,0 3em 0 0,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}50%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 0,0 3em 0 .2em,-2em 2em 0 0,-3em 0 0 -1em,-2em -2em 0 -1em}62.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 0,-2em 2em 0 .2em,-3em 0 0 0,-2em -2em 0 -1em}75%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 .2em,-2em -2em 0 0}87.5%{box-shadow:0 -3em 0 0,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 0,-2em -2em 0 .2em}}@keyframes loading-dots{0%,100%{box-shadow:0 -3em 0 .2em,2em -2em 0 0,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 0}12.5%{box-shadow:0 -3em 0 0,2em -2em 0 .2em,3em 0 0 0,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}25%{box-shadow:0 -3em 0 -.5em,2em -2em 0 0,3em 0 0 .2em,2em 2em 0 0,0 3em 0 -1em,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}37.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 0,2em 2em 0 .2em,0 3em 0 0,-2em 2em 0 -1em,-3em 0 0 -1em,-2em -2em 0 -1em}50%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 0,0 3em 0 .2em,-2em 2em 0 0,-3em 0 0 -1em,-2em -2em 0 -1em}62.5%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 0,-2em 2em 0 .2em,-3em 0 0 0,-2em -2em 0 -1em}75%{box-shadow:0 -3em 0 -1em,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 .2em,-2em -2em 0 0}87.5%{box-shadow:0 -3em 0 0,2em -2em 0 -1em,3em 0 0 -1em,2em 2em 0 -1em,0 3em 0 -1em,-2em 2em 0 0,-3em 0 0 0,-2em -2em 0 .2em}}.fg-loading-partial .fg-loader,.fg-loading-partial .fg-loader:after{border-radius:50%;width:10em;height:10em}.fg-loading-partial .fg-loader{font-size:4px;text-indent:-9999em;margin-top:0;margin-left:0;border-top:1.1em solid rgba(130,130,130,.2);border-right:1.1em solid rgba(130,130,130,.2);border-bottom:1.1em solid rgba(130,130,130,.2);border-left:1.1em solid #828282;-webkit-animation:loading-partial 1.1s infinite paused linear;animation:loading-partial 1.1s infinite paused linear}.fg-loading-partial .fg-loading .fg-loader{-webkit-animation-play-state:running;animation-play-state:running}@-webkit-keyframes loading-partial{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}@keyframes loading-partial{0%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(0);transform:translateX(-50%) translateY(-50%) rotate(0)}100%{-webkit-transform:translateX(-50%) translateY(-50%) rotate(360deg);transform:translateX(-50%) translateY(-50%) rotate(360deg)}}.foogallery.fg-loaded-drop .fg-item.fg-loaded,.foogallery.fg-loaded-fade-in .fg-item.fg-loaded,.foogallery.fg-loaded-flip .fg-item.fg-loaded,.foogallery.fg-loaded-fly .fg-item.fg-loaded,.foogallery.fg-loaded-scale-up .fg-item.fg-loaded,.foogallery.fg-loaded-slide-down .fg-item.fg-loaded,.foogallery.fg-loaded-slide-left .fg-item.fg-loaded,.foogallery.fg-loaded-slide-right .fg-item.fg-loaded,.foogallery.fg-loaded-slide-up .fg-item.fg-loaded,.foogallery.fg-loaded-swing-down .fg-item.fg-loaded{transition-timing-function:ease;transition-duration:650ms;transition-property:background-color,transform}.foogallery.fg-loaded-drop .fg-loaded .fg-item-inner,.foogallery.fg-loaded-fade-in .fg-loaded .fg-item-inner,.foogallery.fg-loaded-flip .fg-loaded .fg-item-inner,.foogallery.fg-loaded-fly .fg-loaded .fg-item-inner,.foogallery.fg-loaded-scale-up .fg-loaded .fg-item-inner,.foogallery.fg-loaded-slide-down .fg-loaded .fg-item-inner,.foogallery.fg-loaded-slide-left .fg-loaded .fg-item-inner,.foogallery.fg-loaded-slide-right .fg-loaded .fg-item-inner,.foogallery.fg-loaded-slide-up .fg-loaded .fg-item-inner,.foogallery.fg-loaded-swing-down .fg-loaded .fg-item-inner{transition-timing-function:ease;transition-duration:650ms}.foogallery.fg-loaded-drop .fg-item.fg-loaded,.foogallery.fg-loaded-flip .fg-item.fg-loaded,.foogallery.fg-loaded-fly .fg-item.fg-loaded,.foogallery.fg-loaded-swing-down .fg-item.fg-loaded{perspective:1300px}.foogallery.fg-loaded-drop .fg-item-inner{transition-property:visibility,opacity,transform;transform-style:preserve-3d;transform:translateZ(400px) translateY(100%) rotateX(-90deg)}.foogallery.fg-loaded-drop .fg-loaded .fg-item-inner{transform:translateZ(0) translateY(0) rotateX(0)}.foogallery.fg-loaded-fade-in .fg-item-inner{transition-property:visibility,opacity}.foogallery.fg-loaded-flip .fg-item-inner{transition-property:visibility,opacity,transform;backface-visibility:hidden;transform-style:preserve-3d;transform:rotateY(-180deg)}.foogallery.fg-loaded-flip .fg-loaded .fg-item-inner{transform:rotateY(0)}.foogallery.fg-loaded-fly .fg-item-inner{transition-property:visibility,opacity,transform;transform-style:preserve-3d;transform-origin:50% 50% -300px;transform:rotateX(-180deg)}.foogallery.fg-loaded-fly .fg-loaded .fg-item-inner{transform:rotateX(0)}.foogallery.fg-loaded-scale-up .fg-item-inner{transition-property:visibility,opacity,transform;transform:scale(.6)}.foogallery.fg-loaded-scale-up .fg-loaded .fg-item-inner{transform:scale(1)}.foogallery.fg-loaded-slide-up .fg-item-inner{transition-property:visibility,opacity,transform;transform:translateY(50%)}.foogallery.fg-loaded-slide-up .fg-loaded .fg-item-inner{transform:translateY(0)}.foogallery.fg-loaded-slide-down .fg-item-inner{transition-property:visibility,opacity,transform;transform:translateY(-50%)}.foogallery.fg-loaded-slide-down .fg-loaded .fg-item-inner{transform:translateY(0)}.foogallery.fg-loaded-slide-left .fg-item-inner{transition-property:visibility,opacity,transform;transform:translateX(50%)}.foogallery.fg-loaded-slide-left .fg-loaded .fg-item-inner{transform:translateX(0)}.foogallery.fg-loaded-slide-right .fg-item-inner{transition-property:visibility,opacity,transform;transform:translateX(-50%)}.foogallery.fg-loaded-slide-right .fg-loaded .fg-item-inner{transform:translateX(0)}.foogallery.fg-loaded-swing-down .fg-item-inner{transition-property:visibility,opacity,transform;transform-style:preserve-3d;transform-origin:0 0;transform:rotateX(-80deg)}.foogallery.fg-loaded-swing-down .fg-loaded .fg-item-inner{transform:rotateX(0)}.foogallery .fg-caption{visibility:hidden;opacity:0;position:absolute;z-index:8;width:100%;max-height:100%;overflow:hidden;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:13px;font-weight:400;line-height:1.3;border:none;text-align:center;cursor:pointer;margin:0}.foogallery .fg-caption a{text-decoration:none}.foogallery .fg-caption a:hover{border-bottom:none}.foogallery .fg-caption-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:16px;font-weight:400;padding:5px}.foogallery .fg-caption-desc{padding:5px}.foogallery .fg-caption-title+.fg-caption-desc{padding-top:0}.foogallery.fg-caption-always .fg-item .fg-caption .fg-caption-inner:before{display:none}.foogallery.fg-caption-always .fg-item.fg-loaded .fg-caption{left:0;bottom:0;transition-timing-function:ease;transition-duration:.3s;transition-property:visibility,opacity;visibility:visible;opacity:1}.foogallery.fg-caption-always .fg-caption{text-align:left}.foogallery.fg-caption-hover .fg-caption .fg-caption-inner{width:100%;max-height:100%;position:absolute;top:50%;left:0;transform:translateY(-50%)}.foogallery.fg-caption-hover .fg-item.fg-loaded .fg-image-overlay{display:none}.foogallery.fg-c-l .fg-caption,.foogallery.fg-caption-always.fg-c-l .fg-caption{text-align:left}.foogallery.fg-c-c .fg-caption,.foogallery.fg-caption-always.fg-c-c .fg-caption{text-align:center}.foogallery.fg-c-r .fg-caption,.foogallery.fg-caption-always.fg-c-r .fg-caption{text-align:right}.foogallery.fg-c-j .fg-caption,.foogallery.fg-caption-always.fg-c-j .fg-caption{text-align:justify}.foogallery .fg-image-overlay:before{content:"";display:block;position:absolute;top:50%;left:50%;transform:translateX(-50%) translateY(-50%);width:32px;height:32px;background-size:32px 32px;background-position:center center;background-repeat:no-repeat}.foogallery .fg-caption-inner:before{content:"";display:none;position:relative;width:32px;height:32px;margin:10px auto 5px auto;background-size:32px 32px;vertical-align:middle;background-position:center center;background-repeat:no-repeat}.foogallery.fg-hover-circle-plus:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-external:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-eye:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-plus:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-tint:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-zoom2:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-zoom3:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-hover-zoom:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-1:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-2:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-3:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-4:not(.fg-preset) .fg-caption-inner:before,.foogallery.fg-video-default:not(.fg-preset) .fg-caption-inner:before{display:block}.foogallery.fg-hover-circle-plus:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-external:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-eye:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-plus:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-tint:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-zoom2:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-zoom3:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-zoom:not(.fg-preset) .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-1:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-2:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-3:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-4:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-video-default:not(.fg-preset) .fg-type-video .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-video-sticky .fg-type-video.fg-loaded .fg-item-inner .fg-image-overlay{background-color:transparent;visibility:visible;opacity:1;display:block}.foogallery.fg-video-sticky .fg-type-video .fg-caption-inner:before{display:none}.foogallery.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-hover-zoom .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom-light)}.foogallery.fg-light-overlays.fg-hover-zoom .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-zoom .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom-dark)}.foogallery.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-hover-zoom2 .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom2-light)}.foogallery.fg-light-overlays.fg-hover-zoom2 .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-zoom2 .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom2-dark)}.foogallery.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-hover-zoom3 .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom3-light)}.foogallery.fg-light-overlays.fg-hover-zoom3 .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-zoom3 .fg-image-overlay:before{background-image:url(../img/icons.svg#zoom3-dark)}.foogallery.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-hover-plus .fg-image-overlay:before{background-image:url(../img/icons.svg#plus-light)}.foogallery.fg-light-overlays.fg-hover-plus .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-plus .fg-image-overlay:before{background-image:url(../img/icons.svg#plus-dark)}.foogallery.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-hover-circle-plus .fg-image-overlay:before{background-image:url(../img/icons.svg#circle-plus-light)}.foogallery.fg-light-overlays.fg-hover-circle-plus .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-circle-plus .fg-image-overlay:before{background-image:url(../img/icons.svg#circle-plus-dark)}.foogallery.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-hover-eye .fg-image-overlay:before{background-image:url(../img/icons.svg#eye-light)}.foogallery.fg-light-overlays.fg-hover-eye .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-eye .fg-image-overlay:before{background-image:url(../img/icons.svg#eye-dark)}.foogallery.fg-hover-external .fg-caption-inner:before,.foogallery.fg-hover-external .fg-image-overlay:before{background-image:url(../img/icons.svg#external-light)}.foogallery.fg-light-overlays.fg-hover-external .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-hover-external .fg-image-overlay:before{background-image:url(../img/icons.svg#external-dark)}.foogallery.fg-video-default .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-default .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-default-light)}.foogallery.fg-light-overlays.fg-video-default .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-default .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-default-dark)}.foogallery.fg-video-1 .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-1 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-1-light)}.foogallery.fg-light-overlays.fg-video-1 .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-1 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-1-dark)}.foogallery.fg-video-2 .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-2 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-2-light)}.foogallery.fg-light-overlays.fg-video-2 .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-2 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-2-dark)}.foogallery.fg-video-3 .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-3 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-3-light)}.foogallery.fg-light-overlays.fg-video-3 .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-3 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-3-dark)}.foogallery.fg-video-4 .fg-type-video .fg-caption-inner:before,.foogallery.fg-video-4 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-4-light)}.foogallery.fg-light-overlays.fg-video-4 .fg-type-video .fg-caption-inner:before,.foogallery.fg-light-overlays.fg-video-4 .fg-type-video .fg-image-overlay:before{background-image:url(../img/icons.svg#video-4-dark)}.foogallery.fg-caption-hover.fg-hover-colorize .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-grayscale .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-scale .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,.foogallery.fg-hover-colorize .fg-loaded .fg-image,.foogallery.fg-hover-colorize .fg-loaded .fg-image-overlay,.foogallery.fg-hover-fade .fg-loaded .fg-image-overlay,.foogallery.fg-hover-grayscale .fg-loaded .fg-image,.foogallery.fg-hover-grayscale .fg-loaded .fg-image-overlay,.foogallery.fg-hover-instant .fg-loaded .fg-image-overlay,.foogallery.fg-hover-push .fg-loaded .fg-thumb,.foogallery.fg-hover-scale .fg-item.fg-loaded,.foogallery.fg-hover-scale .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-down .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-left .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-right .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-up .fg-loaded .fg-image-overlay,.foogallery.fg-hover-zoomed .fg-loaded .fg-image{transition-timing-function:ease;transition-duration:.3s;backface-visibility:hidden}.foogallery.fg-hover-colorize .fg-image{filter:url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'saturate\' values=\'0\'/></filter></svg>#grayscale");filter:gray;-webkit-filter:grayscale(100%);-webkit-transition-property:-webkit-filter;transition-property:filter}.foogallery.fg-hover-colorize .fg-item-inner:hover .fg-image{-webkit-filter:none;filter:none}.foogallery.fg-caption-hover.fg-hover-colorize .fg-caption,.foogallery.fg-hover-colorize .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-colorize .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-colorize .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-caption,.foogallery.fg-hover-fade .fg-loaded .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-fade .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-fade .fg-loaded .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-hover-grayscale .fg-image{-webkit-filter:none;filter:none;-webkit-transition-property:-webkit-filter;transition-property:filter}.foogallery.fg-hover-grayscale .fg-item-inner:hover .fg-image{-webkit-filter:grayscale(1);-webkit-filter:grayscale(100%);filter:grayscale(100%);filter:gray;opacity:1}.foogallery.fg-caption-hover.fg-hover-grayscale .fg-caption,.foogallery.fg-hover-grayscale .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-grayscale .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-grayscale .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-caption,.foogallery.fg-hover-instant .fg-loaded .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:none}.foogallery.fg-caption-hover.fg-hover-instant .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-instant .fg-loaded .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,.foogallery.fg-hover-push .fg-loaded .fg-image-overlay{display:block;left:0;top:0;bottom:0;transform:translateX(100%);visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-caption,.foogallery.fg-hover-push .fg-loaded .fg-thumb{transition-property:transform}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-caption{transform:translateY(0)}.foogallery.fg-caption-hover.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-thumb,.foogallery.fg-hover-push .fg-loaded .fg-item-inner:hover .fg-thumb{transform:translateX(-100%)}.foogallery.fg-hover-scale .fg-item{transition-property:transform;z-index:4}.foogallery.fg-hover-scale .fg-item:hover{transform:scale(1.048);z-index:10}.foogallery.fg-caption-hover.fg-hover-scale .fg-caption,.foogallery.fg-hover-scale .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-scale .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-scale .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-hover-zoomed .fg-image{transition-property:transform;z-index:4}.foogallery.fg-hover-zoomed .fg-item:hover .fg-image{transform:scale(1.15)}.foogallery.fg-hover-zoomed .fg-image-wrap{overflow:hidden}.foogallery.fg-caption-hover.fg-hover-zoomed .fg-caption,.foogallery.fg-hover-zoomed .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:visibility,opacity,background-color}.foogallery.fg-caption-hover.fg-hover-zoomed .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-zoomed .fg-item-inner:hover .fg-image-overlay{visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-left .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-right .fg-loaded .fg-image-overlay,.foogallery.fg-hover-slide-up .fg-loaded .fg-image-overlay{display:block;left:0;top:0;bottom:0;transition-property:transform,background-color,opacity,visibility;visibility:visible;opacity:1}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-item-inner:hover .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-slide-left .fg-loaded .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-slide-right .fg-loaded .fg-item-inner:hover .fg-image-overlay,.foogallery.fg-hover-slide-up .fg-loaded .fg-item-inner:hover .fg-image-overlay{transform:translateY(0) translateX(0)}.foogallery.fg-caption-hover.fg-hover-slide-up .fg-loaded .fg-caption,.foogallery.fg-hover-slide-up .fg-loaded .fg-image-overlay{transform:translateY(100%)}.foogallery.fg-caption-hover.fg-hover-slide-down .fg-loaded .fg-caption,.foogallery.fg-hover-slide-down .fg-loaded .fg-image-overlay{transform:translateY(-100%)}.foogallery.fg-caption-hover.fg-hover-slide-left .fg-loaded .fg-caption,.foogallery.fg-hover-slide-left .fg-loaded .fg-image-overlay{transform:translateX(100%)}.foogallery.fg-caption-hover.fg-hover-slide-right .fg-loaded .fg-caption,.foogallery.fg-hover-slide-right .fg-loaded .fg-image-overlay{transform:translateX(-100%)}.fg-paging-container,.fg-paging-container *,.fg-paging-container :after,.fg-paging-container :before{box-sizing:border-box}.fg-paging-container{display:block;padding:15px;margin-top:0!important;margin-bottom:0!important;margin-left:auto;margin-right:auto;text-align:center;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fg-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.fg-ph-dots:after{display:block;content:'';width:0;height:22px}.fg-paging-container .fg-dot-item,.fg-paging-container .fg-dots{display:inline-block;margin:0;padding:0;outline:0;list-style:none}.fg-paging-container .fg-dot-item .fg-dot-link{display:inline-block;margin:3px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;user-select:none;background-image:none;text-decoration:none;border:1px solid transparent;position:relative;border-radius:50%;padding:0;font-size:0;outline:0;color:transparent;box-shadow:none}.fg-paging-container .fg-dot-item .fg-dot-link:before{content:"";background-color:transparent;border:1px solid transparent;display:block;border-radius:50%;width:9px;height:9px;padding:0;margin:2px}.fg-paging-container .fg-dot-item .fg-dot-link:active,.fg-paging-container .fg-dot-item .fg-dot-link:focus,.fg-paging-container .fg-dot-item .fg-dot-link:hover{text-decoration:none;box-shadow:none;outline:0}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container .fg-dot-item.fg-selected .fg-dot-link{cursor:not-allowed;pointer-events:none}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link{cursor:not-allowed;pointer-events:none;outline:0}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link{background-color:#eee;border-color:#9d9d9d}.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link{border-color:#888}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#666;border-color:#888}.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#eee;border-color:#9d9d9d;opacity:.5}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link{background-color:#666;border-color:#333}.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link{border-color:#444}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#333;border-color:#444}.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#666;border-color:#333;opacity:.5}.fg-paging-container,.fg-paging-container *,.fg-paging-container :after,.fg-paging-container :before{box-sizing:border-box}.fg-paging-container{display:block;padding:15px;margin-top:0!important;margin-bottom:0!important;margin-left:auto;margin-right:auto;text-align:center;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fg-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.fg-ph-dots:after{display:block;content:'';width:0;height:22px}.fg-paging-container .fg-dot-item,.fg-paging-container .fg-dots{display:inline-block;margin:0;padding:0;outline:0;list-style:none}.fg-paging-container .fg-dot-item .fg-dot-link{display:inline-block;margin:3px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;user-select:none;background-image:none;text-decoration:none;border:1px solid transparent;position:relative;border-radius:50%;padding:0;font-size:0;outline:0;color:transparent;box-shadow:none}.fg-paging-container .fg-dot-item .fg-dot-link:before{content:"";background-color:transparent;border:1px solid transparent;display:block;border-radius:50%;width:9px;height:9px;padding:0;margin:2px}.fg-paging-container .fg-dot-item .fg-dot-link:active,.fg-paging-container .fg-dot-item .fg-dot-link:focus,.fg-paging-container .fg-dot-item .fg-dot-link:hover{text-decoration:none;box-shadow:none;outline:0}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container .fg-dot-item.fg-selected .fg-dot-link{cursor:not-allowed;pointer-events:none}.fg-paging-container .fg-dot-item.fg-disabled .fg-dot-link{cursor:not-allowed;pointer-events:none;outline:0}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link{background-color:#eee;border-color:#9d9d9d}.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link{border-color:#888}.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-light .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-light .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#666;border-color:#888}.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-light .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#eee;border-color:#9d9d9d;opacity:.5}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:before{transition-timing-function:ease-out;transition-duration:.3s;transition-property:color,border-color,background-color}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link{background-color:#666;border-color:#333}.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link{border-color:#444}.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:focus:before,.fg-paging-container.fg-dark .fg-dot-item .fg-dot-link:hover:before,.fg-paging-container.fg-dark .fg-dot-item.fg-selected .fg-dot-link:before{background-color:#333;border-color:#444}.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:focus,.fg-paging-container.fg-dark .fg-dot-item.fg-disabled .fg-dot-link:hover{background-color:#666;border-color:#333;opacity:.5}.fg-default:after{content:'';display:block;clear:both}.fg-default .fg-item{display:inline-block;vertical-align:top;max-width:100%}.fg-default .fg-item-inner,.fg-default .fg-thumb{display:block;vertical-align:top;max-width:100%}.fg-default .fg-image{border-radius:0;display:block;max-width:100%;height:auto;margin:0;padding:0}.fg-default .fg-image{vertical-align:top}.fg-default.fg-left{text-align:left}.fg-default.fg-center{text-align:center}.fg-default.fg-right{text-align:right}.fg-default.fg-gutter-5{padding-left:5px;margin-bottom:-5px}.fg-default.fg-gutter-5 .fg-item{margin-right:5px;margin-bottom:5px}.fg-default.fg-gutter-10{padding-left:10px;margin-bottom:-10px}.fg-default.fg-gutter-10 .fg-item{margin-right:10px;margin-bottom:10px}.fg-default.fg-gutter-15{padding-left:15px;margin-bottom:-15px}.fg-default.fg-gutter-15 .fg-item{margin-right:15px;margin-bottom:15px}.fg-default.fg-gutter-20{padding-left:20px;margin-bottom:-20px}.fg-default.fg-gutter-20 .fg-item{margin-right:20px;margin-bottom:20px}.fg-default.fg-gutter-25{padding-left:25px;margin-bottom:-25px}.fg-default.fg-gutter-25 .fg-item{margin-right:25px;margin-bottom:25px}@media only screen and (max-width:600px){.fg-default.fg-m-col1 .fg-image,.fg-default.fg-m-col2 .fg-image,.fg-default.fg-m-col3 .fg-image{width:100%}.fg-default.fg-m-col1.fg-gutter-5 .fg-item{width:calc(100% - 10px);min-width:calc(100% - 10px);max-width:calc(100% - 10px)}.fg-default.fg-m-col2.fg-gutter-5 .fg-item{width:calc(50% - 10px);min-width:calc(50% - 10px);max-width:calc(50% - 10px)}.fg-default.fg-m-col3.fg-gutter-5 .fg-item{width:calc(33.33% - 10px);min-width:calc(33.33% - 10px);max-width:calc(33.33% - 10px)}.fg-default.fg-m-col1.fg-gutter-10 .fg-item{width:calc(100% - 20px);min-width:calc(100% - 20px);max-width:calc(100% - 20px)}.fg-default.fg-m-col2.fg-gutter-10 .fg-item{width:calc(50% - 20px);min-width:calc(50% - 20px);max-width:calc(50% - 20px)}.fg-default.fg-m-col3.fg-gutter-10 .fg-item{width:calc(33.33% - 20px);min-width:calc(33.33% - 20px);max-width:calc(33.33% - 20px)}.fg-default.fg-m-col1.fg-gutter-15 .fg-item{width:calc(100% - 30px);min-width:calc(100% - 30px);max-width:calc(100% - 30px)}.fg-default.fg-m-col2.fg-gutter-15 .fg-item{width:calc(50% - 30px);min-width:calc(50% - 30px);max-width:calc(50% - 30px)}.fg-default.fg-m-col3.fg-gutter-15 .fg-item{width:calc(33.33% - 30px);min-width:calc(33.33% - 30px);max-width:calc(33.33% - 30px)}.fg-default.fg-m-col1.fg-gutter-20 .fg-item{width:calc(100% - 40px);min-width:calc(100% - 40px);max-width:calc(100% - 40px)}.fg-default.fg-m-col2.fg-gutter-20 .fg-item{width:calc(50% - 40px);min-width:calc(50% - 40px);max-width:calc(50% - 40px)}.fg-default.fg-m-col3.fg-gutter-20 .fg-item{width:calc(33.33% - 40px);min-width:calc(33.33% - 40px);max-width:calc(33.33% - 40px)}.fg-default.fg-m-col1.fg-gutter-25 .fg-item{width:calc(100% - 50px);min-width:calc(100% - 50px);max-width:calc(100% - 50px)}.fg-default.fg-m-col2.fg-gutter-25 .fg-item{width:calc(50% - 50px);min-width:calc(50% - 50px);max-width:calc(50% - 50px)}.fg-default.fg-m-col3.fg-gutter-25 .fg-item{width:calc(33.33% - 50px);min-width:calc(33.33% - 50px);max-width:calc(33.33% - 50px)}}.fg-masonry *{box-sizing:border-box}.foogallery.fg-masonry{margin:0 auto;text-align:center}.fg-masonry .fg-thumb{display:block}.fg-masonry.fg-fixed .fg-thumb{display:inline-block}.fg-masonry.fg-fixed .fg-column-width,.fg-masonry.fg-fixed .fg-image,.fg-masonry.fg-fixed .fg-item{max-width:100%}.fg-masonry .fg-column-width{display:inline-block;border:solid 0 transparent}.fg-masonry .fg-column-width,.fg-masonry .fg-gutter-width{position:absolute;height:0;visibility:hidden;opacity:0;pointer-events:none}.fg-masonry.fg-col2 .fg-image,.fg-masonry.fg-col3 .fg-image,.fg-masonry.fg-col4 .fg-image,.fg-masonry.fg-col5 .fg-image,.fg-masonry.fg-col6 .fg-image{width:100%;height:auto;max-width:100%}.fg-masonry .fg-item{line-height:0;font-size:0;vertical-align:top}.fg-masonry.fg-col2 .fg-item{margin-bottom:1%;width:49.5%}.fg-masonry.fg-col2 .fg-column-width{width:49.5%}.fg-masonry.fg-col2 .fg-gutter-width{width:1%}.fg-masonry.fg-col2.fg-gutter-none .fg-item{margin-bottom:0;width:50%}.fg-masonry.fg-col2.fg-gutter-none .fg-column-width{width:50%}.fg-masonry.fg-col2.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col2.fg-gutter-large .fg-item{margin-bottom:3%;width:48.5%}.fg-masonry.fg-col2.fg-gutter-large .fg-column-width{width:48.5%}.fg-masonry.fg-col2.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-col3 .fg-item{margin-bottom:1%;width:32.66%}.fg-masonry.fg-col3 .fg-column-width{width:32.66%}.fg-masonry.fg-col3 .fg-gutter-width{width:1%}.fg-masonry.fg-col3.fg-gutter-none .fg-item{margin-bottom:0;width:33.33%}.fg-masonry.fg-col3.fg-gutter-none .fg-column-width{width:33.33%}.fg-masonry.fg-col3.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col3.fg-gutter-large .fg-item{margin-bottom:3%;width:31.33%}.fg-masonry.fg-col3.fg-gutter-large .fg-column-width{width:31.33%}.fg-masonry.fg-col3.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-col4 .fg-item{margin-bottom:1%;width:24.25%}.fg-masonry.fg-col4 .fg-column-width{width:24.25%}.fg-masonry.fg-col4 .fg-gutter-width{width:1%}.fg-masonry.fg-col4.fg-gutter-none .fg-item{margin-bottom:0;width:25%}.fg-masonry.fg-col4.fg-gutter-none .fg-column-width{width:25%}.fg-masonry.fg-col4.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col4.fg-gutter-large .fg-item{margin-bottom:3%;width:22.75%}.fg-masonry.fg-col4.fg-gutter-large .fg-column-width{width:22.75%}.fg-masonry.fg-col4.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-col5 .fg-item{margin-bottom:1%;width:19.2%}.fg-masonry.fg-col5 .fg-column-width{width:19.2%}.fg-masonry.fg-col5 .fg-gutter-width{width:1%}.fg-masonry.fg-col5.fg-gutter-none .fg-item{margin-bottom:0;width:20%}.fg-masonry.fg-col5.fg-gutter-none .fg-column-width{width:20%}.fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col5.fg-gutter-large .fg-item{margin-bottom:3%;width:17.6%}.fg-masonry.fg-col5.fg-gutter-large .fg-column-width{width:17.6%}.fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width{width:3%}.fg-masonry.fg-col6 .fg-item{margin-bottom:1%;width:15.83%}.fg-masonry.fg-col6 .fg-column-width{width:15.83%}.fg-masonry.fg-col6 .fg-gutter-width{width:1%}.fg-masonry.fg-col6.fg-gutter-none .fg-item{margin-bottom:0;width:16.66%}.fg-masonry.fg-col6.fg-gutter-none .fg-column-width{width:16.66%}.fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col6.fg-gutter-large .fg-item{margin-bottom:3%;width:14.16%}.fg-masonry.fg-col6.fg-gutter-large .fg-column-width{width:14.16%}.fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width{width:3%}@media screen and (max-width:1280px){.fg-masonry.fg-col6 .fg-item{margin-bottom:1%;width:19.2%}.fg-masonry.fg-col6 .fg-column-width{width:19.2%}.fg-masonry.fg-col6 .fg-gutter-width{width:1%}.fg-masonry.fg-col6.fg-gutter-none .fg-item{margin-bottom:0;width:20%}.fg-masonry.fg-col6.fg-gutter-none .fg-column-width{width:20%}.fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col6.fg-gutter-large .fg-item{margin-bottom:3%;width:17.6%}.fg-masonry.fg-col6.fg-gutter-large .fg-column-width{width:17.6%}.fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:1024px){.fg-masonry.fg-col5 .fg-item,.fg-masonry.fg-col6 .fg-item{margin-bottom:1%;width:24.25%}.fg-masonry.fg-col5 .fg-column-width,.fg-masonry.fg-col6 .fg-column-width{width:24.25%}.fg-masonry.fg-col5 .fg-gutter-width,.fg-masonry.fg-col6 .fg-gutter-width{width:1%}.fg-masonry.fg-col5.fg-gutter-none .fg-item,.fg-masonry.fg-col6.fg-gutter-none .fg-item{margin-bottom:0;width:25%}.fg-masonry.fg-col5.fg-gutter-none .fg-column-width,.fg-masonry.fg-col6.fg-gutter-none .fg-column-width{width:25%}.fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col5.fg-gutter-large .fg-item,.fg-masonry.fg-col6.fg-gutter-large .fg-item{margin-bottom:3%;width:22.75%}.fg-masonry.fg-col5.fg-gutter-large .fg-column-width,.fg-masonry.fg-col6.fg-gutter-large .fg-column-width{width:22.75%}.fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:720px){.fg-masonry.fg-col4 .fg-item,.fg-masonry.fg-col5 .fg-item,.fg-masonry.fg-col6 .fg-item{margin-bottom:1%;width:32.66%}.fg-masonry.fg-col4 .fg-column-width,.fg-masonry.fg-col5 .fg-column-width,.fg-masonry.fg-col6 .fg-column-width{width:32.66%}.fg-masonry.fg-col4 .fg-gutter-width,.fg-masonry.fg-col5 .fg-gutter-width,.fg-masonry.fg-col6 .fg-gutter-width{width:1%}.fg-masonry.fg-col4.fg-gutter-none .fg-item,.fg-masonry.fg-col5.fg-gutter-none .fg-item,.fg-masonry.fg-col6.fg-gutter-none .fg-item{margin-bottom:0;width:33.33%}.fg-masonry.fg-col4.fg-gutter-none .fg-column-width,.fg-masonry.fg-col5.fg-gutter-none .fg-column-width,.fg-masonry.fg-col6.fg-gutter-none .fg-column-width{width:33.33%}.fg-masonry.fg-col4.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col4.fg-gutter-large .fg-item,.fg-masonry.fg-col5.fg-gutter-large .fg-item,.fg-masonry.fg-col6.fg-gutter-large .fg-item{margin-bottom:3%;width:31.33%}.fg-masonry.fg-col4.fg-gutter-large .fg-column-width,.fg-masonry.fg-col5.fg-gutter-large .fg-column-width,.fg-masonry.fg-col6.fg-gutter-large .fg-column-width{width:31.33%}.fg-masonry.fg-col4.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:480px){.fg-masonry.fg-col3 .fg-item,.fg-masonry.fg-col4 .fg-item,.fg-masonry.fg-col5 .fg-item,.fg-masonry.fg-col6 .fg-item{margin-bottom:1%;width:49.5%}.fg-masonry.fg-col3 .fg-column-width,.fg-masonry.fg-col4 .fg-column-width,.fg-masonry.fg-col5 .fg-column-width,.fg-masonry.fg-col6 .fg-column-width{width:49.5%}.fg-masonry.fg-col3 .fg-gutter-width,.fg-masonry.fg-col4 .fg-gutter-width,.fg-masonry.fg-col5 .fg-gutter-width,.fg-masonry.fg-col6 .fg-gutter-width{width:1%}.fg-masonry.fg-col3.fg-gutter-none .fg-item,.fg-masonry.fg-col4.fg-gutter-none .fg-item,.fg-masonry.fg-col5.fg-gutter-none .fg-item,.fg-masonry.fg-col6.fg-gutter-none .fg-item{margin-bottom:0;width:50%}.fg-masonry.fg-col3.fg-gutter-none .fg-column-width,.fg-masonry.fg-col4.fg-gutter-none .fg-column-width,.fg-masonry.fg-col5.fg-gutter-none .fg-column-width,.fg-masonry.fg-col6.fg-gutter-none .fg-column-width{width:50%}.fg-masonry.fg-col3.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col4.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col3.fg-gutter-large .fg-item,.fg-masonry.fg-col4.fg-gutter-large .fg-item,.fg-masonry.fg-col5.fg-gutter-large .fg-item,.fg-masonry.fg-col6.fg-gutter-large .fg-item{margin-bottom:3%;width:48.5%}.fg-masonry.fg-col3.fg-gutter-large .fg-column-width,.fg-masonry.fg-col4.fg-gutter-large .fg-column-width,.fg-masonry.fg-col5.fg-gutter-large .fg-column-width,.fg-masonry.fg-col6.fg-gutter-large .fg-column-width{width:48.5%}.fg-masonry.fg-col3.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col4.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width{width:3%}}@media screen and (max-width:320px){.fg-masonry.fg-col2 .fg-item,.fg-masonry.fg-col3 .fg-item,.fg-masonry.fg-col4 .fg-item,.fg-masonry.fg-col5 .fg-item,.fg-masonry.fg-col6 .fg-item{margin-bottom:1%;width:100%}.fg-masonry.fg-col2 .fg-column-width,.fg-masonry.fg-col3 .fg-column-width,.fg-masonry.fg-col4 .fg-column-width,.fg-masonry.fg-col5 .fg-column-width,.fg-masonry.fg-col6 .fg-column-width{width:100%}.fg-masonry.fg-col2 .fg-gutter-width,.fg-masonry.fg-col3 .fg-gutter-width,.fg-masonry.fg-col4 .fg-gutter-width,.fg-masonry.fg-col5 .fg-gutter-width,.fg-masonry.fg-col6 .fg-gutter-width{width:0}.fg-masonry.fg-col2.fg-gutter-none .fg-item,.fg-masonry.fg-col3.fg-gutter-none .fg-item,.fg-masonry.fg-col4.fg-gutter-none .fg-item,.fg-masonry.fg-col5.fg-gutter-none .fg-item,.fg-masonry.fg-col6.fg-gutter-none .fg-item{margin-bottom:0;width:100%}.fg-masonry.fg-col2.fg-gutter-none .fg-column-width,.fg-masonry.fg-col3.fg-gutter-none .fg-column-width,.fg-masonry.fg-col4.fg-gutter-none .fg-column-width,.fg-masonry.fg-col5.fg-gutter-none .fg-column-width,.fg-masonry.fg-col6.fg-gutter-none .fg-column-width{width:100%}.fg-masonry.fg-col2.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col3.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col4.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col5.fg-gutter-none .fg-gutter-width,.fg-masonry.fg-col6.fg-gutter-none .fg-gutter-width{width:0}.fg-masonry.fg-col2.fg-gutter-large .fg-item,.fg-masonry.fg-col3.fg-gutter-large .fg-item,.fg-masonry.fg-col4.fg-gutter-large .fg-item,.fg-masonry.fg-col5.fg-gutter-large .fg-item,.fg-masonry.fg-col6.fg-gutter-large .fg-item{margin-bottom:3%;width:100%}.fg-masonry.fg-col2.fg-gutter-large .fg-column-width,.fg-masonry.fg-col3.fg-gutter-large .fg-column-width,.fg-masonry.fg-col4.fg-gutter-large .fg-column-width,.fg-masonry.fg-col5.fg-gutter-large .fg-column-width,.fg-masonry.fg-col6.fg-gutter-large .fg-column-width{width:100%}.fg-masonry.fg-col2.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col3.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col4.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col5.fg-gutter-large .fg-gutter-width,.fg-masonry.fg-col6.fg-gutter-large .fg-gutter-width{width:0}}.foogallery.fg-border-thin .fg-column-width{border-width:4px}.foogallery.fg-border-medium .fg-column-width{border-width:10px}.foogallery.fg-border-thick .fg-column-width{border-width:16px}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption{visibility:visible;opacity:1;font-size:13px;position:relative;display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;text-transform:none;transform:none;transition:none;background-color:transparent;border-style:solid;border-color:transparent;text-align:left}.foogallery.fg-masonry.fg-captions-bottom.fg-c-l .fg-item-inner .fg-caption{text-align:left}.foogallery.fg-masonry.fg-captions-bottom.fg-c-c .fg-item-inner .fg-caption{text-align:center}.foogallery.fg-masonry.fg-captions-bottom.fg-c-r .fg-item-inner .fg-caption{text-align:right}.foogallery.fg-masonry.fg-captions-bottom.fg-c-j .fg-item-inner .fg-caption{text-align:justify}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner:hover .fg-caption{transform:none;transition:none}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption-inner{display:block;position:relative;max-height:none;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;border:none;transform:none;transition:none}.foogallery.fg-masonry.fg-captions-bottom .fg-item-inner .fg-caption-inner:before{display:none}.foogallery.fg-masonry.fg-captions-bottom.fg-caption-hover .fg-item-inner .fg-image-overlay{display:block}.foogallery.fg-masonry.fg-captions-bottom.fg-caption-always .fg-item-inner:hover .fg-caption{visibility:visible;opacity:1}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption,.fg-masonry.fg-captions-bottom.fg-light .fg-caption{color:#828282}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption a,.fg-masonry.fg-captions-bottom.fg-light .fg-caption a{color:#828282;border-bottom:1px solid #828282}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption a:hover,.fg-masonry.fg-captions-bottom.fg-light .fg-caption a:hover{border-bottom:none}.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title,.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title a{color:#222}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title,.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title a{color:#fff}.fg-masonry.fg-captions-bottom.fg-light .fg-caption-title a{border-bottom:1px solid #222}.fg-masonry.fg-captions-bottom.fg-dark .fg-caption-title a{border-bottom:1px solid #fff}.fg-masonry.fg-captions-bottom .fg-caption{border-width:10px}.fg-masonry.fg-captions-bottom .fg-caption-title+.fg-caption-desc{margin-top:4px}.fg-masonry.fg-captions-bottom.fg-border-thin .fg-caption{border-width:10px 4px 4px 4px}.fg-masonry.fg-captions-bottom.fg-border-medium .fg-caption{border-width:10px 0 0 0}.fg-masonry.fg-captions-bottom.fg-border-thick .fg-caption{border-width:16px 0 0 0}.fg-masonry.fg-captions-bottom.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-masonry.fg-transparent .fg-item-inner{background-color:transparent;color:#333;border-color:transparent}.fg-masonry.fg-transparent .fg-caption{color:#7f7f7f}.fg-masonry.fg-transparent.fg-captions-bottom .fg-caption{border-width:0;border-top-width:10px;border-bottom-width:10px}.fg-masonry.fg-transparent .fg-caption a{color:#7f7f7f;border-bottom:1px solid #7f7f7f}.fg-masonry.fg-transparent .fg-caption a:hover{border-bottom:none}.fg-masonry.fg-transparent .fg-caption-title,.fg-masonry.fg-transparent .fg-caption-title a{color:#333}.fg-masonry.fg-transparent .fg-caption-title a{border-bottom:1px solid #333}.fg-masonry.fg-transparent.fg-round-full .fg-item,.fg-masonry.fg-transparent.fg-round-full .fg-item-inner{border-radius:15px}.fg-masonry.fg-transparent.fg-round-full .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-full .fg-image-wrap,.fg-masonry.fg-transparent.fg-round-full.fg-shadow-inset-large .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-full.fg-shadow-inset-medium .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-full.fg-shadow-inset-small .fg-thumb:after{border-radius:50%;overflow:hidden}.fg-masonry.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap,.fg-masonry.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap,.fg-masonry.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{overflow:hidden}.fg-masonry.fg-transparent.fg-round-small.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-small.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-small.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:5px}.fg-masonry.fg-transparent.fg-round-medium.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-medium.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-medium.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:10px}.fg-masonry.fg-transparent.fg-round-large.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-large.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-large.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-masonry.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-masonry.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:15px}.fg-masonry.fg-transparent.fg-shadow-inset-small .fg-thumb:after{box-shadow:inset 0 1px 4px 0 rgba(0,0,0,.3)}.fg-masonry.fg-transparent.fg-shadow-inset-medium .fg-thumb:after{box-shadow:inset 0 1px 10px 0 rgba(0,0,0,.3)}.fg-masonry.fg-transparent.fg-shadow-inset-large .fg-thumb:after{box-shadow:inset 0 1px 16px 0 rgba(0,0,0,.3)}.fg-masonry.fg-transparent.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px rgba(128,128,128,.5)}.fg-masonry.fg-transparent.fg-shadow-small .fg-item-inner{box-shadow:0 1px 4px 0 rgba(128,128,128,.5)}.fg-masonry.fg-transparent.fg-shadow-medium .fg-item-inner{box-shadow:0 1px 10px 0 rgba(128,128,128,.5)}.fg-masonry.fg-transparent.fg-shadow-large .fg-item-inner{box-shadow:0 1px 16px 0 rgba(128,128,128,.5)}.fg-justified{box-sizing:border-box;position:relative;text-align:center}.foogallery.fg-justified .fg-item{box-sizing:border-box;display:inline-block;margin:0;padding:0}.foogallery.fg-justified .fg-image,.foogallery.fg-justified .fg-item-inner,.foogallery.fg-justified .fg-thumb{box-sizing:border-box;display:block;margin:0;padding:0}.fg-justified .fg-item{visibility:visible;position:relative}.fg-justified .fg-item-inner{position:relative;width:100%;height:100%}.fg-justified .fg-thumb{position:relative;overflow:hidden}.fg-justified .fg-image{z-index:1}.fg-justified .fg-item.fg-positioned .fg-image-wrap,.fg-justified .fg-item.fg-positioned .fg-thumb{width:100%;height:100%}.fg-justified .fg-item.fg-positioned .fg-image{width:100%!important;height:auto!important;min-height:100%}.foogallery.fg-justified-css{position:relative;display:flex;box-sizing:border-box;align-items:center;justify-content:stretch;flex-wrap:wrap}.foogallery.fg-justified-css:after{display:block;content:'';flex-shrink:0;flex-grow:10;min-width:60px}.foogallery.fg-justified-css .fg-image,.foogallery.fg-justified-css .fg-item,.foogallery.fg-justified-css .fg-item-inner,.foogallery.fg-justified-css .fg-thumb{display:block}.foogallery.fg-justified-css .fg-item{flex-shrink:0;flex-grow:1;margin:5px}.foogallery.fg-justified-css .fg-image-wrap{display:flex;align-items:center;justify-content:stretch;overflow:hidden}.foogallery.fg-justified-css .fg-image{width:100%;height:auto}.fg-simple_portfolio{display:flex;flex-wrap:wrap;justify-content:center;align-items:stretch;align-content:center}.fg-simple_portfolio .fg-item{position:relative;flex-grow:0;flex-shrink:0;flex-basis:auto;margin:10px;max-width:100%}.fg-simple_portfolio .fg-item-inner{display:flex;flex-direction:column;margin:0;height:100%}.fg-simple_portfolio.fg-captions-top .fg-item-inner{flex-direction:column-reverse}.fg-simple_portfolio .fg-image{height:auto;width:100%}.fg-simple_portfolio .fg-thumb{min-width:auto;min-height:auto}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption{visibility:visible;opacity:1;font-size:13px;position:relative;display:block;top:auto;bottom:auto;left:auto;right:auto;width:100%;height:100%;text-transform:none;transform:none;transition:none;background-color:transparent;border-style:solid;border-color:transparent;text-align:left}.foogallery.fg-simple_portfolio.fg-c-l .fg-item-inner .fg-caption{text-align:left}.foogallery.fg-simple_portfolio.fg-c-c .fg-item-inner .fg-caption{text-align:center}.foogallery.fg-simple_portfolio.fg-c-r .fg-item-inner .fg-caption{text-align:right}.foogallery.fg-simple_portfolio.fg-c-j .fg-item-inner .fg-caption{text-align:justify}.foogallery.fg-simple_portfolio .fg-item-inner:hover .fg-caption{transform:none;transition:none}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption-inner{display:block;top:auto;bottom:auto;left:auto;right:auto;width:auto;height:auto;border:none;transform:none;transition:none}.foogallery.fg-simple_portfolio .fg-item-inner .fg-caption-inner:before{display:none}.foogallery.fg-simple_portfolio.fg-caption-hover .fg-item-inner .fg-image-overlay{display:block}.foogallery.fg-simple_portfolio.fg-caption-always .fg-item-inner:hover .fg-caption{visibility:visible;opacity:1}.fg-simple_portfolio .fg-caption-title{white-space:normal}.fg-simple_portfolio.fg-dark .fg-caption,.fg-simple_portfolio.fg-light .fg-caption{color:#828282}.fg-simple_portfolio.fg-dark .fg-caption a,.fg-simple_portfolio.fg-light .fg-caption a{color:#828282;border-bottom:1px solid #828282}.fg-simple_portfolio.fg-dark .fg-caption a:hover,.fg-simple_portfolio.fg-light .fg-caption a:hover{border-bottom:none}.fg-simple_portfolio.fg-light .fg-caption-title,.fg-simple_portfolio.fg-light .fg-caption-title a{color:#222}.fg-simple_portfolio.fg-dark .fg-caption-title,.fg-simple_portfolio.fg-dark .fg-caption-title a{color:#fff}.fg-simple_portfolio.fg-light .fg-caption-title a{border-bottom:1px solid #222}.fg-simple_portfolio.fg-dark .fg-caption-title a{border-bottom:1px solid #fff}.fg-simple_portfolio .fg-caption{border-width:0}.fg-simple_portfolio .fg-caption-title+.fg-caption-desc{margin-top:4px}.fg-simple_portfolio.fg-border-thin .fg-caption{border-width:10px 4px 4px 4px}.fg-simple_portfolio.fg-captions-top.fg-border-thin .fg-caption{border-width:4px 4px 10px 4px}.fg-simple_portfolio.fg-border-medium .fg-caption{border-width:10px 0 0 0}.fg-simple_portfolio.fg-captions-top.fg-border-medium .fg-caption{border-width:0 0 10px 0}.fg-simple_portfolio.fg-border-thick .fg-caption{border-width:16px 0 0 0}.fg-simple_portfolio.fg-captions-top.fg-border-thick .fg-caption{border-width:0 0 16px 0}.fg-simple_portfolio.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-simple_portfolio.fg-transparent .fg-item-inner{background-color:transparent;color:#333;border-color:transparent}.fg-simple_portfolio.fg-transparent .fg-caption{color:#7f7f7f}.fg-simple_portfolio.fg-transparent .fg-caption a{color:#7f7f7f;border-bottom:1px solid #7f7f7f}.fg-simple_portfolio.fg-transparent .fg-caption a:hover{border-bottom:none}.fg-simple_portfolio.fg-transparent .fg-caption-title,.fg-simple_portfolio.fg-transparent .fg-caption-title a{color:#333}.fg-simple_portfolio.fg-transparent .fg-caption-title a{border-bottom:1px solid #333}.fg-simple_portfolio.fg-transparent.fg-round-full .fg-item,.fg-simple_portfolio.fg-transparent.fg-round-full .fg-item-inner{border-radius:15px}.fg-simple_portfolio.fg-transparent.fg-round-full .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-full .fg-image-wrap,.fg-simple_portfolio.fg-transparent.fg-round-full.fg-shadow-inset-large .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-full.fg-shadow-inset-medium .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-full.fg-shadow-inset-small .fg-thumb:after{border-radius:50%;overflow:hidden}.fg-simple_portfolio.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap,.fg-simple_portfolio.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap,.fg-simple_portfolio.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{overflow:hidden}.fg-simple_portfolio.fg-transparent.fg-round-small.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-small.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-small.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:5px}.fg-simple_portfolio.fg-transparent.fg-round-medium.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-medium.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-medium.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:10px}.fg-simple_portfolio.fg-transparent.fg-round-large.fg-shadow-inset-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-large.fg-shadow-inset-medium:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-large.fg-shadow-inset-small:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-thumb:after,.fg-simple_portfolio.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-overlay,.fg-simple_portfolio.fg-transparent.fg-round-large:not(.fg-shadow-outline):not(.fg-shadow-small):not(.fg-shadow-medium):not(.fg-shadow-large) .fg-image-wrap{border-radius:15px}.fg-simple_portfolio.fg-transparent.fg-shadow-inset-small .fg-thumb:after{box-shadow:inset 0 1px 4px 0 rgba(0,0,0,.3)}.fg-simple_portfolio.fg-transparent.fg-shadow-inset-medium .fg-thumb:after{box-shadow:inset 0 1px 10px 0 rgba(0,0,0,.3)}.fg-simple_portfolio.fg-transparent.fg-shadow-inset-large .fg-thumb:after{box-shadow:inset 0 1px 16px 0 rgba(0,0,0,.3)}.fg-simple_portfolio.fg-transparent.fg-shadow-outline .fg-item-inner{box-shadow:0 0 0 1px rgba(128,128,128,.5)}.fg-simple_portfolio.fg-transparent.fg-shadow-small .fg-item-inner{box-shadow:0 1px 4px 0 rgba(128,128,128,.5)}.fg-simple_portfolio.fg-transparent.fg-shadow-medium .fg-item-inner{box-shadow:0 1px 10px 0 rgba(128,128,128,.5)}.fg-simple_portfolio.fg-transparent.fg-shadow-large .fg-item-inner{box-shadow:0 1px 16px 0 rgba(128,128,128,.5)}.foogallery.fg-preset.fg-polaroid .fg-item{-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .35s,background-color .65s}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(2n+1){-webkit-transform:rotate(3deg);transform:rotate(3deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(2n){-webkit-transform:rotate(-3deg);transform:rotate(-3deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(3n){-webkit-transform:rotate(1deg);transform:rotate(1deg)}.foogallery.fg-preset.fg-polaroid .fg-item:nth-child(5n){-webkit-transform:rotate(-2deg);transform:rotate(-2deg)}.foogallery.fg-preset.fg-polaroid .fg-item:hover{-webkit-transform:rotate(0);transform:rotate(0)}.foogallery.fg-preset.fg-polaroid .fg-caption{position:relative;width:auto;font-family:"Segoe Print Regular",-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}.foogallery.fg-preset.fg-polaroid .fg-caption-inner,.foogallery.fg-preset.fg-polaroid .fg-caption-title{position:relative;width:auto}.foogallery.fg-preset.fg-polaroid .fg-caption-title{text-align:center}.foogallery.fg-preset.fg-polaroid .fg-caption-desc{display:none}.foogallery.fg-light.fg-preset.fg-polaroid .fg-caption-title,.foogallery.fg-preset.fg-polaroid .fg-caption-title{color:#333}.foogallery.fg-dark.fg-preset.fg-polaroid .fg-caption-title{color:#fff}.foogallery.fg-preset.fg-polaroid .fg-caption{border-style:solid;border-color:transparent;border-width:10px}.foogallery.fg-preset.fg-polaroid .fg-caption-title+.fg-caption-desc{margin-top:4px}.foogallery.fg-preset.fg-polaroid.fg-border-thin .fg-caption{border-width:10px 4px 4px 4px}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-thin .fg-caption{border-width:4px 4px 10px 4px}.foogallery.fg-preset.fg-polaroid.fg-border-medium .fg-caption{border-width:10px 0 0 0}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-medium .fg-caption{border-width:0 0 10px 0}.foogallery.fg-preset.fg-polaroid.fg-border-thick .fg-caption{border-width:16px 0 0 0}.foogallery.fg-preset.fg-polaroid.fg-captions-top.fg-border-thick .fg-caption{border-width:0 0 16px 0}.foogallery.fg-preset.fg-polaroid.fg-border-thick .fg-caption-title+.fg-caption-desc{margin-top:10px}.fg-image-viewer{display:block;font-family:'Open Sans','Helvetica Neue',Arial,sans-serif}.fg-image-viewer.fg-left{text-align:left}.fg-image-viewer.fg-center{text-align:center}.fg-image-viewer.fg-right{text-align:right}.fiv-inner{position:relative;display:inline-block;max-width:100%;overflow:hidden;z-index:6}.fiv-inner .fiv-inner-container{position:relative;overflow:hidden;max-width:100%;border-style:solid;border-width:0;border-bottom-width:4px;z-index:5}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:active,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:hover,.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb:visited{position:relative;display:block;border:none;outline:0;text-decoration:none;box-shadow:none;max-width:100%}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item{position:absolute;visibility:visible;opacity:1;border:none;outline:0;text-decoration:none;box-shadow:none;max-width:100%}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item:first-of-type{position:relative}.fg-image-viewer .fiv-inner .fiv-inner-container .fg-item .fg-thumb img{display:block;max-width:100%;height:auto;border:none;outline:0;text-decoration:none}.fg-image-viewer .fiv-inner .fiv-ctrls{display:block;text-align:center;font-size:14px;border-style:solid;line-height:34px}.fg-image-viewer .fiv-inner .fiv-ctrls:after{content:'';display:block;clear:both}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-count{display:inline-block;font-weight:400;margin:0}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;min-width:80px;position:relative;overflow:hidden;transition:background-color .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:before,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:before{display:block;position:absolute;font-size:24px;line-height:30px;top:0;left:0;width:100%;transform:translateY(0);transition:transform .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:hover:before,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:hover:before{transform:translateY(-100%)}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next span,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev span{display:block;width:100%;transform:translateY(100%);transition:transform .3s}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:hover span,.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:hover span{transform:translateY(0)}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev{float:left}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-prev:before{content:'\2190'}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next{float:right}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-next:before{content:'\2192'}.fg-image-viewer .fiv-inner .fiv-ctrls .fiv-count span{margin:0 4px}.foogallery.fg-image-viewer.fg-caption-always .fg-item-inner .fg-caption{padding:0;border:none}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-title{padding:10px 10px 10px 10px}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-desc{padding:10px 10px 10px 10px}.foogallery.fg-image-viewer.fg-caption-always .fg-caption-title+.fg-caption-desc{padding:0 10px 10px 10px}.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-count,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-prev,.fg-image-viewer.fg-light .fiv-inner .fiv-inner-container{background-color:#fff;color:#333;border-color:#fff}.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-next:hover,.fg-image-viewer.fg-light .fiv-inner .fiv-ctrls .fiv-prev:hover{background-color:#f2f2f2}.fg-image-viewer.fg-light .fiv-next,.fg-image-viewer.fg-light .fiv-prev{box-shadow:inset 0 0 0 1px #ddd}.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-count,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-next,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-prev,.fg-image-viewer.fg-dark .fiv-inner .fiv-inner-container{background-color:#333;color:#fff;border-color:#333}.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-next:hover,.fg-image-viewer.fg-dark .fiv-inner .fiv-ctrls .fiv-prev:hover{background-color:#444}.fg-image-viewer.fg-dark .fiv-next,.fg-image-viewer.fg-dark .fiv-prev{box-shadow:inset 0 0 0 1px #222}.foogallery.fg-image-viewer.fg-border-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin .fg-item-inner{border-width:0}.foogallery.fg-image-viewer .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thin .fiv-inner-container{border-width:4px}.foogallery.fg-image-viewer.fg-border-medium .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-medium .fiv-inner-container{border-width:10px}.foogallery.fg-image-viewer.fg-border-thick .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thick .fiv-inner-container{border-width:16px}.foogallery.fg-image-viewer .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-medium .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thick .fiv-ctrls,.foogallery.fg-image-viewer.fg-border-thin .fiv-ctrls{border-top-width:1px}.foogallery.fg-image-viewer.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-round-small .fiv-inner{border-radius:5px}.foogallery.fg-image-viewer.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-round-small .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-round-small .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-small .fiv-prev,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-small .fiv-prev,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-small .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-round-medium .fiv-inner{border-radius:10px}.foogallery.fg-image-viewer.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-round-medium .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-round-medium .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-medium .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-medium .fiv-prev,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-medium .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-round-large .fiv-inner{border-radius:15px}.foogallery.fg-image-viewer.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-round-large .fg-item-inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.foogallery.fg-image-viewer.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-round-large .fiv-prev{border-radius:11px}.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-thin.fg-round-large .fiv-prev{border-radius:11px}.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-medium.fg-round-large .fiv-prev{border-radius:5px}.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fg-item,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fg-item-inner,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fiv-next,.foogallery.fg-image-viewer.fg-border-thick.fg-round-large .fiv-prev{border-radius:3px}.foogallery.fg-image-viewer.fg-round-full .fiv-inner,.foogallery.fg-image-viewer.fg-round-full .fiv-next,.foogallery.fg-image-viewer.fg-round-full .fiv-prev{border-radius:50%}.foogallery.fg-image-viewer.fg-dark.fg-shadow-large .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-outline .fg-item-inner,.foogallery.fg-image-viewer.fg-dark.fg-shadow-small .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-large .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-medium .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-outline .fg-item-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-small .fg-item-inner{box-shadow:none}.foogallery.fg-image-viewer.fg-light.fg-shadow-outline .fiv-inner{box-shadow:0 0 0 1px #ddd}.foogallery.fg-image-viewer.fg-dark.fg-shadow-outline .fiv-inner{box-shadow:0 0 0 1px #222}.foogallery.fg-image-viewer.fg-dark.fg-shadow-small .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-small .fiv-inner{box-shadow:0 1px 4px 0 rgba(0,0,0,.5)}.foogallery.fg-image-viewer.fg-dark.fg-shadow-medium .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-medium .fiv-inner{box-shadow:0 1px 10px 0 rgba(0,0,0,.5)}.foogallery.fg-image-viewer.fg-dark.fg-shadow-large .fiv-inner,.foogallery.fg-image-viewer.fg-light.fg-shadow-large .fiv-inner{box-shadow:0 1px 16px 0 rgba(0,0,0,.5)}.foogallery.fg-thumbnail,.foogallery.fg-thumbnail.fg-center{text-align:center}.foogallery.fg-thumbnail.fg-left{text-align:left}.foogallery.fg-thumbnail.fg-right{text-align:right}.foogallery.fg-thumbnail.fg-float-left{float:left;width:auto}.foogallery.fg-thumbnail.fg-float-right{float:right;width:auto}.foogallery.fg-thumbnail .fg-item{display:inline-block;vertical-align:top;max-width:100%}.foogallery.fg-thumbnail .fg-image{max-width:100%}.foogallery.fg-thumbnail .fg-st-hidden{display:none}.foogallery-stack-album{text-align:center;overflow:hidden;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:13px;font-weight:400;line-height:1.3}.foogallery-stack-album,.foogallery-stack-album *{box-sizing:border-box}.foogallery-stack-album.fg-align-left{text-align:left}.foogallery-stack-album.fg-align-center{text-align:center}.foogallery-stack-album.fg-align-right{text-align:right}.foogallery-stack-album.fg-disable-transitions,.foogallery-stack-album.fg-disable-transitions *{transition:none!important}.fg-header{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;position:relative;padding:0;margin:0;border-top:solid 1px #aaa;border-bottom:solid 1px #aaa}.fg-header-title{display:block;margin:0;padding:0 20px;width:100%;text-align:left}.fg-header-active{display:block;margin:0;padding:0 20px;visibility:hidden;opacity:0;width:100%;text-align:right;transition-property:opacity,visibility;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-header-back{display:block;padding:0;margin:5px;visibility:hidden;opacity:0;min-width:40px;width:40px;height:40px;border-radius:50%;text-align:center;line-height:38px;color:#999;background:#ddd;background:rgba(200,200,200,.5);cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition-property:opacity,visibility;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-has-active .fg-header-active,.fg-has-active .fg-header-back{visibility:visible;opacity:1}.fg-piles{display:inline-block;position:relative;transition-property:width,height;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-pile{display:block;position:absolute;top:0;left:0;list-style:none;padding:0;margin:0;visibility:visible;opacity:1;transition-property:opacity,visibility,top,left,width,height;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-pile.fg-hidden{visibility:hidden;opacity:0}.fg-pile-item{display:block;position:absolute;top:25px;left:25px;visibility:visible;opacity:1;cursor:pointer;border:10px solid #fff;background-color:#fff;box-shadow:0 1px 4px rgba(0,0,0,.2);transition-property:opacity,visibility,top,left,transform;transition-duration:.3s;transition-timing-function:ease-in-out;z-index:1;transform:rotate(0)}.fg-expanded .fg-pile-item{z-index:2;transform:rotate(0)!important}.fg-pile-item.fg-has-cover{z-index:10;transform:rotate(0)!important}.fg-pile-item:nth-child(2){z-index:9}.fg-pile-item:nth-child(3){z-index:8}.fg-pile-item:nth-child(4){z-index:7}.fg-pile-item:nth-child(1n+5){visibility:hidden;opacity:0}.fg-expanded .fg-pile-item:nth-child(1n+4){visibility:visible;opacity:1}.fg-pile-item-thumb{display:block}.fg-pile-item-image{display:block}.fg-pile-item-caption{display:flex;justify-content:center;flex-direction:column;position:absolute;top:0;left:0;bottom:0;right:0;width:100%;height:100%;margin:0;padding:10px;background-color:rgba(68,68,68,.5);color:#fff;text-align:center;visibility:hidden;opacity:0;transition-property:opacity,visibility;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-pile-item-title{display:block;width:100%;padding:0 0 10px}.fg-pile-item-desc{display:block;width:100%;max-height:100%;border-top:solid 1px currentColor;padding:10px 0 0;overflow:hidden}.fg-pile-item-thumb:hover .fg-pile-item-caption{visibility:visible;opacity:1}.fg-pile-cover{display:flex;justify-content:left;align-items:center;position:absolute;top:0;left:0;bottom:0;right:0;width:100%;height:100%;visibility:visible;opacity:1;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition-property:opacity,visibility;transition-duration:.3s;transition-timing-function:ease-in-out}.fg-expanded .fg-pile-cover{visibility:hidden;opacity:0;pointer-events:none}.fg-pile-cover-content{display:flex;position:relative;background:#fff;color:#333;width:75%;font-weight:700;box-shadow:1px 1px 1px rgba(0,0,0,.1),5px 0 5px -3px rgba(0,0,0,.4),inset 0 0 5px rgba(0,0,0,.04)}.fg-pile-cover-title{text-align:center;padding:10px;width:100%}.fg-pile-cover-count{color:#aaa;padding:10px 5px;background:#f7f7f7;height:100%}
extensions/default-templates/shared/js/foogallery.js CHANGED
@@ -1735,4231 +1735,3728 @@
1735
  */
1736
  window.FooGallery = window.FooGallery || {}
1737
  );
 
 
 
 
1738
  /*!
1739
  * FooGallery.utils - Contains common utility methods and classes used in our plugins.
1740
- * @version 0.2.2
1741
  * @link https://github.com/steveush/foo-utils#readme
1742
- * @copyright Steve Usher 2020
1743
  * @license Released under the GPL-3.0 license.
1744
  */
 
1745
  /**
1746
  * @file This creates the global FooGallery.utils namespace
1747
  */
1748
  (function ($) {
 
 
 
 
 
 
 
 
 
 
 
 
1749
 
1750
- if (!$){
1751
- console.warn('jQuery must be included in the page prior to the FooGallery.utils library.');
1752
- return;
1753
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1754
 
1755
- function __exists(){
1756
- try {
1757
- return !!window.FooGallery.utils; // does the namespace already exist?
1758
- } catch(err) {
1759
- return false;
1760
- }
1761
- }
1762
 
1763
- if (!__exists()){
1764
- /**
1765
- * @summary This namespace contains common utility methods and code shared between our plugins.
1766
- * @global
1767
- * @namespace FooGallery.utils
1768
- * @description This namespace relies on jQuery being included in the page prior to it being loaded.
1769
- */
1770
- window.FooGallery.utils = {
1771
- /**
1772
- * @summary A reference to the jQuery object the library is registered with.
1773
- * @memberof FooGallery.utils.
1774
- * @name $
1775
- * @type {jQuery}
1776
- * @description This is used internally for all jQuery operations to help work around issues where multiple jQuery libraries have been included in a single page.
1777
- * @example {@caption The following shows the issue when multiple jQuery's are included in a single page.}{@lang html}
1778
- * <script src="jquery-1.12.4.js"></script>
1779
- * <script src="my-plugin.js"></script>
1780
- * <script src="jquery-2.2.4.js"></script>
1781
- * <script>
1782
- * jQuery(function($){
1783
- * $(".selector").myPlugin(); // => This would throw a TypeError: $(...).myPlugin is not a function
1784
- * });
1785
- * </script>
1786
- * @example {@caption The reason the above throws an error is that the `$.fn.myPlugin` function is registered to the first instance of jQuery in the page however the instance used to create the ready callback and actually try to execute `$(...).myPlugin()` is the second. To resolve this issue ideally you would remove the second instance of jQuery however you can use the `FooGallery.utils.$` member to ensure you are always working with the instance of jQuery the library was registered with.}{@lang html}
1787
- * <script src="jquery-1.12.4.js"></script>
1788
- * <script src="my-plugin.js"></script>
1789
- * <script src="jquery-2.2.4.js"></script>
1790
- * <script>
1791
- * FooGallery.utils.$(function($){
1792
- * $(".selector").myPlugin(); // => It works!
1793
- * });
1794
- * </script>
1795
- */
1796
- $: $,
1797
- /**
1798
- * @summary The version of this library.
1799
- * @memberof FooGallery.utils.
1800
- * @name version
1801
- * @type {string}
1802
- */
1803
- version: '0.2.2'
1804
- };
1805
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1806
 
1807
- // at this point there will always be a FooGallery.utils namespace registered to the global scope.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1808
 
1809
- })(jQuery);
1810
- (function ($, _){
1811
- // only register methods if this version is the current version
1812
- if (_.version !== '0.2.2') return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1813
 
1814
- /**
1815
- * @summary Contains common type checking utility methods.
1816
- * @memberof FooGallery.utils.
1817
- * @namespace is
1818
- */
1819
- _.is = {};
1820
 
1821
- /**
1822
- * @summary Checks if the `value` is an array.
1823
- * @memberof FooGallery.utils.is.
1824
- * @function array
1825
- * @param {*} value - The value to check.
1826
- * @returns {boolean} `true` if the supplied `value` is an array.
1827
- * @example {@run true}
1828
- * // alias the FooGallery.utils.is namespace
1829
- * var _is = FooGallery.utils.is;
1830
- *
1831
- * console.log( _is.array( [] ) ); // => true
1832
- * console.log( _is.array( null ) ); // => false
1833
- * console.log( _is.array( 123 ) ); // => false
1834
- * console.log( _is.array( "" ) ); // => false
1835
- */
1836
- _.is.array = function (value) {
1837
- return '[object Array]' === Object.prototype.toString.call(value);
1838
- };
1839
 
1840
- /**
1841
- * @summary Checks if the `value` is a boolean.
1842
- * @memberof FooGallery.utils.is.
1843
- * @function boolean
1844
- * @param {*} value - The value to check.
1845
- * @returns {boolean} `true` if the supplied `value` is a boolean.
1846
- * @example {@run true}
1847
- * // alias the FooGallery.utils.is namespace
1848
- * var _is = FooGallery.utils.is;
1849
- *
1850
- * console.log( _is.boolean( true ) ); // => true
1851
- * console.log( _is.boolean( false ) ); // => true
1852
- * console.log( _is.boolean( "true" ) ); // => false
1853
- * console.log( _is.boolean( "false" ) ); // => false
1854
- * console.log( _is.boolean( 1 ) ); // => false
1855
- * console.log( _is.boolean( 0 ) ); // => false
1856
- */
1857
- _.is.boolean = function (value) {
1858
- return '[object Boolean]' === Object.prototype.toString.call(value);
1859
- };
1860
 
1861
- /**
1862
- * @summary Checks if the `value` is an element.
1863
- * @memberof FooGallery.utils.is.
1864
- * @function element
1865
- * @param {*} value - The value to check.
1866
- * @returns {boolean} `true` if the supplied `value` is an element.
1867
- * @example {@run true}
1868
- * // alias the FooGallery.utils.is namespace
1869
- * var _is = FooGallery.utils.is,
1870
- * // create an element to test
1871
- * el = document.createElement("span");
1872
- *
1873
- * console.log( _is.element( el ) ); // => true
1874
- * console.log( _is.element( $(el) ) ); // => false
1875
- * console.log( _is.element( null ) ); // => false
1876
- * console.log( _is.element( {} ) ); // => false
1877
- */
1878
- _.is.element = function (value) {
1879
- return typeof HTMLElement === 'object'
1880
- ? value instanceof HTMLElement
1881
- : !!value && typeof value === 'object' && value.nodeType === 1 && typeof value.nodeName === 'string';
1882
- };
1883
 
1884
- /**
1885
- * @summary Checks if the `value` is empty.
1886
- * @memberof FooGallery.utils.is.
1887
- * @function empty
1888
- * @param {*} value - The value to check.
1889
- * @returns {boolean} `true` if the supplied `value` is empty.
1890
- * @description The following values are considered to be empty by this method:
1891
- *
1892
- * <ul><!--
1893
- * --><li>`""` - An empty string</li><!--
1894
- * --><li>`0` - 0 as an integer</li><!--
1895
- * --><li>`0.0` - 0 as a float</li><!--
1896
- * --><li>`[]` - An empty array</li><!--
1897
- * --><li>`{}` - An empty object</li><!--
1898
- * --><li>`$()` - An empty jQuery object</li><!--
1899
- * --><li>`false`</li><!--
1900
- * --><li>`null`</li><!--
1901
- * --><li>`undefined`</li><!--
1902
- * --></ul>
1903
- * @example {@run true}
1904
- * // alias the FooGallery.utils.is namespace
1905
- * var _is = FooGallery.utils.is;
1906
- *
1907
- * console.log( _is.empty( undefined ) ); // => true
1908
- * console.log( _is.empty( null ) ); // => true
1909
- * console.log( _is.empty( 0 ) ); // => true
1910
- * console.log( _is.empty( 0.0 ) ); // => true
1911
- * console.log( _is.empty( "" ) ); // => true
1912
- * console.log( _is.empty( [] ) ); // => true
1913
- * console.log( _is.empty( {} ) ); // => true
1914
- * console.log( _is.empty( 1 ) ); // => false
1915
- * console.log( _is.empty( 0.1 ) ); // => false
1916
- * console.log( _is.empty( "one" ) ); // => false
1917
- * console.log( _is.empty( ["one"] ) ); // => false
1918
- * console.log( _is.empty( { "name": "My Object" } ) ); // => false
1919
- */
1920
- _.is.empty = function(value){
1921
- if (_.is.undef(value) || value === null) return true;
1922
- if (_.is.number(value) && value === 0) return true;
1923
- if (_.is.boolean(value) && value === false) return true;
1924
- if (_.is.string(value) && value.length === 0) return true;
1925
- if (_.is.array(value) && value.length === 0) return true;
1926
- if (_.is.jq(value) && value.length === 0) return true;
1927
- if (_.is.hash(value)){
1928
- for(var prop in value) {
1929
- if(value.hasOwnProperty(prop))
1930
- return false;
1931
- }
1932
- return true;
1933
- }
1934
- return false;
1935
- };
1936
 
1937
- /**
1938
- * @summary Checks if the `value` is an error.
1939
- * @memberof FooGallery.utils.is.
1940
- * @function error
1941
- * @param {*} value - The value to check.
1942
- * @returns {boolean} `true` if the supplied `value` is an error.
1943
- * @example {@run true}
1944
- * // alias the FooGallery.utils.is namespace
1945
- * var _is = FooGallery.utils.is,
1946
- * // create some errors to test
1947
- * err1 = new Error("err1"),
1948
- * err2 = new SyntaxError("err2");
1949
- *
1950
- * console.log( _is.error( err1 ) ); // => true
1951
- * console.log( _is.error( err2 ) ); // => true
1952
- * console.log( _is.error( null ) ); // => false
1953
- * console.log( _is.error( 123 ) ); // => false
1954
- * console.log( _is.error( "" ) ); // => false
1955
- * console.log( _is.error( {} ) ); // => false
1956
- * console.log( _is.error( [] ) ); // => false
1957
- */
1958
- _.is.error = function (value) {
1959
- return '[object Error]' === Object.prototype.toString.call(value);
1960
- };
1961
 
1962
- /**
1963
- * @summary Checks if the `value` is a function.
1964
- * @memberof FooGallery.utils.is.
1965
- * @function fn
1966
- * @param {*} value - The value to check.
1967
- * @returns {boolean} `true` if the supplied `value` is a function.
1968
- * @example {@run true}
1969
- * // alias the FooGallery.utils.is namespace
1970
- * var _is = FooGallery.utils.is,
1971
- * // create a function to test
1972
- * func = function(){};
1973
- *
1974
- * console.log( _is.fn( func ) ); // => true
1975
- * console.log( _is.fn( null ) ); // => false
1976
- * console.log( _is.fn( 123 ) ); // => false
1977
- * console.log( _is.fn( "" ) ); // => false
1978
- */
1979
- _.is.fn = function (value) {
1980
- return value === window.alert || '[object Function]' === Object.prototype.toString.call(value);
1981
- };
1982
 
1983
- /**
1984
- * @summary Checks if the `value` is a hash.
1985
- * @memberof FooGallery.utils.is.
1986
- * @function hash
1987
- * @param {*} value - The value to check.
1988
- * @returns {boolean} `true` if the supplied `value` is a hash.
1989
- * @example {@run true}
1990
- * // alias the FooGallery.utils.is namespace
1991
- * var _is = FooGallery.utils.is;
1992
- *
1993
- * console.log( _is.hash( {"some": "prop"} ) ); // => true
1994
- * console.log( _is.hash( {} ) ); // => true
1995
- * console.log( _is.hash( window ) ); // => false
1996
- * console.log( _is.hash( document ) ); // => false
1997
- * console.log( _is.hash( "" ) ); // => false
1998
- * console.log( _is.hash( 123 ) ); // => false
1999
- */
2000
- _.is.hash = function (value) {
2001
- return _.is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval;
2002
- };
2003
 
2004
- /**
2005
- * @summary Checks if the `value` is a jQuery object.
2006
- * @memberof FooGallery.utils.is.
2007
- * @function jq
2008
- * @param {*} value - The value to check.
2009
- * @returns {boolean} `true` if the supplied `value` is a jQuery object.
2010
- * @example {@run true}
2011
- * // alias the FooGallery.utils.is namespace
2012
- * var _is = FooGallery.utils.is,
2013
- * // create an element to test
2014
- * el = document.createElement("span");
2015
- *
2016
- * console.log( _is.jq( $(el) ) ); // => true
2017
- * console.log( _is.jq( $() ) ); // => true
2018
- * console.log( _is.jq( el ) ); // => false
2019
- * console.log( _is.jq( {} ) ); // => false
2020
- * console.log( _is.jq( null ) ); // => false
2021
- * console.log( _is.jq( 123 ) ); // => false
2022
- * console.log( _is.jq( "" ) ); // => false
2023
- */
2024
- _.is.jq = function(value){
2025
- return !_.is.undef($) && value instanceof $;
2026
- };
2027
 
2028
- /**
2029
- * @summary Checks if the `value` is a number.
2030
- * @memberof FooGallery.utils.is.
2031
- * @function number
2032
- * @param {*} value - The value to check.
2033
- * @returns {boolean}
2034
- * @example {@run true}
2035
- * // alias the FooGallery.utils.is namespace
2036
- * var _is = FooGallery.utils.is;
2037
- *
2038
- * console.log( _is.number( 123 ) ); // => true
2039
- * console.log( _is.number( undefined ) ); // => false
2040
- * console.log( _is.number( null ) ); // => false
2041
- * console.log( _is.number( "" ) ); // => false
2042
- */
2043
- _.is.number = function (value) {
2044
- return '[object Number]' === Object.prototype.toString.call(value) && !isNaN(value);
2045
- };
2046
 
2047
- /**
2048
- * @summary Checks if the `value` is an object.
2049
- * @memberof FooGallery.utils.is.
2050
- * @function object
2051
- * @param {*} value - The value to check.
2052
- * @returns {boolean} `true` if the supplied `value` is an object.
2053
- * @example {@run true}
2054
- * // alias the FooGallery.utils.is namespace
2055
- * var _is = FooGallery.utils.is;
2056
- *
2057
- * console.log( _is.object( {"some": "prop"} ) ); // => true
2058
- * console.log( _is.object( {} ) ); // => true
2059
- * console.log( _is.object( window ) ); // => true
2060
- * console.log( _is.object( document ) ); // => true
2061
- * console.log( _is.object( undefined ) ); // => false
2062
- * console.log( _is.object( null ) ); // => false
2063
- * console.log( _is.object( "" ) ); // => false
2064
- * console.log( _is.object( 123 ) ); // => false
2065
- */
2066
- _.is.object = function (value) {
2067
- return '[object Object]' === Object.prototype.toString.call(value) && !_.is.undef(value) && value !== null;
2068
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2069
 
2070
- /**
2071
- * @summary Checks if the `value` is a promise.
2072
- * @memberof FooGallery.utils.is.
2073
- * @function promise
2074
- * @param {*} value - The object to check.
2075
- * @returns {boolean} `true` if the supplied `value` is an object.
2076
- * @description This is a simple check to determine if an object is a jQuery promise object. It simply checks the object has a `then` and `promise` function defined.
2077
- *
2078
- * The promise object is created as an object literal inside of `jQuery.Deferred`, it has no prototype, nor any other truly unique properties that could be used to distinguish it.
2079
- *
2080
- * This method should be a little more accurate than the internal jQuery one that simply checks for a `promise` function.
2081
- * @example {@run true}
2082
- * // alias the FooGallery.utils.is namespace
2083
- * var _is = FooGallery.utils.is;
2084
- *
2085
- * console.log( _is.promise( $.Deferred() ) ); // => true
2086
- * console.log( _is.promise( {} ) ); // => false
2087
- * console.log( _is.promise( undefined ) ); // => false
2088
- * console.log( _is.promise( null ) ); // => false
2089
- * console.log( _is.promise( "" ) ); // => false
2090
- * console.log( _is.promise( 123 ) ); // => false
2091
- */
2092
- _.is.promise = function(value){
2093
- return _.is.object(value) && _.is.fn(value.then) && _.is.fn(value.promise);
2094
- };
2095
 
2096
- /**
2097
- * @summary Checks if the `value` is a valid CSS length.
2098
- * @memberof FooGallery.utils.is.
2099
- * @function size
2100
- * @param {*} value - The value to check.
2101
- * @returns {boolean} `true` if the `value` is a number or CSS length.
2102
- * @example {@run true}
2103
- * // alias the FooGallery.utils.is namespace
2104
- * var _is = FooGallery.utils.is;
2105
- *
2106
- * console.log( _is.size( 80 ) ); // => true
2107
- * console.log( _is.size( "80px" ) ); // => true
2108
- * console.log( _is.size( "80em" ) ); // => true
2109
- * console.log( _is.size( "80%" ) ); // => true
2110
- * console.log( _is.size( {} ) ); // => false
2111
- * console.log( _is.size( undefined ) ); // => false
2112
- * console.log( _is.size( null ) ); // => false
2113
- * console.log( _is.size( "" ) ); // => false
2114
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/length|&lt;length&gt; - CSS | MDN} for more information on CSS length values.
2115
- */
2116
- _.is.size = function(value){
2117
- if (!(_.is.string(value) && !_.is.empty(value)) && !_.is.number(value)) return false;
2118
- return /^(auto|none|(?:[\d.]*)+?(?:%|px|mm|q|cm|in|pt|pc|em|ex|ch|rem|vh|vw|vmin|vmax)?)$/.test(value);
2119
- };
2120
 
2121
- /**
2122
- * @summary Checks if the `value` is a string.
2123
- * @memberof FooGallery.utils.is.
2124
- * @function string
2125
- * @param {*} value - The value to check.
2126
- * @returns {boolean} `true` if the `value` is a string.
2127
- * @example {@run true}
2128
- * // alias the FooGallery.utils.is namespace
2129
- * var _is = FooGallery.utils.is;
2130
- *
2131
- * console.log( _is.string( "" ) ); // => true
2132
- * console.log( _is.string( undefined ) ); // => false
2133
- * console.log( _is.string( null ) ); // => false
2134
- * console.log( _is.string( 123 ) ); // => false
2135
- */
2136
- _.is.string = function (value) {
2137
- return '[object String]' === Object.prototype.toString.call(value);
2138
- };
2139
 
2140
- /**
2141
- * @summary Checks if the `value` is `undefined`.
2142
- * @memberof FooGallery.utils.is.
2143
- * @function undef
2144
- * @param {*} value - The value to check is undefined.
2145
- * @returns {boolean} `true` if the supplied `value` is `undefined`.
2146
- * @example {@run true}
2147
- * // alias the FooGallery.utils.is namespace
2148
- * var _is = FooGallery.utils.is;
2149
- *
2150
- * console.log( _is.undef( undefined ) ); // => true
2151
- * console.log( _is.undef( null ) ); // => false
2152
- * console.log( _is.undef( 123 ) ); // => false
2153
- * console.log( _is.undef( "" ) ); // => false
2154
- */
2155
- _.is.undef = function (value) {
2156
- return typeof value === 'undefined';
2157
- };
 
 
 
 
2158
 
2159
- })(
2160
- // dependencies
2161
- FooGallery.utils.$,
2162
- FooGallery.utils
2163
- );
2164
- (function($, _, _is){
2165
- // only register methods if this version is the current version
2166
- if (_.version !== '0.2.2') return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2167
 
2168
- /**
2169
- * @memberof FooGallery.utils.
2170
- * @namespace fn
2171
- * @summary Contains common function utility methods.
2172
- */
2173
- _.fn = {};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2174
 
2175
- var fnStr = Function.prototype.toString;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2176
 
2177
- /**
2178
- * @summary The regular expression to test if a function uses the `this._super` method applied by the {@link FooGallery.utils.fn.add} method.
2179
- * @memberof FooGallery.utils.fn.
2180
- * @name CONTAINS_SUPER
2181
- * @type {RegExp}
2182
- * @default /\b_super\b/
2183
- * @readonly
2184
- * @description When the script is first loaded into the page this performs a quick check to see if the browser supports function decompilation. If it does the regular expression is set to match the expected `_super`, however if function decompilation is not supported, the regular expression is set to match anything effectively making the test always return `true`.
2185
- * @example {@run true}
2186
- * // alias the FooGallery.utils.fn namespace
2187
- * var _fn = FooGallery.utils.fn;
2188
- *
2189
- * // create some functions to test
2190
- * function testFn1(){}
2191
- * function testFn2(){
2192
- * this._super();
2193
- * }
2194
- *
2195
- * console.log( _fn.CONTAINS_SUPER.test( testFn1 ) ); // => false
2196
- * console.log( _fn.CONTAINS_SUPER.test( testFn2 ) ); // => true
2197
- *
2198
- * // NOTE: in browsers that don't support functional decompilation both tests will return `true`
2199
- */
2200
- _.fn.CONTAINS_SUPER = /xyz/.test(fnStr.call(function(){
2201
- //noinspection JSUnresolvedVariable,BadExpressionStatementJS
2202
- xyz;
2203
- })) ? /\b_super\b/ : /.*/;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2204
 
2205
- /**
2206
- * @summary Adds or overrides the given method `name` on the `proto` using the supplied `fn`.
2207
- * @memberof FooGallery.utils.fn.
2208
- * @function addOrOverride
2209
- * @param {Object} proto - The prototype to add the method to.
2210
- * @param {string} name - The name of the method to add, if this already exists the original will be exposed within the scope of the supplied `fn` as `this._super`.
2211
- * @param {function} fn - The function to add to the prototype, if this is overriding an existing method you can use `this._super` to access the original within its' scope.
2212
- * @description If the new method overrides a pre-existing one, this function will expose the overridden method as `this._super` within the new methods scope.
2213
- *
2214
- * This replaces having to write out the following to override a method and call its original:
2215
- *
2216
- * ```javascript
2217
- * var original = MyClass.prototype.someMethod;
2218
- * MyClass.prototype.someMethod = function(arg1, arg2){
2219
- * // execute the original
2220
- * original.call(this, arg1, arg2);
2221
- * };
2222
- * ```
2223
- *
2224
- * With the following:
2225
- *
2226
- * ```javascript
2227
- * FooGallery.utils.fn.addOrOverride( MyClass.prototype, "someMethod", function(arg1, arg2){
2228
- * // execute the original
2229
- * this._super(arg1, arg2);
2230
- * });
2231
- * ```
2232
- *
2233
- * This method is used by the {@link FooGallery.utils.Class} to implement the inheritance of individual methods.
2234
- * @example {@run true}
2235
- * // alias the FooGallery.utils.fn namespace
2236
- * var _fn = FooGallery.utils.fn;
2237
- *
2238
- * var proto = {
2239
- * write: function( message ){
2240
- * console.log( "Original#write: " + message );
2241
- * }
2242
- * };
2243
- *
2244
- * proto.write( "My message" ); // => "Original#write: My message"
2245
- *
2246
- * _fn.addOrOverride( proto, "write", function( message ){
2247
- * message = "Override#write: " + message;
2248
- * this._super( message );
2249
- * } );
2250
- *
2251
- * proto.write( "My message" ); // => "Original#write: Override#write: My message"
2252
- */
2253
- _.fn.addOrOverride = function(proto, name, fn){
2254
- if (!_is.object(proto) || !_is.string(name) || _is.empty(name) || !_is.fn(fn)) return;
2255
- var _super = proto[name],
2256
- wrap = _is.fn(_super) && _.fn.CONTAINS_SUPER.test(fnStr.call(fn));
2257
- // only wrap the function if it overrides a method and makes use of `_super` within it's body.
2258
- proto[name] = wrap ?
2259
- (function (_super, fn) {
2260
- // create a new wrapped that exposes the original method as `_super`
2261
- return function () {
2262
- var tmp = this._super;
2263
- this._super = _super;
2264
- var ret = fn.apply(this, arguments);
2265
- this._super = tmp;
2266
- return ret;
2267
- };
2268
- })(_super, fn) : fn;
2269
- };
 
 
 
 
2270
 
2271
- /**
2272
- * @summary Use the `Function.prototype.apply` method on a class constructor using the `new` keyword.
2273
- * @memberof FooGallery.utils.fn.
2274
- * @function apply
2275
- * @param {Object} klass - The class to create.
2276
- * @param {Array} [args=[]] - The arguments to pass to the constructor.
2277
- * @returns {Object} The new instance of the `klass` created with the supplied `args`.
2278
- * @description When using the default `Function.prototype.apply` you can't use it on class constructors requiring the `new` keyword, this method allows us to do that.
2279
- * @example {@run true}
2280
- * // alias the FooGallery.utils.fn namespace
2281
- * var _fn = FooGallery.utils.fn;
2282
- *
2283
- * // create a class to test with
2284
- * function Test( name, value ){
2285
- * if ( !( this instanceof Test )){
2286
- * console.log( "Test instantiated without the `new` keyword." );
2287
- * return;
2288
- * }
2289
- * console.log( "Test: name = " + name + ", value = " + value );
2290
- * }
2291
- *
2292
- * Test.apply( Test, ["My name", "My value"] ); // => "Test instantiated without the `new` keyword."
2293
- * _fn.apply( Test, ["My name", "My value"] ); // => "Test: name = My name, value = My value"
2294
- */
2295
- _.fn.apply = function(klass, args){
2296
- args.unshift(klass);
2297
- return new (Function.prototype.bind.apply(klass, args));
2298
- // args = _is.array(args) ? args : [];
2299
- // function Class() {
2300
- // return klass.apply(this, args);
2301
- // }
2302
- // Class.prototype = klass.prototype;
2303
- // return new Class();
2304
- };
 
 
 
 
 
 
2305
 
2306
- /**
2307
- * @summary Converts the default `arguments` object into a proper array.
2308
- * @memberof FooGallery.utils.fn.
2309
- * @function arg2arr
2310
- * @param {IArguments} args - The arguments object to create an array from.
2311
- * @returns {Array}
2312
- * @description This method is simply a replacement for calling `Array.prototype.slice.call()` to create an array from an `arguments` object.
2313
- * @example {@run true}
2314
- * // alias the FooGallery.utils.fn namespace
2315
- * var _fn = FooGallery.utils.fn;
2316
- *
2317
- * function callMe(){
2318
- * var args = _fn.arg2arr(arguments);
2319
- * console.log( arguments instanceof Array ); // => false
2320
- * console.log( args instanceof Array ); // => true
2321
- * console.log( args ); // => [ "arg1", "arg2" ]
2322
- * }
2323
- *
2324
- * callMe("arg1", "arg2");
2325
- */
2326
- _.fn.arg2arr = function(args){
2327
- return Array.prototype.slice.call(args);
2328
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2329
 
2330
- /**
2331
- * @summary Debounces the `fn` by the supplied `time`.
2332
- * @memberof FooGallery.utils.fn.
2333
- * @function debounce
2334
- * @param {function} fn - The function to debounce.
2335
- * @param {number} time - The time in milliseconds to delay execution.
2336
- * @returns {function}
2337
- * @description This returns a wrapped version of the `fn` which delays its' execution by the supplied `time`. Additional calls to the function will extend the delay until the `time` expires.
2338
- */
2339
- _.fn.debounce = function (fn, time) {
2340
- var timeout;
2341
- return function () {
2342
- var ctx = this, args = _.fn.arg2arr(arguments);
2343
- clearTimeout(timeout);
2344
- timeout = setTimeout(function () {
2345
- fn.apply(ctx, args);
2346
- }, time);
2347
- };
2348
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2349
 
2350
- /**
2351
- * @summary Throttles the `fn` by the supplied `time`.
2352
- * @memberof FooGallery.utils.fn.
2353
- * @function throttle
2354
- * @param {function} fn - The function to throttle.
2355
- * @param {number} time - The time in milliseconds to delay execution.
2356
- * @returns {function}
2357
- * @description This returns a wrapped version of the `fn` which ensures it's executed only once every `time` milliseconds. The first call to the function will be executed, after that only the last of any additional calls will be executed once the `time` expires.
2358
- */
2359
- _.fn.throttle = function (fn, time) {
2360
- var last, timeout;
2361
- return function () {
2362
- var ctx = this, args = _.fn.arg2arr(arguments);
2363
- if (!last){
2364
- fn.apply(ctx, args);
2365
- last = Date.now();
2366
- } else {
2367
- clearTimeout(timeout);
2368
- timeout = setTimeout(function () {
2369
- if (Date.now() - last >= time) {
2370
- fn.apply(ctx, args);
2371
- last = Date.now();
2372
- }
2373
- }, time - (Date.now() - last));
2374
- }
2375
- }
2376
- };
2377
 
2378
- /**
2379
- * @summary Checks the given `value` and ensures a function is returned.
2380
- * @memberof FooGallery.utils.fn.
2381
- * @function check
2382
- * @param {?Object} thisArg=window - The `this` keyword within the returned function, if the supplied value is not an object this defaults to the `window`.
2383
- * @param {*} value - The value to check, if not a function or the name of one then the `def` value is automatically returned.
2384
- * @param {function} [def=jQuery.noop] - A default function to use if the `value` is not resolved to a function.
2385
- * @param {Object} [ctx=window] - If the `value` is a string this is supplied to the {@link FooGallery.utils.fn.fetch} method as the content to retrieve the function from.
2386
- * @returns {function} A function that ensures the correct context is applied when executed.
2387
- * @description This function is primarily used to check the value of a callback option that could be supplied as either a function or a string.
2388
- *
2389
- * When just the function name is supplied this method uses the {@link FooGallery.utils.fn.fetch} method to resolve and wrap it to ensure when it's called the correct context is applied.
2390
- *
2391
- * Being able to resolve a function from a name allows callbacks to be easily set even through data attributes as you can just supply the full function name as a string and then use this method to retrieve the actual function.
2392
- * @example {@run true}
2393
- * // alias the FooGallery.utils.fn namespace
2394
- * var _fn = FooGallery.utils.fn;
2395
- *
2396
- * // a simple `api` with a `sendMessage` function
2397
- * window.api = {
2398
- * sendMessage: function(){
2399
- * this.write( "window.api.sendMessage" );
2400
- * },
2401
- * child: {
2402
- * api: {
2403
- * sendMessage: function(){
2404
- * this.write( "window.api.child.api.sendMessage" );
2405
- * }
2406
- * }
2407
- * }
2408
- * };
2409
- *
2410
- * // a default function to use in case the check fails
2411
- * var def = function(){
2412
- * this.write( "default" );
2413
- * };
2414
- *
2415
- * // an object to use as the `this` object within the scope of the checked functions
2416
- * var thisArg = {
2417
- * write: function( message ){
2418
- * console.log( message );
2419
- * }
2420
- * };
2421
- *
2422
- * // check the value and return a wrapped function ensuring the correct context.
2423
- * var fn = _fn.check( thisArg, null, def );
2424
- * fn(); // => "default"
2425
- *
2426
- * fn = _fn.check( thisArg, "api.doesNotExist", def );
2427
- * fn(); // => "default"
2428
- *
2429
- * fn = _fn.check( thisArg, api.sendMessage, def );
2430
- * fn(); // => "window.api.sendMessage"
2431
- *
2432
- * fn = _fn.check( thisArg, "api.sendMessage", def );
2433
- * fn(); // => "window.api.sendMessage"
2434
- *
2435
- * fn = _fn.check( thisArg, "api.sendMessage", def, window.api.child );
2436
- * fn(); // => "window.api.child.api.sendMessage"
2437
- */
2438
- _.fn.check = function(thisArg, value, def, ctx){
2439
- def = _is.fn(def) ? def : $.noop;
2440
- thisArg = _is.object(thisArg) ? thisArg : window;
2441
- function wrap(fn){
2442
- return function(){
2443
- return fn.apply(thisArg, arguments);
2444
- };
2445
- }
2446
- value = _is.string(value) ? _.fn.fetch(value, ctx) : value;
2447
- return _is.fn(value) ? wrap(value) : wrap(def);
2448
- };
2449
 
2450
- /**
2451
- * @summary Fetches a function given its `name`.
2452
- * @memberof FooGallery.utils.fn.
2453
- * @function fetch
2454
- * @param {string} name - The name of the function to fetch. This can be a `.` notated name.
2455
- * @param {Object} [ctx=window] - The context to retrieve the function from, defaults to the `window` object.
2456
- * @returns {?function} `null` if a function with the given name is not found within the context.
2457
- * @example {@run true}
2458
- * // alias the FooGallery.utils.fn namespace
2459
- * var _fn = FooGallery.utils.fn;
2460
- *
2461
- * // create a dummy `api` with a `sendMessage` function to test
2462
- * window.api = {
2463
- * sendMessage: function( message ){
2464
- * console.log( "api.sendMessage: " + message );
2465
- * }
2466
- * };
2467
- *
2468
- * // the below shows 3 different ways to fetch the `sendMessage` function
2469
- * var send1 = _fn.fetch( "api.sendMessage" );
2470
- * var send2 = _fn.fetch( "api.sendMessage", window );
2471
- * var send3 = _fn.fetch( "sendMessage", window.api );
2472
- *
2473
- * // all the retrieved methods should be the same
2474
- * console.log( send1 === send2 && send2 === send3 ); // => true
2475
- *
2476
- * // check if the function was found
2477
- * if ( send1 != null ){
2478
- * send1( "My message" ); // => "api.sendMessage: My message"
2479
- * }
2480
- */
2481
- _.fn.fetch = function(name, ctx){
2482
- if (!_is.string(name) || _is.empty(name)) return null;
2483
- ctx = _is.object(ctx) ? ctx : window;
2484
- $.each(name.split('.'), function(i, part){
2485
- if (ctx[part]) ctx = ctx[part];
2486
- else return false;
2487
- });
2488
- return _is.fn(ctx) ? ctx : null;
2489
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2490
 
2491
- /**
2492
- * @summary Enqueues methods using the given `name` from all supplied `objects` and executes each in order with the given arguments.
2493
- * @memberof FooGallery.utils.fn.
2494
- * @function enqueue
2495
- * @param {Array.<Object>} objects - The objects to call the method on.
2496
- * @param {string} name - The name of the method to execute.
2497
- * @param {*} [arg1] - The first argument to call the method with.
2498
- * @param {...*} [argN] - Any additional arguments for the method.
2499
- * @returns {Promise} If `resolved` the first argument supplied to any success callbacks is an array of all returned value(s). These values are encapsulated within their own array as if the method returned a promise it could be resolved with more than one argument.
2500
- *
2501
- * If `rejected` any fail callbacks are supplied the arguments the promise was rejected with plus an additional one appended by this method, an array of all objects that have already had their methods run. This allows you to perform rollback operations if required after a failure. The last object in this array would contain the method that raised the error.
2502
- * @description This method allows an array of `objects` that implement a common set of methods to be executed in a supplied order. Each method in the queue is only executed after the successful completion of the previous. Success is evaluated as the method did not throw an error and if it returned a promise it was resolved.
2503
- *
2504
- * An example of this being used within the plugin is the loading and execution of methods on the various components. Using this method ensures components are loaded and have their methods executed in a static order regardless of when they were registered with the plugin or if the method is async. This way if `ComponentB`'s `preinit` relies on properties set in `ComponentA`'s `preinit` method you can register `ComponentB` with a lower priority than `ComponentA` and you can be assured `ComponentA`'s `preinit` completed successfully before `ComponentB`'s `preinit` is called event if it performs an async operation.
2505
- * @example {@caption Shows a basic example of how you can use this method.}{@run true}
2506
- * // alias the FooGallery.utils.fn namespace
2507
- * var _fn = FooGallery.utils.fn;
2508
- *
2509
- * // create some dummy objects that implement the same members or methods.
2510
- * var obj1 = {
2511
- * "name": "obj1",
2512
- * "appendName": function(str){
2513
- * console.log( "Executing obj1.appendName..." );
2514
- * return str + this.name;
2515
- * }
2516
- * };
2517
- *
2518
- * // this objects `appendName` method returns a promise
2519
- * var obj2 = {
2520
- * "name": "obj2",
2521
- * "appendName": function(str){
2522
- * console.log( "Executing obj2.appendName..." );
2523
- * var self = this;
2524
- * return $.Deferred(function(def){
2525
- * // use a setTimeout to delay execution
2526
- * setTimeout(function(){
2527
- * def.resolve(str + self.name);
2528
- * }, 300);
2529
- * });
2530
- * }
2531
- * };
2532
- *
2533
- * // this objects `appendName` method is only executed once obj2's promise is resolved
2534
- * var obj3 = {
2535
- * "name": "obj3",
2536
- * "appendName": function(str){
2537
- * console.log( "Executing obj3.appendName..." );
2538
- * return str + this.name;
2539
- * }
2540
- * };
2541
- *
2542
- * _fn.enqueue( [obj1, obj2, obj3], "appendName", "modified_by:" ).then(function(results){
2543
- * console.log( results ); // => [ [ "modified_by:obj1" ], [ "modified_by:obj2" ], [ "modified_by:obj3" ] ]
2544
- * });
2545
- * @example {@caption If an error is thrown by one of the called methods or it returns a promise that is rejected, execution is halted and any fail callbacks are executed. The last argument is an array of objects that have had their methods run, the last object within this array is the one that raised the error.}{@run true}
2546
- * // alias the FooGallery.utils.fn namespace
2547
- * var _fn = FooGallery.utils.fn;
2548
- *
2549
- * // create some dummy objects that implement the same members or methods.
2550
- * var obj1 = {
2551
- * "name": "obj1",
2552
- * "last": null,
2553
- * "appendName": function(str){
2554
- * console.log( "Executing obj1.appendName..." );
2555
- * return this.last = str + this.name;
2556
- * },
2557
- * "rollback": function(){
2558
- * console.log( "Executing obj1.rollback..." );
2559
- * this.last = null;
2560
- * }
2561
- * };
2562
- *
2563
- * // this objects `appendName` method throws an error
2564
- * var obj2 = {
2565
- * "name": "obj2",
2566
- * "last": null,
2567
- * "appendName": function(str){
2568
- * console.log( "Executing obj2.appendName..." );
2569
- * //throw new Error("Oops, something broke.");
2570
- * var self = this;
2571
- * return $.Deferred(function(def){
2572
- * // use a setTimeout to delay execution
2573
- * setTimeout(function(){
2574
- * self.last = str + self.name;
2575
- * def.reject(Error("Oops, something broke."));
2576
- * }, 300);
2577
- * });
2578
- * },
2579
- * "rollback": function(){
2580
- * console.log( "Executing obj2.rollback..." );
2581
- * this.last = null;
2582
- * }
2583
- * };
2584
- *
2585
- * // this objects `appendName` and `rollback` methods are never executed
2586
- * var obj3 = {
2587
- * "name": "obj3",
2588
- * "last": null,
2589
- * "appendName": function(str){
2590
- * console.log( "Executing obj3.appendName..." );
2591
- * return this.last = str + this.name;
2592
- * },
2593
- * "rollback": function(){
2594
- * console.log( "Executing obj3.rollback..." );
2595
- * this.last = null;
2596
- * }
2597
- * };
2598
- *
2599
- * _fn.enqueue( [obj1, obj2, obj3], "appendName", "modified_by:" ).fail(function(err, run){
2600
- * console.log( err.message ); // => "Oops, something broke."
2601
- * console.log( run ); // => [ {"name":"obj1","last":"modified_by:obj1"}, {"name":"obj2","last":"modified_by:obj2"} ]
2602
- * var guilty = run[run.length - 1];
2603
- * console.log( "Error thrown by: " + guilty.name ); // => "obj2"
2604
- * run.reverse(); // reverse execution when rolling back to avoid dependency issues
2605
- * return _fn.enqueue( run, "rollback" ).then(function(){
2606
- * console.log( "Error handled and rollback performed." );
2607
- * console.log( run ); // => [ {"name":"obj1","last":null}, {"name":"obj2","last":null} ]
2608
- * });
2609
- * });
2610
- */
2611
- _.fn.enqueue = function(objects, name, arg1, argN){
2612
- var args = _.fn.arg2arr(arguments), // get an array of all supplied arguments
2613
- def = $.Deferred(), // the main deferred object for the function
2614
- queue = $.Deferred(), // the deferred object to use as an queue
2615
- promise = queue.promise(), // used to register component methods for execution
2616
- results = [], // stores the results of each method to be returned by the main deferred
2617
- run = [], // stores each object once its' method has been run
2618
- first = true; // whether or not this is the first resolve callback
2619
-
2620
- // take the objects and name parameters out of the args array
2621
- objects = args.shift();
2622
- name = args.shift();
2623
-
2624
- // safely execute a function, catch any errors and reject the deferred if required.
2625
- function safe(obj, method){
2626
- try {
2627
- run.push(obj);
2628
- return method.apply(obj, args);
2629
- } catch(err) {
2630
- def.reject(err, run);
2631
- return def;
2632
- }
2633
- }
2634
 
2635
- // loop through all the supplied objects
2636
- $.each(objects, function(i, obj){
2637
- // if the obj has a function with the supplied name
2638
- if (_is.fn(obj[name])){
2639
- // then register the method in the callback queue
2640
- promise = promise.then(function(){
2641
- // only register the result if this is not the first resolve callback, the first is triggered by this function kicking off the queue
2642
- if (!first){
2643
- var resolveArgs = _.fn.arg2arr(arguments);
2644
- results.push(resolveArgs);
2645
- }
2646
- first = false;
2647
- // execute the method and return it's result, if the result is a promise
2648
- // the next method will only be executed once it's resolved
2649
- return safe(obj, obj[name]);
2650
- });
2651
- }
2652
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2653
 
2654
- // add one last callback to catch the final result
2655
- promise.then(function(){
2656
- // only register the result if this is not the first resolve callback
2657
- if (!first){
2658
- var resolveArgs = _.fn.arg2arr(arguments);
2659
- results.push(resolveArgs);
2660
- }
2661
- first = false;
2662
- // resolve the main deferred with the array of all the method results
2663
- def.resolve(results);
2664
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2665
 
2666
- // hook into failures and ensure the run array is appended to the args
2667
- promise.fail(function(){
2668
- var rejectArgs = _.fn.arg2arr(arguments);
2669
- rejectArgs.push(run);
2670
- def.reject.apply(def, rejectArgs);
2671
- });
2672
 
2673
- // kick off the queue
2674
- queue.resolve();
 
 
 
 
2675
 
2676
- return def.promise();
2677
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2678
 
2679
- /**
2680
- * @summary Waits for the outcome of all promises regardless of failure and resolves supplying the results of just those that succeeded.
2681
- * @memberof FooGallery.utils.fn.
2682
- * @function when
2683
- * @param {Promise[]} promises - The array of promises to wait for.
2684
- * @returns {Promise}
2685
- */
2686
- _.fn.when = function(promises){
2687
- if (!_is.array(promises) || _is.empty(promises)) return $.when();
2688
- var d = $.Deferred(), results = [], remaining = promises.length;
2689
- function reduceRemaining(){
2690
- remaining--; // always mark as finished
2691
- if(!remaining) d.resolve(results);
2692
- }
2693
- for(var i = 0; i < promises.length; i++){
2694
- if (_is.promise(promises[i])){
2695
- promises[i].then(function(res){
2696
- results.push(res); // on success, add to results
2697
- }).always(reduceRemaining);
2698
- } else {
2699
- reduceRemaining();
2700
- }
2701
- }
2702
- return d.promise(); // return a promise on the remaining values
2703
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2704
 
2705
- /**
2706
- * @summary Return a promise rejected using the supplied args.
2707
- * @memberof FooGallery.utils.fn.
2708
- * @function rejectWith
2709
- * @param {*} [arg1] - The first argument to reject the promise with.
2710
- * @param {...*} [argN] - Any additional arguments to reject the promise with.
2711
- * @returns {Promise}
2712
- */
2713
- _.fn.rejectWith = function(arg1, argN){
2714
- var def = $.Deferred(), args = _.fn.arg2arr(arguments);
2715
- return def.reject.apply(def, args).promise();
2716
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2717
 
2718
- /**
2719
- * @summary Return a promise resolved using the supplied args.
2720
- * @memberof FooGallery.utils.fn.
2721
- * @function resolveWith
2722
- * @param {*} [arg1] - The first argument to resolve the promise with.
2723
- * @param {...*} [argN] - Any additional arguments to resolve the promise with.
2724
- * @returns {Promise}
2725
- */
2726
- _.fn.resolveWith = function(arg1, argN){
2727
- var def = $.Deferred(), args = _.fn.arg2arr(arguments);
2728
- return def.resolve.apply(def, args).promise();
2729
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2730
 
2731
- /**
2732
- * @summary A resolved promise object.
2733
- * @memberof FooGallery.utils.fn.
2734
- * @name resolved
2735
- * @type {Promise}
2736
- */
2737
- _.fn.resolved = $.Deferred().resolve().promise();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2738
 
2739
- /**
2740
- * @summary A rejected promise object.
2741
- * @memberof FooGallery.utils.fn.
2742
- * @name rejected
2743
- * @type {Promise}
2744
- */
2745
- _.fn.rejected = $.Deferred().reject().promise();
2746
 
2747
- })(
2748
- // dependencies
2749
- FooGallery.utils.$,
2750
- FooGallery.utils,
2751
- FooGallery.utils.is
2752
- );
2753
- (function(_, _is){
2754
- // only register methods if this version is the current version
2755
- if (_.version !== '0.2.2') return;
2756
 
2757
- /**
2758
- * @summary Contains common url utility methods.
2759
- * @memberof FooGallery.utils.
2760
- * @namespace url
2761
- */
2762
- _.url = {};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2763
 
2764
- // used for parsing a url into it's parts.
2765
- var _a = document.createElement('a');
2766
 
2767
- /**
2768
- * @summary Parses the supplied url into an object containing it's component parts.
2769
- * @memberof FooGallery.utils.url.
2770
- * @function parts
2771
- * @param {string} url - The url to parse.
2772
- * @returns {FooGallery.utils.url~Parts}
2773
- * @example {@run true}
2774
- * // alias the FooGallery.utils.url namespace
2775
- * var _url = FooGallery.utils.url;
2776
- *
2777
- * console.log( _url.parts( "http://example.com/path/?param=true#something" ) ); // => {"hash":"#something", ...}
2778
- */
2779
- _.url.parts = function(url){
2780
- _a.href = url;
2781
- var port = _a.port ? _a.port : (["http:","https:"].indexOf(_a.protocol) !== -1 ? (_a.protocol === "https:" ? "443" : "80") : ""),
2782
- host = _a.hostname + (port ? ":" + port : ""),
2783
- origin = _a.origin ? _a.origin : _a.protocol + "//" + host,
2784
- pathname = _a.pathname.slice(0, 1) === "/" ? _a.pathname : "/" + _a.pathname;
2785
- return {
2786
- hash: _a.hash, host: host, hostname: _a.hostname, href: _a.href,
2787
- origin: origin, pathname: pathname, port: port,
2788
- protocol: _a.protocol, search: _a.search
2789
- };
2790
- };
2791
 
2792
- /**
2793
- * @summary Given a <code>url</code> that could be relative or full this ensures a full url is returned.
2794
- * @memberof FooGallery.utils.url.
2795
- * @function full
2796
- * @param {string} url - The url to ensure is full.
2797
- * @returns {?string} `null` if the given `path` is not a string or empty.
2798
- * @description Given a full url this will simply return it however if given a relative url this will create a full url using the current location to fill in the blanks.
2799
- * @example {@run true}
2800
- * // alias the FooGallery.utils.url namespace
2801
- * var _url = FooGallery.utils.url;
2802
- *
2803
- * console.log( _url.full( "http://example.com/path/" ) ); // => "http://example.com/path/"
2804
- * console.log( _url.full( "/path/" ) ); // => "{protocol}//{host}/path/"
2805
- * console.log( _url.full( "path/" ) ); // => "{protocol}//{host}/{pathname}/path/"
2806
- * console.log( _url.full( "../path/" ) ); // => "{protocol}//{host}/{calculated pathname}/path/"
2807
- * console.log( _url.full() ); // => null
2808
- * console.log( _url.full( 123 ) ); // => null
2809
- */
2810
- _.url.full = function(url){
2811
- if (!_is.string(url) || _is.empty(url)) return null;
2812
- _a.href = url;
2813
- return _a.href;
2814
- };
2815
 
2816
- /**
2817
- * @summary Gets or sets a parameter in the given <code>search</code> string.
2818
- * @memberof FooGallery.utils.url.
2819
- * @function param
2820
- * @param {string} search - The search string to use (usually `location.search`).
2821
- * @param {string} key - The key of the parameter.
2822
- * @param {?string} [value] - The value to set for the parameter. If not provided the current value for the `key` is returned.
2823
- * @returns {?string} The value of the `key` in the given `search` string if no `value` is supplied or `null` if the `key` does not exist.
2824
- * @returns {string} A modified `search` string if a `value` is supplied.
2825
- * @example <caption>Shows how to retrieve a parameter value from a search string.</caption>{@run true}
2826
- * // alias the FooGallery.utils.url namespace
2827
- * var _url = FooGallery.utils.url,
2828
- * // create a search string to test
2829
- * search = "?wmode=opaque&autoplay=1";
2830
- *
2831
- * console.log( _url.param( search, "wmode" ) ); // => "opaque"
2832
- * console.log( _url.param( search, "autoplay" ) ); // => "1"
2833
- * console.log( _url.param( search, "nonexistent" ) ); // => null
2834
- * @example <caption>Shows how to set a parameter value in the given search string.</caption>{@run true}
2835
- * // alias the FooGallery.utils.url namespace
2836
- * var _url = FooGallery.utils.url,
2837
- * // create a search string to test
2838
- * search = "?wmode=opaque&autoplay=1";
2839
- *
2840
- * console.log( _url.param( search, "wmode", "window" ) ); // => "?wmode=window&autoplay=1"
2841
- * console.log( _url.param( search, "autoplay", "0" ) ); // => "?wmode=opaque&autoplay=0"
2842
- * console.log( _url.param( search, "v", "2" ) ); // => "?wmode=opaque&autoplay=1&v=2"
2843
- */
2844
- _.url.param = function(search, key, value){
2845
- if (!_is.string(search) || !_is.string(key) || _is.empty(key)) return search;
2846
- var regex, match, result, param;
2847
- if (_is.undef(value)){
2848
- regex = new RegExp('[?|&]' + key + '=([^&;]+?)(&|#|;|$)'); // regex to match the key and it's value but only capture the value
2849
- match = regex.exec(search) || ["",""]; // match the param otherwise return an empty string match
2850
- result = match[1].replace(/\+/g, '%20'); // replace any + character's with spaces
2851
- return _is.string(result) && !_is.empty(result) ? decodeURIComponent(result) : null; // decode the result otherwise return null
2852
- }
2853
- if (_is.empty(value)){
2854
- regex = new RegExp('^([^#]*\?)(([^#]*)&)?' + key + '(\=[^&#]*)?(&|#|$)');
2855
- result = search.replace(regex, '$1$3$5').replace(/^([^#]*)((\?)&|\?(#|$))/,'$1$3$4');
2856
- } else {
2857
- regex = new RegExp('([?&])' + key + '[^&]*'); // regex to match the key and it's current value but only capture the preceding ? or & char
2858
- param = key + '=' + encodeURIComponent(value);
2859
- result = search.replace(regex, '$1' + param); // replace any existing instance of the key with the new value
2860
- // If nothing was replaced, then add the new param to the end
2861
- if (result === search && !regex.test(result)) { // if no replacement occurred and the parameter is not currently in the result then add it
2862
- result += (result.indexOf("?") !== -1 ? '&' : '?') + param;
2863
- }
2864
- }
2865
- return result;
2866
- };
2867
 
2868
- //######################
2869
- //## Type Definitions ##
2870
- //######################
2871
 
2872
- /**
2873
- * @summary A plain JavaScript object returned by the {@link FooGallery.utils.url.parts} method.
2874
- * @typedef {Object} FooGallery.utils.url~Parts
2875
- * @property {string} hash - A string containing a `#` followed by the fragment identifier of the URL.
2876
- * @property {string} host - A string containing the host, that is the hostname, a `:`, and the port of the URL.
2877
- * @property {string} hostname - A string containing the domain of the URL.
2878
- * @property {string} href - A string containing the entire URL.
2879
- * @property {string} origin - A string containing the canonical form of the origin of the specific location.
2880
- * @property {string} pathname - A string containing an initial `/` followed by the path of the URL.
2881
- * @property {string} port - A string containing the port number of the URL.
2882
- * @property {string} protocol - A string containing the protocol scheme of the URL, including the final `:`.
2883
- * @property {string} search - A string containing a `?` followed by the parameters of the URL. Also known as "querystring".
2884
- * @see {@link FooGallery.utils.url.parts} for example usage.
2885
- */
2886
 
2887
- })(
2888
- // dependencies
2889
- FooGallery.utils,
2890
- FooGallery.utils.is
2891
- );
2892
- (function (_, _is, _fn) {
2893
- // only register methods if this version is the current version
2894
- if (_.version !== '0.2.2') return;
2895
 
2896
- /**
2897
- * @summary Contains common string utility methods.
2898
- * @memberof FooGallery.utils.
2899
- * @namespace str
2900
- */
2901
- _.str = {};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2902
 
2903
- /**
2904
- * @summary Converts the given `target` to camel case.
2905
- * @memberof FooGallery.utils.str.
2906
- * @function camel
2907
- * @param {string} target - The string to camel case.
2908
- * @returns {string}
2909
- * @example {@run true}
2910
- * // alias the FooGallery.utils.str namespace
2911
- * var _str = FooGallery.utils.str;
2912
- *
2913
- * console.log( _str.camel( "max-width" ) ); // => "maxWidth"
2914
- * console.log( _str.camel( "max--width" ) ); // => "maxWidth"
2915
- * console.log( _str.camel( "max Width" ) ); // => "maxWidth"
2916
- * console.log( _str.camel( "Max_width" ) ); // => "maxWidth"
2917
- * console.log( _str.camel( "MaxWidth" ) ); // => "maxWidth"
2918
- * console.log( _str.camel( "Abbreviations like CSS are left intact" ) ); // => "abbreviationsLikeCSSAreLeftIntact"
2919
- */
2920
- _.str.camel = function (target) {
2921
- if (_is.empty(target)) return target;
2922
- if (target.toUpperCase() === target) return target.toLowerCase();
2923
- return target.replace(/^([A-Z])|[-\s_]+(\w)/g, function (match, p1, p2) {
2924
- if (_is.string(p2)) return p2.toUpperCase();
2925
- return p1.toLowerCase();
2926
- });
2927
- };
2928
 
2929
- /**
2930
- * @summary Converts the given `target` to kebab case. Non-alphanumeric characters are converted to `-`.
2931
- * @memberof FooGallery.utils.str.
2932
- * @function kebab
2933
- * @param {string} target - The string to kebab case.
2934
- * @returns {string}
2935
- * @example {@run true}
2936
- * // alias the FooGallery.utils.str namespace
2937
- * var _str = FooGallery.utils.str;
2938
- *
2939
- * console.log( _str.kebab( "max-width" ) ); // => "max-width"
2940
- * console.log( _str.kebab( "max--width" ) ); // => "max-width"
2941
- * console.log( _str.kebab( "max Width" ) ); // => "max-width"
2942
- * console.log( _str.kebab( "Max_width" ) ); // => "max-width"
2943
- * console.log( _str.kebab( "MaxWidth" ) ); // => "max-width"
2944
- * console.log( _str.kebab( "Non-alphanumeric ch@racters are converted to dashes!" ) ); // => "non-alphanumeric-ch-racters-are-converted-to-dashes"
2945
- */
2946
- _.str.kebab = function(target){
2947
- if (_is.empty(target)) return target;
2948
- return target
2949
- .match(/[A-Z]{2,}(?=[A-Z][a-z0-9]*|\b)|[A-Z]?[a-z0-9]*|[A-Z]|[0-9]+/g)
2950
- .filter(Boolean)
2951
- .map(function(x){ return x.toLowerCase(); })
2952
- .join('-');
2953
- };
2954
 
2955
- /**
2956
- * @summary Checks if the `target` contains the given `substr`.
2957
- * @memberof FooGallery.utils.str.
2958
- * @function contains
2959
- * @param {string} target - The string to check.
2960
- * @param {string} substr - The string to check for.
2961
- * @param {boolean} [ignoreCase=false] - Whether or not to ignore casing when performing the check.
2962
- * @returns {boolean} `true` if the `target` contains the given `substr`.
2963
- * @example {@run true}
2964
- * // alias the FooGallery.utils.str namespace
2965
- * var _str = FooGallery.utils.str,
2966
- * // create a string to test
2967
- * target = "To be, or not to be, that is the question.";
2968
- *
2969
- * console.log( _str.contains( target, "To be" ) ); // => true
2970
- * console.log( _str.contains( target, "question" ) ); // => true
2971
- * console.log( _str.contains( target, "no" ) ); // => true
2972
- * console.log( _str.contains( target, "nonexistent" ) ); // => false
2973
- * console.log( _str.contains( target, "TO BE" ) ); // => false
2974
- * console.log( _str.contains( target, "TO BE", true ) ); // => true
2975
- */
2976
- _.str.contains = function (target, substr, ignoreCase) {
2977
- if (!_is.string(target) || _is.empty(target) || !_is.string(substr) || _is.empty(substr)) return false;
2978
- return substr.length <= target.length
2979
- && (!!ignoreCase ? target.toUpperCase().indexOf(substr.toUpperCase()) : target.indexOf(substr)) !== -1;
2980
- };
2981
 
2982
- /**
2983
- * @summary Checks if the `target` contains the given `word`.
2984
- * @memberof FooGallery.utils.str.
2985
- * @function containsWord
2986
- * @param {string} target - The string to check.
2987
- * @param {string} word - The word to check for.
2988
- * @param {boolean} [ignoreCase=false] - Whether or not to ignore casing when performing the check.
2989
- * @returns {boolean} `true` if the `target` contains the given `word`.
2990
- * @description This method differs from {@link FooGallery.utils.str.contains} in that it searches for whole words by splitting the `target` string on word boundaries (`\b`) and then comparing the individual parts.
2991
- * @example {@run true}
2992
- * // alias the FooGallery.utils.str namespace
2993
- * var _str = FooGallery.utils.str,
2994
- * // create a string to test
2995
- * target = "To be, or not to be, that is the question.";
2996
- *
2997
- * console.log( _str.containsWord( target, "question" ) ); // => true
2998
- * console.log( _str.containsWord( target, "no" ) ); // => false
2999
- * console.log( _str.containsWord( target, "NOT" ) ); // => false
3000
- * console.log( _str.containsWord( target, "NOT", true ) ); // => true
3001
- * console.log( _str.containsWord( target, "nonexistent" ) ); // => false
3002
- */
3003
- _.str.containsWord = function(target, word, ignoreCase){
3004
- if (!_is.string(target) || _is.empty(target) || !_is.string(word) || _is.empty(word) || target.length < word.length)
3005
- return false;
3006
- var parts = target.split(/\W/);
3007
- for (var i = 0, len = parts.length; i < len; i++){
3008
- if (ignoreCase ? parts[i].toUpperCase() === word.toUpperCase() : parts[i] === word) return true;
3009
- }
3010
- return false;
3011
- };
3012
 
3013
- /**
3014
- * @summary Checks if the `target` ends with the given `substr`.
3015
- * @memberof FooGallery.utils.str.
3016
- * @function endsWith
3017
- * @param {string} target - The string to check.
3018
- * @param {string} substr - The substr to check for.
3019
- * @returns {boolean} `true` if the `target` ends with the given `substr`.
3020
- * @example {@run true}
3021
- * // alias the FooGallery.utils.str namespace
3022
- * var _str = FooGallery.utils.str;
3023
- *
3024
- * console.log( _str.endsWith( "something", "g" ) ); // => true
3025
- * console.log( _str.endsWith( "something", "ing" ) ); // => true
3026
- * console.log( _str.endsWith( "something", "no" ) ); // => false
3027
- */
3028
- _.str.endsWith = function (target, substr) {
3029
- if (!_is.string(target) || _is.empty(target) || !_is.string(substr) || _is.empty(substr)) return target === substr;
3030
- return target.slice(target.length - substr.length) === substr;
3031
- };
 
 
 
 
3032
 
3033
- /**
3034
- * @summary Escapes the `target` for use in a regular expression.
3035
- * @memberof FooGallery.utils.str.
3036
- * @function escapeRegExp
3037
- * @param {string} target - The string to escape.
3038
- * @returns {string}
3039
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions|Regular Expressions: Using Special Characters - JavaScript | MDN}
3040
- */
3041
- _.str.escapeRegExp = function(target){
3042
- if (_is.empty(target)) return target;
3043
- return target.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3044
- };
3045
 
3046
- /**
3047
- * @summary Generates a 32 bit FNV-1a hash from the given `target`.
3048
- * @memberof FooGallery.utils.str.
3049
- * @function fnv1a
3050
- * @param {string} target - The string to generate a hash from.
3051
- * @returns {?number} `null` if the `target` is not a string or empty otherwise a 32 bit FNV-1a hash.
3052
- * @example {@run true}
3053
- * // alias the FooGallery.utils.str namespace
3054
- * var _str = FooGallery.utils.str;
3055
- *
3056
- * console.log( _str.fnv1a( "Some string to generate a hash for." ) ); // => 207568994
3057
- * console.log( _str.fnv1a( "Some string to generate a hash for" ) ); // => 1350435704
3058
- * @see {@link https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function|Fowler–Noll–Vo hash function}
3059
- */
3060
- _.str.fnv1a = function(target){
3061
- if (!_is.string(target) || _is.empty(target)) return null;
3062
- var i, l, hval = 0x811c9dc5;
3063
- for (i = 0, l = target.length; i < l; i++) {
3064
- hval ^= target.charCodeAt(i);
3065
- hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
3066
- }
3067
- return hval >>> 0;
3068
- };
3069
 
3070
- /**
3071
- * @summary Returns the remainder of the `target` split on the first index of the given `substr`.
3072
- * @memberof FooGallery.utils.str.
3073
- * @function from
3074
- * @param {string} target - The string to split.
3075
- * @param {string} substr - The substring to split on.
3076
- * @returns {?string} `null` if the given `substr` does not exist within the `target`.
3077
- * @example {@run true}
3078
- * // alias the FooGallery.utils.str namespace
3079
- * var _str = FooGallery.utils.str,
3080
- * // create a string to test
3081
- * target = "To be, or not to be, that is the question.";
3082
- *
3083
- * console.log( _str.from( target, "no" ) ); // => "t to be, that is the question."
3084
- * console.log( _str.from( target, "that" ) ); // => " is the question."
3085
- * console.log( _str.from( target, "question" ) ); // => "."
3086
- * console.log( _str.from( target, "nonexistent" ) ); // => null
3087
- */
3088
- _.str.from = function (target, substr) {
3089
- return _.str.contains(target, substr) ? target.substring(target.indexOf(substr) + substr.length) : null;
3090
- };
3091
 
3092
- /**
3093
- * @summary Joins any number of strings using the given `separator`.
3094
- * @memberof FooGallery.utils.str.
3095
- * @function join
3096
- * @param {string} separator - The separator to use to join the strings.
3097
- * @param {string} part - The first string to join.
3098
- * @param {...string} [partN] - Any number of additional strings to join.
3099
- * @returns {?string}
3100
- * @description This method differs from using the standard `Array.prototype.join` function to join strings in that it ignores empty parts and checks to see if each starts with the supplied `separator`. If the part starts with the `separator` it is removed before appending it to the final result.
3101
- * @example {@run true}
3102
- * // alias the FooGallery.utils.str namespace
3103
- * var _str = FooGallery.utils.str;
3104
- *
3105
- * console.log( _str.join( "_", "all", "in", "one" ) ); // => "all_in_one"
3106
- * console.log( _str.join( "_", "all", "_in", "one" ) ); // => "all_in_one"
3107
- * console.log( _str.join( "/", "http://", "/example.com/", "/path/to/image.png" ) ); // => "http://example.com/path/to/image.png"
3108
- * console.log( _str.join( "/", "http://", "/example.com", "/path/to/image.png" ) ); // => "http://example.com/path/to/image.png"
3109
- * console.log( _str.join( "/", "http://", "example.com", "path/to/image.png" ) ); // => "http://example.com/path/to/image.png"
3110
- */
3111
- _.str.join = function(separator, part, partN){
3112
- if (!_is.string(separator) || !_is.string(part)) return null;
3113
- var parts = _fn.arg2arr(arguments);
3114
- separator = parts.shift();
3115
- var i, l, result = parts.shift();
3116
- for (i = 0, l = parts.length; i < l; i++){
3117
- part = parts[i];
3118
- if (_is.empty(part)) continue;
3119
- if (_.str.endsWith(result, separator)){
3120
- result = result.slice(0, result.length-separator.length);
3121
- }
3122
- if (_.str.startsWith(part, separator)){
3123
- part = part.slice(separator.length);
3124
- }
3125
- result += separator + part;
3126
- }
3127
- return result;
3128
- };
3129
 
3130
- /**
3131
- * @summary Checks if the `target` starts with the given `substr`.
3132
- * @memberof FooGallery.utils.str.
3133
- * @function startsWith
3134
- * @param {string} target - The string to check.
3135
- * @param {string} substr - The substr to check for.
3136
- * @returns {boolean} `true` if the `target` starts with the given `substr`.
3137
- * @example {@run true}
3138
- * // alias the FooGallery.utils.str namespace
3139
- * var _str = FooGallery.utils.str;
3140
- *
3141
- * console.log( _str.startsWith( "something", "s" ) ); // => true
3142
- * console.log( _str.startsWith( "something", "some" ) ); // => true
3143
- * console.log( _str.startsWith( "something", "no" ) ); // => false
3144
- */
3145
- _.str.startsWith = function (target, substr) {
3146
- if (_is.empty(target) || _is.empty(substr)) return false;
3147
- return target.slice(0, substr.length) === substr;
3148
- };
3149
 
3150
- /**
3151
- * @summary Returns the first part of the `target` split on the first index of the given `substr`.
3152
- * @memberof FooGallery.utils.str.
3153
- * @function until
3154
- * @param {string} target - The string to split.
3155
- * @param {string} substr - The substring to split on.
3156
- * @returns {string} The `target` if the `substr` does not exist.
3157
- * @example {@run true}
3158
- * // alias the FooGallery.utils.str namespace
3159
- * var _str = FooGallery.utils.str,
3160
- * // create a string to test
3161
- * target = "To be, or not to be, that is the question.";
3162
- *
3163
- * console.log( _str.until( target, "no" ) ); // => "To be, or "
3164
- * console.log( _str.until( target, "that" ) ); // => "To be, or not to be, "
3165
- * console.log( _str.until( target, "question" ) ); // => "To be, or not to be, that is the "
3166
- * console.log( _str.until( target, "nonexistent" ) ); // => "To be, or not to be, that is the question."
3167
- */
3168
- _.str.until = function (target, substr) {
3169
- return _.str.contains(target, substr) ? target.substring(0, target.indexOf(substr)) : target;
3170
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3171
 
3172
- /**
3173
- * @summary A basic string formatter that can use both index and name based placeholders but handles only string or number replacements.
3174
- * @memberof FooGallery.utils.str.
3175
- * @function format
3176
- * @param {string} target - The format string containing any placeholders to replace.
3177
- * @param {string|number|Object|Array} arg1 - The first value to format the target with. If an object is supplied it's properties are used to match named placeholders. If an array, string or number is supplied it's values are used to match any index placeholders.
3178
- * @param {...(string|number)} [argN] - Any number of additional strings or numbers to format the target with.
3179
- * @returns {string} The string formatted with the supplied arguments.
3180
- * @description This method allows you to supply the replacements as an object when using named placeholders or as an array or additional arguments when using index placeholders.
3181
- *
3182
- * This does not perform a simultaneous replacement of placeholders, which is why it's referred to as a basic formatter. This means replacements that contain placeholders within there value could end up being replaced themselves as seen in the last example.
3183
- * @example {@caption The following shows how to use index placeholders.}{@run true}
3184
- * // alias the FooGallery.utils.str namespace
3185
- * var _str = FooGallery.utils.str,
3186
- * // create a format string using index placeholders
3187
- * format = "Hello, {0}, are you feeling {1}?";
3188
- *
3189
- * console.log( _str.format( format, "Steve", "OK" ) ); // => "Hello, Steve, are you feeling OK?"
3190
- * // or
3191
- * console.log( _str.format( format, [ "Steve", "OK" ] ) ); // => "Hello, Steve, are you feeling OK?"
3192
- * @example {@caption While the above works perfectly fine the downside is that the placeholders provide no clues as to what should be supplied as a replacement value, this is were supplying an object and using named placeholders steps in.}{@run true}
3193
- * // alias the FooGallery.utils.str namespace
3194
- * var _str = FooGallery.utils.str,
3195
- * // create a format string using named placeholders
3196
- * format = "Hello, {name}, are you feeling {adjective}?";
3197
- *
3198
- * console.log( _str.format( format, {name: "Steve", adjective: "OK"} ) ); // => "Hello, Steve, are you feeling OK?"
3199
- * @example {@caption The following demonstrates the issue with not performing a simultaneous replacement of placeholders.}{@run true}
3200
- * // alias the FooGallery.utils.str namespace
3201
- * var _str = FooGallery.utils.str;
3202
- *
3203
- * console.log( _str.format("{0}{1}", "{1}", "{0}") ); // => "{0}{0}"
3204
- *
3205
- * // If the replacement happened simultaneously the result would be "{1}{0}" but this method executes
3206
- * // replacements synchronously as seen below:
3207
- *
3208
- * // "{0}{1}".replace( "{0}", "{1}" )
3209
- * // => "{1}{1}".replace( "{1}", "{0}" )
3210
- * // => "{0}{0}"
3211
- */
3212
- _.str.format = function (target, arg1, argN){
3213
- var args = _fn.arg2arr(arguments);
3214
- target = args.shift(); // remove the target from the args
3215
- if (_is.string(target) && args.length > 0){
3216
- if (args.length === 1 && (_is.array(args[0]) || _is.object(args[0]))){
3217
- args = args[0];
3218
- }
3219
- _.each(args, function(value, placeholder){
3220
- target = target.replace(new RegExp("\\{" + placeholder + "\\}", "gi"), value + "");
3221
- });
3222
- }
3223
- return target;
3224
- };
3225
 
3226
- })(
3227
- // dependencies
3228
- FooGallery.utils,
3229
- FooGallery.utils.is,
3230
- FooGallery.utils.fn
3231
- );
3232
- (function($, _, _is, _fn, _str){
3233
- // only register methods if this version is the current version
3234
- if (_.version !== '0.2.2') return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3235
 
3236
- /**
3237
- * @summary Contains common object utility methods.
3238
- * @memberof FooGallery.utils.
3239
- * @namespace obj
3240
- */
3241
- _.obj = {};
 
 
3242
 
3243
- // used by the obj.create method
3244
- var Obj = function () {};
3245
- /**
3246
- * @summary Creates a new object with the specified prototype.
3247
- * @memberof FooGallery.utils.obj.
3248
- * @function create
3249
- * @param {Object} proto - The object which should be the prototype of the newly-created object.
3250
- * @returns {Object} A new object with the specified prototype.
3251
- * @description This is a basic implementation of the {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create|Object.create} method.
3252
- */
3253
- _.obj.create = function (proto) {
3254
- if (!_is.object(proto))
3255
- throw TypeError('Argument must be an object');
3256
- Obj.prototype = proto;
3257
- var result = new Obj();
3258
- Obj.prototype = null;
3259
- return result;
3260
- };
3261
 
3262
- /**
3263
- * @summary Merge the contents of two or more objects together into the first `target` object.
3264
- * @memberof FooGallery.utils.obj.
3265
- * @function extend
3266
- * @param {Object} target - The object to merge properties into.
3267
- * @param {Object} object - An object containing properties to merge.
3268
- * @param {...Object} [objectN] - Additional objects containing properties to merge.
3269
- * @returns {Object} The `target` merged with the contents from any additional objects.
3270
- * @description This does not merge arrays by index as jQuery does, it treats them as a single property and replaces the array with a shallow copy of the new one.
3271
- *
3272
- * This method makes use of the {@link FooGallery.utils.obj.merge} method internally.
3273
- * @example {@run true}
3274
- * // alias the FooGallery.utils.obj namespace
3275
- * var _obj = FooGallery.utils.obj,
3276
- * // create some objects to merge
3277
- * defaults = {"name": "My Object", "enabled": false, "arr": [1,2,3]},
3278
- * options = {"enabled": true, "something": 123, "arr": [4,5,6]};
3279
- *
3280
- * // merge the two objects into a new third one without modifying either of the originals
3281
- * var settings = _obj.extend( {}, defaults, options );
3282
- *
3283
- * console.log( settings ); // => {"name": "My Object", "enabled": true, "arr": [4,5,6], "something": 123}
3284
- * console.log( defaults ); // => {"name": "My Object", "enabled": true, "arr": [1,2,3]}
3285
- * console.log( options ); // => {"enabled": true, "arr": [4,5,6], "something": 123}
3286
- */
3287
- _.obj.extend = function(target, object, objectN){
3288
- target = _is.object(target) ? target : {};
3289
- var objects = _fn.arg2arr(arguments);
3290
- objects.shift();
3291
- $.each(objects, function(i, object){
3292
- _.obj.merge(target, object);
3293
- });
3294
- return target;
3295
- };
3296
 
3297
- /**
3298
- * @summary Merge the contents of two objects together into the first `target` object.
3299
- * @memberof FooGallery.utils.obj.
3300
- * @function merge
3301
- * @param {Object} target - The object to merge properties into.
3302
- * @param {Object} object - The object containing properties to merge.
3303
- * @returns {Object} The `target` merged with the contents from the `object`.
3304
- * @description This does not merge arrays by index as jQuery does, it treats them as a single property and replaces the array with a shallow copy of the new one.
3305
- *
3306
- * This method is used internally by the {@link FooGallery.utils.obj.extend} method.
3307
- * @example {@run true}
3308
- * // alias the FooGallery.utils.obj namespace
3309
- * var _obj = FooGallery.utils.obj,
3310
- * // create some objects to merge
3311
- * target = {"name": "My Object", "enabled": false, "arr": [1,2,3]},
3312
- * object = {"enabled": true, "something": 123, "arr": [4,5,6]};
3313
- *
3314
- * console.log( _obj.merge( target, object ) ); // => {"name": "My Object", "enabled": true, "arr": [4,5,6], "something": 123}
3315
- */
3316
- _.obj.merge = function(target, object){
3317
- target = _is.hash(target) ? target : {};
3318
- object = _is.hash(object) ? object : {};
3319
- for (var prop in object) {
3320
- if (object.hasOwnProperty(prop)) {
3321
- if (_is.hash(object[prop])) {
3322
- target[prop] = _is.hash(target[prop]) ? target[prop] : {};
3323
- _.obj.merge(target[prop], object[prop]);
3324
- } else if (_is.array(object[prop])) {
3325
- target[prop] = object[prop].slice();
3326
- } else {
3327
- target[prop] = object[prop];
3328
- }
3329
- }
3330
- }
3331
- return target;
3332
- };
3333
 
3334
- /**
3335
- * @summary Merge the validated properties of the `object` into the `target` using the optional `mappings`.
3336
- * @memberof FooGallery.utils.obj.
3337
- * @function mergeValid
3338
- * @param {Object} target - The object to merge properties into.
3339
- * @param {FooGallery.utils.obj~Validators} validators - An object containing validators for the `target` object properties.
3340
- * @param {Object} object - The object containing properties to merge.
3341
- * @param {FooGallery.utils.obj~Mappings} [mappings] - An object containing property name mappings.
3342
- * @returns {Object} The modified `target` object containing any valid properties from the supplied `object`.
3343
- * @example {@caption Shows the basic usage for this method and shows how invalid properties or those with no corresponding validator are ignored.}{@run true}
3344
- * // alias the FooGallery.utils.obj and FooGallery.utils.is namespaces
3345
- * var _obj = FooGallery.utils.obj,
3346
- * _is = FooGallery.utils.is;
3347
- *
3348
- * //create the target object and it's validators
3349
- * var target = {"name":"John","location":"unknown"},
3350
- * validators = {"name":_is.string,"location":_is.string};
3351
- *
3352
- * // create the object to merge into the target
3353
- * var object = {
3354
- * "name": 1234, // invalid
3355
- * "location": "Liverpool", // updated
3356
- * "notMerged": true // ignored
3357
- * };
3358
- *
3359
- * // merge the object into the target, invalid properties or those with no corresponding validator are ignored.
3360
- * console.log( _obj.mergeValid( target, validators, object ) ); // => { "name": "John", "location": "Liverpool" }
3361
- * @example {@caption Shows how to supply a mappings object for this method.}{@run true}
3362
- * // alias the FooGallery.utils.obj and FooGallery.utils.is namespaces
3363
- * var _obj = FooGallery.utils.obj,
3364
- * _is = FooGallery.utils.is;
3365
- *
3366
- * //create the target object and it's validators
3367
- * var target = {"name":"John","location":"unknown"},
3368
- * validators = {"name":_is.string,"location":_is.string};
3369
- *
3370
- * // create the object to merge into the target
3371
- * var object = {
3372
- * "name": { // ignored
3373
- * "proper": "Christopher", // mapped to name if short is invalid
3374
- * "short": "Chris" // map to name
3375
- * },
3376
- * "city": "London" // map to location
3377
- * };
3378
- *
3379
- * // create the mapping object
3380
- * var mappings = {
3381
- * "name": [ "name.short", "name.proper" ], // try use the short name and fallback to the proper
3382
- * "location": "city"
3383
- * };
3384
- *
3385
- * // merge the object into the target using the mappings, invalid properties or those with no corresponding validator are ignored.
3386
- * console.log( _obj.mergeValid( target, validators, object, mappings ) ); // => { "name": "Chris", "location": "London" }
3387
- */
3388
- _.obj.mergeValid = function(target, validators, object, mappings){
3389
- if (!_is.hash(object) || !_is.hash(validators)) return target;
3390
- validators = _is.hash(validators) ? validators : {};
3391
- mappings = _is.hash(mappings) ? mappings : {};
3392
- var prop, maps, value;
3393
- for (prop in validators){
3394
- if (!validators.hasOwnProperty(prop) || !_is.fn(validators[prop])) continue;
3395
- maps = _is.array(mappings[prop]) ? mappings[prop] : (_is.string(mappings[prop]) ? [mappings[prop]] : [prop]);
3396
- $.each(maps, function(i, map){
3397
- value = _.obj.prop(object, map);
3398
- if (_is.undef(value)) return; // continue
3399
- if (validators[prop](value)){
3400
- _.obj.prop(target, prop, value);
3401
- return false; // break
3402
- }
3403
- });
3404
- }
3405
- return target;
3406
- };
3407
 
3408
- /**
3409
- * @summary Get or set a property value given its `name`.
3410
- * @memberof FooGallery.utils.obj.
3411
- * @function prop
3412
- * @param {Object} object - The object to inspect for the property.
3413
- * @param {string} name - The name of the property to fetch. This can be a `.` notated name.
3414
- * @param {*} [value] - If supplied this is the value to set for the property.
3415
- * @returns {*} The value for the `name` property, if it does not exist then `undefined`.
3416
- * @returns {undefined} If a `value` is supplied this method returns nothing.
3417
- * @example {@caption Shows how to get a property value from an object.}{@run true}
3418
- * // alias the FooGallery.utils.obj namespace
3419
- * var _obj = FooGallery.utils.obj,
3420
- * // create an object to test
3421
- * object = {
3422
- * "name": "My Object",
3423
- * "some": {
3424
- * "thing": 123
3425
- * }
3426
- * };
3427
- *
3428
- * console.log( _obj.prop( object, "name" ) ); // => "My Object"
3429
- * console.log( _obj.prop( object, "some.thing" ) ); // => 123
3430
- * @example {@caption Shows how to set a property value for an object.}{@run true}
3431
- * // alias the FooGallery.utils.obj namespace
3432
- * var _obj = FooGallery.utils.obj,
3433
- * // create an object to test
3434
- * object = {
3435
- * "name": "My Object",
3436
- * "some": {
3437
- * "thing": 123
3438
- * }
3439
- * };
3440
- *
3441
- * _obj.prop( object, "name", "My Updated Object" );
3442
- * _obj.prop( object, "some.thing", 987 );
3443
- *
3444
- * console.log( object ); // => { "name": "My Updated Object", "some": { "thing": 987 } }
3445
- */
3446
- _.obj.prop = function(object, name, value){
3447
- if (!_is.object(object) || _is.empty(name)) return;
3448
- var parts, last;
3449
- if (_is.undef(value)){
3450
- if (_str.contains(name, '.')){
3451
- parts = name.split('.');
3452
- last = parts.length - 1;
3453
- $.each(parts, function(i, part){
3454
- if (i === last){
3455
- value = object[part];
3456
- } else if (_is.hash(object[part])) {
3457
- object = object[part];
3458
- } else {
3459
- // exit early
3460
- return false;
3461
- }
3462
- });
3463
- } else if (!_is.undef(object[name])){
3464
- value = object[name];
3465
- }
3466
- return value;
3467
- }
3468
- if (_str.contains(name, '.')){
3469
- parts = name.split('.');
3470
- last = parts.length - 1;
3471
- $.each(parts, function(i, part){
3472
- if (i === last){
3473
- object[part] = value;
3474
- } else {
3475
- object = _is.hash(object[part]) ? object[part] : (object[part] = {});
3476
- }
3477
- });
3478
- } else if (!_is.undef(object[name])){
3479
- object[name] = value;
3480
- }
3481
- };
3482
 
3483
- //######################
3484
- //## Type Definitions ##
3485
- //######################
3486
 
3487
- /**
3488
- * @summary An object used by the {@link FooGallery.utils.obj.mergeValid|mergeValid} method to map new values onto the `target` object.
3489
- * @typedef {Object.<string,(string|Array.<string>)>} FooGallery.utils.obj~Mappings
3490
- * @description The mappings object is a single level object. If you want to map a property from/to a child object on either the source or target objects you must supply the name using `.` notation as seen in the below example with the `"name.first"` to `"Name.Short"` mapping.
3491
- * @example {@caption The basic structure of a mappings object is the below.}
3492
- * {
3493
- * "TargetName": "SourceName", // for top level properties
3494
- * "Child.TargetName": "Child.SourceName" // for child properties
3495
- * }
3496
- * @example {@caption Given the following target object.}
3497
- * var target = {
3498
- * "name": {
3499
- * "first": "",
3500
- * "last": null
3501
- * },
3502
- * "age": 0
3503
- * };
3504
- * @example {@caption And the following object to merge.}
3505
- * var object = {
3506
- * "Name": {
3507
- * "Full": "Christopher",
3508
- * "Short": "Chris"
3509
- * },
3510
- * "Age": 32
3511
- * };
3512
- * @example {@caption The mappings object would look like the below.}
3513
- * var mappings = {
3514
- * "name.first": "Name.Short",
3515
- * "age": "Age"
3516
- * };
3517
- * @example {@caption If you want the `"name.first"` property to try to use the `"Name.Short"` value but fallback to `"Name.Proper"` you can specify the mapping value as an array.}
3518
- * var mappings = {
3519
- * "name.first": [ "Name.Short", "Name.Proper" ],
3520
- * "age": "Age"
3521
- * };
3522
- */
3523
 
3524
- /**
3525
- * @summary An object used by the {@link FooGallery.utils.obj.mergeValid|mergeValid} method to validate properties.
3526
- * @typedef {Object.<string,function(*):boolean>} FooGallery.utils.obj~Validators
3527
- * @description The validators object is a single level object. If you want to validate a property of a child object you must supply the name using `.` notation as seen in the below example with the `"name.first"` and `"name.last"` properties.
3528
- *
3529
- * Any function that accepts a value to test as the first argument and returns a boolean can be used as a validator. This means the majority of the {@link FooGallery.utils.is} methods can be used directly. If the property supports multiple types just provide your own function as seen with `"name.last"` in the below example.
3530
- * @example {@caption The basic structure of a validators object is the below.}
3531
- * {
3532
- * "PropName": function(*):boolean, // for top level properties
3533
- * "Child.PropName": function(*):boolean // for child properties
3534
- * }
3535
- * @example {@caption Given the following target object.}
3536
- * var target = {
3537
- * "name": {
3538
- * "first": "", // must be a string
3539
- * "last": null // must be a string or null
3540
- * },
3541
- * "age": 0 // must be a number
3542
- * };
3543
- * @example {@caption The validators object could be created as seen below.}
3544
- * // alias the FooGallery.utils.is namespace
3545
- * var _is = FooGallery.utils.is;
3546
- *
3547
- * var validators = {
3548
- * "name.first": _is.string,
3549
- * "name.last": function(value){
3550
- * return _is.string(value) || value === null;
3551
- * },
3552
- * "age": _is.number
3553
- * };
3554
- */
3555
 
3556
- })(
3557
- // dependencies
3558
- FooGallery.utils.$,
3559
- FooGallery.utils,
3560
- FooGallery.utils.is,
3561
- FooGallery.utils.fn,
3562
- FooGallery.utils.str
3563
- );
3564
- (function($, _, _is){
3565
- // only register methods if this version is the current version
3566
- if (_.version !== '0.2.2') return;
3567
 
3568
- // any methods that have dependencies but don't fall into a specific subset or namespace can be added here
 
3569
 
3570
- /**
3571
- * @summary The callback for the {@link FooGallery.utils.ready} method.
3572
- * @callback FooGallery.utils~readyCallback
3573
- * @param {jQuery} $ - The instance of jQuery the plugin was registered with.
3574
- * @this window
3575
- * @see Take a look at the {@link FooGallery.utils.ready} method for example usage.
3576
- */
 
3577
 
3578
- /**
3579
- * @summary Waits for the DOM to be accessible and then executes the supplied callback.
3580
- * @memberof FooGallery.utils.
3581
- * @function ready
3582
- * @param {FooGallery.utils~readyCallback} callback - The function to execute once the DOM is accessible.
3583
- * @example {@caption This method can be used as a replacement for the jQuery ready callback to avoid an error in another script stopping our scripts from running.}
3584
- * FooGallery.utils.ready(function($){
3585
- * // do something
3586
- * });
3587
- */
3588
- _.ready = function (callback) {
3589
- function onready(){
3590
- try { callback.call(window, _.$); }
3591
- catch(err) { console.error(err); }
3592
- }
3593
- if (Function('/*@cc_on return true@*/')() ? document.readyState === "complete" : document.readyState !== "loading") onready();
3594
- else document.addEventListener('DOMContentLoaded', onready, false);
3595
- };
3596
-
3597
- /**
3598
- * @summary Executed once for each array index or object property until it returns a truthy value.
3599
- * @callback FooGallery.utils~findCallback
3600
- * @param {*} value - The current value being iterated over. This could be either an element in an array or the value of an object property.
3601
- * @param {(number|string)} [key] - The array index or property name of the `value`.
3602
- * @param {(Object|Array)} [object] - The array or object currently being searched.
3603
- * @returns {boolean} A truthy value.
3604
- */
3605
-
3606
- /**
3607
- * @summary Returns the value of the first element or property in the provided target that satisfies the provided test function.
3608
- * @memberof FooGallery.utils.
3609
- * @function find
3610
- * @param {(Object|Array)} target - The object or array to search.
3611
- * @param {FooGallery.utils~findCallback} callback - A function to execute for each value in the target.
3612
- * @param {*} [thisArg] - The `this` value within the `callback`.
3613
- * @returns {*} The value of the first element or property in the provided target that satisfies the provided test function. Otherwise, `undefined` is returned.
3614
- */
3615
- _.find = function(target, callback, thisArg){
3616
- if (!_is.fn(callback)) return;
3617
- thisArg = _is.undef(thisArg) ? callback : thisArg;
3618
- var i, l;
3619
- if (_is.array(target)){
3620
- for (i = 0, l = target.length; i < l; i++){
3621
- if (callback.call(thisArg, target[i], i, target)){
3622
- return target[i];
3623
- }
3624
- }
3625
- } else if (_is.object(target)){
3626
- var keys = Object.keys(target);
3627
- for (i = 0, l = keys.length; i < l; i++){
3628
- if (callback.call(thisArg, target[keys[i]], keys[i], target)){
3629
- return target[keys[i]];
3630
- }
3631
- }
3632
- }
3633
- };
3634
-
3635
- /**
3636
- * @summary Executed once for each array index or object property.
3637
- * @callback FooGallery.utils~eachCallback
3638
- * @param {*} value - The current value being iterated over. This could be either an element in an array or the value of an object property.
3639
- * @param {(number|string)} [key] - The array index or property name of the `value`.
3640
- * @param {(Object|Array)} [object] - The array or object currently being searched.
3641
- * @returns {(boolean|void)} Return `false` to break out of the loop, all other values are ignored.
3642
- */
3643
-
3644
- /**
3645
- * @summary Iterate over all indexes or properties of the provided target executing the provided callback once per value.
3646
- * @memberof FooGallery.utils.
3647
- * @function each
3648
- * @param {(Object|Array)} object - The object or array to search.
3649
- * @param {FooGallery.utils~eachCallback} callback - A function to execute for each value in the target.
3650
- * @param {*} [thisArg] - The `this` value within the `callback`.
3651
- */
3652
- _.each = function(object, callback, thisArg){
3653
- if (!_is.fn(callback)) return;
3654
- thisArg = _is.undef(thisArg) ? callback : thisArg;
3655
- var i, l, result;
3656
- if (_is.array(object)){
3657
- for (i = 0, l = object.length; i < l; i++){
3658
- result = callback.call(thisArg, object[i], i, object);
3659
- if (result === false) break;
3660
- }
3661
- } else if (_is.object(object)){
3662
- var keys = Object.keys(object);
3663
- for (i = 0, l = keys.length; i < l; i++){
3664
- result = callback.call(thisArg, object[keys[i]], keys[i], object);
3665
- if (result === false) break;
3666
- }
3667
- }
3668
- };
3669
-
3670
- /**
3671
- * @summary Checks if a value exists within an array.
3672
- * @memberof FooGallery.utils.
3673
- * @function inArray
3674
- * @param {*} needle - The value to search for.
3675
- * @param {[]} haystack - The array to search within.
3676
- * @returns {number} Returns the index of the value if found otherwise -1.
3677
- */
3678
- _.inArray = function(needle, haystack){
3679
- if (_is.array(haystack)){
3680
- return haystack.indexOf(needle);
3681
- }
3682
- return -1;
3683
- };
3684
-
3685
- /**
3686
- * @summary Compares two version numbers.
3687
- * @memberof FooGallery.utils.
3688
- * @function versionCompare
3689
- * @param {string} version1 - The first version to use in the comparison.
3690
- * @param {string} version2 - The second version to compare to the first.
3691
- * @returns {number} `0` if the version are equal.
3692
- * `-1` if `version1` is less than `version2`.
3693
- * `1` if `version1` is greater than `version2`.
3694
- * `NaN` if either of the supplied versions do not conform to MAJOR.MINOR.PATCH format.
3695
- * @description This method will compare two version numbers that conform to the basic MAJOR.MINOR.PATCH format returning the result as a simple number. This method will handle short version string comparisons e.g. `1.0` versus `1.0.1`.
3696
- * @example {@caption The following shows the results of comparing various version strings.}
3697
- * console.log( FooGallery.utils.versionCompare( "0", "0" ) ); // => 0
3698
- * console.log( FooGallery.utils.versionCompare( "0.0", "0" ) ); // => 0
3699
- * console.log( FooGallery.utils.versionCompare( "0.0", "0.0.0" ) ); // => 0
3700
- * console.log( FooGallery.utils.versionCompare( "0.1", "0.0.0" ) ); // => 1
3701
- * console.log( FooGallery.utils.versionCompare( "0.1", "0.0.1" ) ); // => 1
3702
- * console.log( FooGallery.utils.versionCompare( "1", "0.1" ) ); // => 1
3703
- * console.log( FooGallery.utils.versionCompare( "1.10", "1.9" ) ); // => 1
3704
- * console.log( FooGallery.utils.versionCompare( "1.9", "1.10" ) ); // => -1
3705
- * console.log( FooGallery.utils.versionCompare( "1", "1.1" ) ); // => -1
3706
- * console.log( FooGallery.utils.versionCompare( "1.0.9", "1.1" ) ); // => -1
3707
- * @example {@caption If either of the supplied version strings does not match the MAJOR.MINOR.PATCH format then `NaN` is returned.}
3708
- * console.log( FooGallery.utils.versionCompare( "not-a-version", "1.1" ) ); // => NaN
3709
- * console.log( FooGallery.utils.versionCompare( "1.1", "not-a-version" ) ); // => NaN
3710
- * console.log( FooGallery.utils.versionCompare( "not-a-version", "not-a-version" ) ); // => NaN
3711
- */
3712
- _.versionCompare = function(version1, version2){
3713
- // if either of the versions do not match the expected format return NaN
3714
- if (!(/[\d.]/.test(version1) && /[\d.]/.test(version2))) return NaN;
3715
-
3716
- /**
3717
- * @summary Splits and parses the given version string into a numeric array.
3718
- * @param {string} version - The version string to split and parse.
3719
- * @returns {Array.<number>}
3720
- * @ignore
3721
- */
3722
- function split(version){
3723
- var parts = version.split('.'), result = [];
3724
- for(var i = 0, len = parts.length; i < len; i++){
3725
- result[i] = parseInt(parts[i]);
3726
- if (isNaN(result[i])) result[i] = 0;
3727
- }
3728
- return result;
3729
- }
3730
-
3731
- // get the base numeric arrays for each version
3732
- var v1parts = split(version1),
3733
- v2parts = split(version2);
3734
-
3735
- // ensure both arrays are the same length by padding the shorter with 0
3736
- while (v1parts.length < v2parts.length) v1parts.push(0);
3737
- while (v2parts.length < v1parts.length) v2parts.push(0);
3738
-
3739
- // perform the actual comparison
3740
- for (var i = 0; i < v1parts.length; ++i) {
3741
- if (v2parts.length === i) return 1;
3742
- if (v1parts[i] === v2parts[i]) continue;
3743
- if (v1parts[i] > v2parts[i]) return 1;
3744
- else return -1;
3745
- }
3746
- if (v1parts.length !== v2parts.length) return -1;
3747
- return 0;
3748
- };
3749
-
3750
- // A variable to hold the last number used to generate an ID in the current page.
3751
- var uniqueId = 0;
3752
-
3753
- /**
3754
- * @summary Generate and apply a unique id for the given `$element`.
3755
- * @memberof FooGallery.utils.
3756
- * @function uniqueId
3757
- * @param {jQuery} $element - The jQuery element object to retrieve an id from or generate an id for.
3758
- * @param {string} [prefix="uid-"] - A prefix to append to the start of any generated ids.
3759
- * @returns {string} Either the `$element`'s existing id or a generated one that has been applied to it.
3760
- * @example {@run true}
3761
- * // alias the FooGallery.utils namespace
3762
- * var _ = FooGallery.utils;
3763
- *
3764
- * // create some elements to test
3765
- * var $hasId = $("<span/>", {id: "exists"});
3766
- * var $generatedId = $("<span/>");
3767
- * var $generatedPrefixedId = $("<span/>");
3768
- *
3769
- * console.log( _.uniqueId( $hasId ) ); // => "exists"
3770
- * console.log( $hasId.attr( "id" ) ); // => "exists"
3771
- * console.log( _.uniqueId( $generatedId ) ); // => "uid-1"
3772
- * console.log( $generatedId.attr( "id" ) ); // => "uid-1"
3773
- * console.log( _.uniqueId( $generatedPrefixedId, "plugin-" ) ); // => "plugin-2"
3774
- * console.log( $generatedPrefixedId.attr( "id" ) ); // => "plugin-2"
3775
- */
3776
- _.uniqueId = function($element, prefix){
3777
- var id = $element.attr('id');
3778
- if (_is.empty(id)){
3779
- prefix = _is.string(prefix) && !_is.empty(prefix) ? prefix : "uid-";
3780
- id = prefix + (++uniqueId);
3781
- $element.attr('id', id).data('__uniqueId__', true);
3782
- }
3783
- return id;
3784
- };
3785
-
3786
- /**
3787
- * @summary Remove the id from the given `$element` if it was set using the {@link FooGallery.utils.uniqueId|uniqueId} method.
3788
- * @memberof FooGallery.utils.
3789
- * @function removeUniqueId
3790
- * @param {jQuery} $element - The jQuery element object to remove a generated id from.
3791
- * @example {@run true}
3792
- * // alias the FooGallery.utils namespace
3793
- * var _ = FooGallery.utils;
3794
- *
3795
- * // create some elements to test
3796
- * var $hasId = $("<span/>", {id: "exists"});
3797
- * var $generatedId = $("<span/>");
3798
- * var $generatedPrefixedId = $("<span/>");
3799
- *
3800
- * console.log( _.uniqueId( $hasId ) ); // => "exists"
3801
- * console.log( _.uniqueId( $generatedId ) ); // => "uid-1"
3802
- * console.log( _.uniqueId( $generatedPrefixedId, "plugin-" ) ); // => "plugin-2"
3803
- */
3804
- _.removeUniqueId = function($element){
3805
- if ($element.data('__uniqueId__')){
3806
- $element.removeAttr('id').removeData('__uniqueId__');
3807
- }
3808
- };
3809
-
3810
- /**
3811
- * @summary Convert CSS class names into CSS selectors.
3812
- * @memberof FooGallery.utils.
3813
- * @function selectify
3814
- * @param {(string|string[]|object)} classes - A space delimited string of CSS class names or an array of them with each item being included in the selector using the OR (`,`) syntax as a separator. If an object is supplied the result will be an object with the same property names but the values converted to selectors.
3815
- * @returns {(object|string)}
3816
- * @example {@caption Shows how the method can be used.}
3817
- * // alias the FooGallery.utils namespace
3818
- * var _ = FooGallery.utils;
3819
- *
3820
- * console.log( _.selectify("my-class") ); // => ".my-class"
3821
- * console.log( _.selectify("my-class my-other-class") ); // => ".my-class.my-other-class"
3822
- * console.log( _.selectify(["my-class", "my-other-class"]) ); // => ".my-class,.my-other-class"
3823
- * console.log( _.selectify({
3824
- * class1: "my-class",
3825
- * class2: "my-class my-other-class",
3826
- * class3: ["my-class", "my-other-class"]
3827
- * }) ); // => { class1: ".my-class", class2: ".my-class.my-other-class", class3: ".my-class,.my-other-class" }
3828
- */
3829
- _.selectify = function (classes) {
3830
- if (_is.empty(classes)) return null;
3831
- if (_is.hash(classes)) {
3832
- var result = {}, selector;
3833
- for (var name in classes) {
3834
- if (!classes.hasOwnProperty(name)) continue;
3835
- selector = _.selectify(classes[name]);
3836
- if (selector) {
3837
- result[name] = selector;
3838
- }
3839
- }
3840
- return result;
3841
- }
3842
- if (_is.string(classes) || _is.array(classes)) {
3843
- if (_is.string(classes)) classes = [classes];
3844
- return classes.map(function(str){
3845
- return _is.string(str) ? "." + str.split(/\s/g).join(".") : null;
3846
- }).join(",");
3847
- }
3848
- return null;
3849
- };
3850
-
3851
- /**
3852
- * @summary Parses the supplied `src` and `srcset` values and returns the best matching URL for the supplied render size.
3853
- * @memberof FooGallery.utils.
3854
- * @function src
3855
- * @param {string} src - The default src for the image.
3856
- * @param {string} srcset - The srcset containing additional image sizes.
3857
- * @param {number} srcWidth - The width of the `src` image.
3858
- * @param {number} srcHeight - The height of the `src` image.
3859
- * @param {number} renderWidth - The rendered width of the image element.
3860
- * @param {number} renderHeight - The rendered height of the image element.
3861
- * @param {number} [devicePixelRatio] - The device pixel ratio to use while parsing. Defaults to the current device pixel ratio.
3862
- * @returns {(string|null)} Returns the parsed responsive src or null if no src is provided.
3863
- * @description This can be used to parse the correct src to use when loading an image through JavaScript.
3864
- * @example {@caption The following shows using the method with the srcset w-descriptor.}{@run true}
3865
- * var src = "test-240x120.jpg",
3866
- * width = 240, // the naturalWidth of the 'src' image
3867
- * height = 120, // the naturalHeight of the 'src' image
3868
- * srcset = "test-480x240.jpg 480w, test-720x360.jpg 720w, test-960x480.jpg 960w";
3869
- *
3870
- * console.log( FooGallery.utils.src( src, srcset, width, height, 240, 120, 1 ) ); // => "test-240x120.jpg"
3871
- * console.log( FooGallery.utils.src( src, srcset, width, height, 240, 120, 2 ) ); // => "test-480x240.jpg"
3872
- * console.log( FooGallery.utils.src( src, srcset, width, height, 480, 240, 1 ) ); // => "test-480x240.jpg"
3873
- * console.log( FooGallery.utils.src( src, srcset, width, height, 480, 240, 2 ) ); // => "test-960x480.jpg"
3874
- * console.log( FooGallery.utils.src( src, srcset, width, height, 720, 360, 1 ) ); // => "test-720x360.jpg"
3875
- * console.log( FooGallery.utils.src( src, srcset, width, height, 960, 480, 1 ) ); // => "test-960x480.jpg"
3876
- * @example {@caption The following shows using the method with the srcset h-descriptor.}{@run true}
3877
- * var src = "test-240x120.jpg",
3878
- * width = 240, // the naturalWidth of the 'src' image
3879
- * height = 120, // the naturalHeight of the 'src' image
3880
- * srcset = "test-480x240.jpg 240h, test-720x360.jpg 360h, test-960x480.jpg 480h";
3881
- *
3882
- * console.log( FooGallery.utils.src( src, srcset, width, height, 240, 120, 1 ) ); // => "test-240x120.jpg"
3883
- * console.log( FooGallery.utils.src( src, srcset, width, height, 240, 120, 2 ) ); // => "test-480x240.jpg"
3884
- * console.log( FooGallery.utils.src( src, srcset, width, height, 480, 240, 1 ) ); // => "test-480x240.jpg"
3885
- * console.log( FooGallery.utils.src( src, srcset, width, height, 480, 240, 2 ) ); // => "test-960x480.jpg"
3886
- * console.log( FooGallery.utils.src( src, srcset, width, height, 720, 360, 1 ) ); // => "test-720x360.jpg"
3887
- * console.log( FooGallery.utils.src( src, srcset, width, height, 960, 480, 1 ) ); // => "test-960x480.jpg"
3888
- * @example {@caption The following shows using the method with the srcset x-descriptor.}{@run true}
3889
- * var src = "test-240x120.jpg",
3890
- * width = 240, // the naturalWidth of the 'src' image
3891
- * height = 120, // the naturalHeight of the 'src' image
3892
- * srcset = "test-480x240.jpg 2x, test-720x360.jpg 3x, test-960x480.jpg 4x";
3893
- *
3894
- * console.log( FooGallery.utils.src( src, srcset, width, height, 240, 120, 1 ) ); // => "test-240x120.jpg"
3895
- * console.log( FooGallery.utils.src( src, srcset, width, height, 240, 120, 2 ) ); // => "test-480x240.jpg"
3896
- * console.log( FooGallery.utils.src( src, srcset, width, height, 480, 240, 1 ) ); // => "test-240x120.jpg"
3897
- * console.log( FooGallery.utils.src( src, srcset, width, height, 480, 240, 2 ) ); // => "test-480x240.jpg"
3898
- * console.log( FooGallery.utils.src( src, srcset, width, height, 720, 360, 1 ) ); // => "test-240x120.jpg"
3899
- * console.log( FooGallery.utils.src( src, srcset, width, height, 960, 480, 1 ) ); // => "test-240x120.jpg"
3900
- */
3901
- _.src = function(src, srcset, srcWidth, srcHeight, renderWidth, renderHeight, devicePixelRatio){
3902
- if (!_is.string(src)) return null;
3903
- // if there is no srcset just return the src
3904
- if (!_is.string(srcset)) return src;
3905
-
3906
- // first split the srcset into its individual sources
3907
- var sources = srcset.replace(/(\s[\d.]+[whx]),/g, '$1 @,@ ').split(' @,@ ');
3908
- // then parse those sources into objects containing the url, width, height and pixel density
3909
- var list = sources.map(function (val) {
3910
- return {
3911
- url: /^\s*(\S*)/.exec(val)[1],
3912
- w: parseFloat((/\S\s+(\d+)w/.exec(val) || [0, Infinity])[1]),
3913
- h: parseFloat((/\S\s+(\d+)h/.exec(val) || [0, Infinity])[1]),
3914
- x: parseFloat((/\S\s+([\d.]+)x/.exec(val) || [0, 1])[1])
3915
- };
3916
- });
3917
-
3918
- // if there is no items parsed from the srcset then just return the src
3919
- if (!list.length) return src;
3920
 
3921
- // add the current src into the mix by inspecting the first parsed item to figure out how to handle it
3922
- list.unshift({
3923
- url: src,
3924
- w: list[0].w !== Infinity && list[0].h === Infinity ? srcWidth : Infinity,
3925
- h: list[0].h !== Infinity && list[0].w === Infinity ? srcHeight : Infinity,
3926
- x: 1
3927
- });
3928
 
3929
- // get the current viewport info and use it to determine the correct src to load
3930
- var dpr = _is.number(devicePixelRatio) ? devicePixelRatio : (window.devicePixelRatio || 1),
3931
- area = {w: renderWidth * dpr, h: renderHeight * dpr, x: dpr},
3932
- props = ['w','h','x'];
 
 
 
 
 
 
 
3933
 
3934
- // first check each of the viewport properties against the max values of the same properties in our src array
3935
- // only src's with a property greater than the viewport or equal to the max are kept
3936
- props.forEach(function (prop) {
3937
- var max = Math.max.apply(null, list.map(function (item) {
3938
- return item[prop];
3939
- }));
3940
- list = list.filter(function (item) {
3941
- return item[prop] >= area[prop] || item[prop] === max;
3942
- });
3943
- });
3944
 
3945
- // next reduce our src array by comparing the viewport properties against the minimum values of the same properties of each src
3946
- // only src's with a property equal to the minimum are kept
3947
- props.forEach(function (prop) {
3948
- var min = Math.min.apply(null, list.map(function (item) {
3949
- return item[prop];
3950
- }));
3951
- list = list.filter(function (item) {
3952
- return item[prop] === min;
3953
- });
3954
- });
3955
 
3956
- // return the first url as it is the best match for the current viewport
3957
- return list[0].url;
3958
- };
 
 
3959
 
3960
- /**
3961
- * @summary Get the scroll parent for the supplied element optionally filtering by axis.
3962
- * @memberof FooGallery.utils.
3963
- * @function scrollParent
3964
- * @param {(string|Element|jQuery)} element - The selector, element or jQuery element to find the scroll parent of.
3965
- * @param {string} [axis="xy"] - The axis to check. By default this method will check both the X and Y axis.
3966
- * @param {jQuery} [def] - The default jQuery element to return if no result was found. Defaults to the supplied elements document.
3967
- * @returns {jQuery}
3968
- */
3969
- _.scrollParent = function(element, axis, def){
3970
- element = _is.jq(element) ? element : $(element);
3971
- axis = _is.string(axis) && /^(x|y|xy|yx)$/i.test(axis) ? axis : "xy";
3972
- var $doc = $(!!element.length && element[0].ownerDocument || document);
3973
- def = _is.jq(def) ? def : $doc;
3974
-
3975
- if (!element.length) return def;
3976
-
3977
- var position = element.css("position"),
3978
- excludeStaticParent = position === "absolute",
3979
- scroll = /(auto|scroll)/i, axisX = /x/i, axisY = /y/i,
3980
- $parent = element.parentsUntil(def).filter(function(i, el){
3981
- var $el = $(this);
3982
- if (excludeStaticParent && $el.css("position") === "static") return false;
3983
- var scrollY = axisY.test(axis) && el.scrollHeight > el.clientHeight && scroll.test($el.css("overflow-y")),
3984
- scrollX = axisX.test(axis) && el.scrollWidth > el.clientWidth && scroll.test($el.css("overflow-x"));
3985
- return scrollY || scrollX;
3986
- }).eq(0);
3987
-
3988
- if ($parent.is("html")) $parent = $doc;
3989
- return position === "fixed" || !$parent.length ? def : $parent;
3990
- };
3991
 
3992
- })(
3993
- // dependencies
3994
- FooGallery.utils.$,
3995
- FooGallery.utils,
3996
- FooGallery.utils.is
3997
- );
3998
- (function($, _, _is){
3999
- // only register methods if this version is the current version
4000
- if (_.version !== '0.2.2') return;
4001
 
4002
- /**
4003
- * @summary Contains common utility methods and members for the CSS animation property.
4004
- * @memberof FooGallery.utils.
4005
- * @namespace animation
4006
- */
4007
- _.animation = {};
4008
 
4009
- function raf(callback){
4010
- return setTimeout(callback, 1000/60);
4011
- }
 
 
 
4012
 
4013
- function caf(requestID){
4014
- clearTimeout(requestID);
4015
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4016
 
4017
- /**
4018
- * @summary A cross browser wrapper for the `requestAnimationFrame` method.
4019
- * @memberof FooGallery.utils.animation.
4020
- * @function requestFrame
4021
- * @param {function} callback - The function to call when it's time to update your animation for the next repaint.
4022
- * @return {number} - The request id that uniquely identifies the entry in the callback list.
4023
- */
4024
- _.animation.requestFrame = (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || raf).bind(window);
4025
 
4026
- /**
4027
- * @summary A cross browser wrapper for the `cancelAnimationFrame` method.
4028
- * @memberof FooGallery.utils.animation.
4029
- * @function cancelFrame
4030
- * @param {number} requestID - The ID value returned by the call to {@link FooGallery.utils.animation.requestFrame|requestFrame} that requested the callback.
4031
- */
4032
- _.animation.cancelFrame = (window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame || caf).bind(window);
 
 
 
 
 
 
 
 
 
 
 
 
4033
 
4034
- // create a test element to check for the existence of the various animation properties
4035
- var testElement = document.createElement('div');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4036
 
4037
- /**
4038
- * @summary Whether or not animations are supported by the current browser.
4039
- * @memberof FooGallery.utils.animation.
4040
- * @name supported
4041
- * @type {boolean}
4042
- */
4043
- _.animation.supported = (
4044
- /**
4045
- * @ignore
4046
- * @summary Performs a one time test to see if animations are supported
4047
- * @param {HTMLElement} el - An element to test with.
4048
- * @returns {boolean} `true` if animations are supported.
4049
- */
4050
- function(el){
4051
- var style = el.style;
4052
- return _is.string(style['animation'])
4053
- || _is.string(style['WebkitAnimation'])
4054
- || _is.string(style['MozAnimation'])
4055
- || _is.string(style['msAnimation'])
4056
- || _is.string(style['OAnimation']);
4057
- }
4058
- )(testElement);
4059
 
4060
- /**
4061
- * @summary The `animationend` event name for the current browser.
4062
- * @memberof FooGallery.utils.animation.
4063
- * @name end
4064
- * @type {string}
4065
- * @description Depending on the browser this returns one of the following values:
4066
- *
4067
- * <ul><!--
4068
- * --><li>`"animationend"`</li><!--
4069
- * --><li>`"webkitAnimationEnd"`</li><!--
4070
- * --><li>`"msAnimationEnd"`</li><!--
4071
- * --><li>`"oAnimationEnd"`</li><!--
4072
- * --><li>`null` - If the browser doesn't support animations</li><!--
4073
- * --></ul>
4074
- */
4075
- _.animation.end = (
4076
- /**
4077
- * @ignore
4078
- * @summary Performs a one time test to determine which `animationend` event to use for the current browser.
4079
- * @param {HTMLElement} el - An element to test with.
4080
- * @returns {?string} The correct `animationend` event for the current browser, `null` if the browser doesn't support animations.
4081
- */
4082
- function(el){
4083
- var style = el.style;
4084
- if (_is.string(style['animation'])) return 'animationend';
4085
- if (_is.string(style['WebkitAnimation'])) return 'webkitAnimationEnd';
4086
- if (_is.string(style['MozAnimation'])) return 'animationend';
4087
- if (_is.string(style['msAnimation'])) return 'msAnimationEnd';
4088
- if (_is.string(style['OAnimation'])) return 'oAnimationEnd';
4089
- return null;
4090
- }
4091
- )(testElement);
4092
 
4093
- /**
4094
- * @summary Gets the `animation-duration` value for the supplied jQuery element.
4095
- * @memberof FooGallery.utils.animation.
4096
- * @function duration
4097
- * @param {jQuery} $element - The jQuery element to retrieve the duration from.
4098
- * @param {number} [def=0] - The default value to return if no duration is set.
4099
- * @returns {number} The value of the `animation-duration` property converted to a millisecond value.
4100
- */
4101
- _.animation.duration = function($element, def){
4102
- def = _is.number(def) ? def : 0;
4103
- if (!_is.jq($element)) return def;
4104
- // we can use jQuery.css() method to retrieve the value cross browser
4105
- var duration = $element.css('animation-duration');
4106
- if (/^([\d.]*)+?(ms|s)/i.test(duration)){
4107
- // if we have a valid duration value split it into it's components
4108
- var parts = duration.split(","), max = 0;
4109
- parts.forEach(function(part){
4110
- var match = part.match(/^\s*?([\d.]*)+?(ms|s)\s*?$/i),
4111
- value = parseFloat(match[1]),
4112
- unit = match[2].toLowerCase();
4113
- if (unit === 's'){
4114
- // convert seconds to milliseconds
4115
- value = value * 1000;
4116
- }
4117
- if (value > max) max = value;
4118
- });
4119
- return max;
4120
- }
4121
- return def;
4122
- };
4123
 
4124
- /**
4125
- * @summary Gets the `animation-iteration-count` value for the supplied jQuery element.
4126
- * @memberof FooGallery.utils.animation.
4127
- * @function iterations
4128
- * @param {jQuery} $element - The jQuery element to retrieve the duration from.
4129
- * @param {number} [def=1] - The default value to return if no iteration count is set.
4130
- * @returns {number} The value of the `animation-iteration-count` property.
4131
- */
4132
- _.animation.iterations = function($element, def){
4133
- def = _is.number(def) ? def : 1;
4134
- if (!_is.jq($element)) return def;
4135
- // we can use jQuery.css() method to retrieve the value cross browser
4136
- var iterations = $element.css('animation-iteration-count');
4137
- if (/^(([\d.]+)|infinite)/i.test(iterations)){
4138
- // if we have a valid iterations value split it into it's components
4139
- var parts = iterations.split(","), max = 0;
4140
- parts.forEach(function(part){
4141
- var value = parseFloat(part);
4142
- if (isNaN(value)) value = Infinity;
4143
- if (value > max) max = value;
4144
- });
4145
- return max;
4146
- }
4147
- return def;
4148
- };
4149
 
4150
- /**
4151
- * @summary The callback function to execute when starting a animation.
4152
- * @callback FooGallery.utils.animation~startCallback
4153
- * @param {jQuery} $element - The element to start the animation on.
4154
- * @this Element
4155
- */
 
4156
 
4157
- /**
4158
- * @summary Start a animation by toggling the supplied `className` on the `$element`.
4159
- * @memberof FooGallery.utils.animation.
4160
- * @function start
4161
- * @param {jQuery} $element - The jQuery element to start the animation on.
4162
- * @param {(string|FooGallery.utils.animation~startCallback)} classNameOrFunc - One or more class names (separated by spaces) to be toggled or a function that performs the required actions to start the animation.
4163
- * @param {boolean} [state] - A Boolean (not just truthy/falsy) value to determine whether the class should be added or removed.
4164
- * @param {number} [timeout] - The maximum time, in milliseconds, to wait for the `animationend` event to be raised. If not provided this will be automatically set to the elements `animation-duration` multiplied by the `animation-iteration-count` property plus an extra 50 milliseconds.
4165
- * @returns {Promise}
4166
- * @description This method lets us use CSS animations by toggling a class and using the `animationend` event to perform additional actions once the animation has completed across all browsers. In browsers that do not support animations this method would behave the same as if just calling jQuery's `.toggleClass` method.
4167
- *
4168
- * The last parameter `timeout` is used to create a timer that behaves as a safety net in case the `animationend` event is never raised and ensures the deferred returned by this method is resolved or rejected within a specified time.
4169
- *
4170
- * If no `timeout` is supplied the `animation-duration` and `animation-iterations-count` must be set on the `$element` before this method is called so one can be generated.
4171
- * @see {@link https://developer.mozilla.org/en/docs/Web/CSS/animation-duration|animation-duration - CSS | MDN} for more information on the `animation-duration` CSS property.
4172
- */
4173
- _.animation.start = function($element, classNameOrFunc, state, timeout){
4174
- var deferred = $.Deferred(), promise = deferred.promise();
4175
-
4176
- $element = $element.first();
4177
-
4178
- if (_.animation.supported){
4179
- $element.prop('offsetTop');
4180
- var safety = $element.data('animation_safety');
4181
- if (_is.hash(safety) && _is.number(safety.timer)){
4182
- clearTimeout(safety.timer);
4183
- $element.removeData('animation_safety').off(_.animation.end + '.utils');
4184
- safety.deferred.reject();
4185
- }
4186
- if (!_is.number(timeout)){
4187
- var iterations = _.animation.iterations($element);
4188
- if (iterations === Infinity){
4189
- deferred.reject("No timeout supplied with an infinite animation.");
4190
- return promise;
4191
- }
4192
- timeout = (_.animation.duration($element) * iterations) + 50;
4193
- }
4194
- safety = {
4195
- deferred: deferred,
4196
- timer: setTimeout(function(){
4197
- // This is the safety net in case a animation fails for some reason and the animationend event is never raised.
4198
- // This will remove the bound event and resolve the deferred
4199
- $element.removeData('animation_safety').off(_.animation.end + '.utils');
4200
- deferred.resolve();
4201
- }, timeout)
4202
- };
4203
- $element.data('animation_safety', safety);
4204
 
4205
- $element.on(_.animation.end + '.utils', function(e){
4206
- if ($element.is(e.target)){
4207
- clearTimeout(safety.timer);
4208
- $element.removeData('animation_safety').off(_.animation.end + '.utils');
4209
- deferred.resolve();
4210
- }
4211
- });
4212
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4213
 
4214
- _.animation.requestFrame(function(){
4215
- if (_is.fn(classNameOrFunc)){
4216
- classNameOrFunc.apply($element.get(0), [$element]);
4217
- } else {
4218
- $element.toggleClass(classNameOrFunc, state);
4219
- }
4220
- if (!_.animation.supported){
4221
- // If the browser doesn't support animations then just resolve the deferred
4222
- deferred.resolve();
4223
- }
4224
- });
4225
 
4226
- return promise;
4227
- };
 
 
 
 
 
 
 
4228
 
4229
- })(
4230
- // dependencies
4231
- FooGallery.utils.$,
4232
- FooGallery.utils,
4233
- FooGallery.utils.is
4234
- );
4235
- (function($, _, _is, _animation){
4236
- // only register methods if this version is the current version
4237
- if (_.version !== '0.2.2') return;
4238
 
4239
- /**
4240
- * @summary Contains common utility methods and members for the CSS transition property.
4241
- * @memberof FooGallery.utils.
4242
- * @namespace transition
4243
- */
4244
- _.transition = {};
4245
 
4246
- // create a test element to check for the existence of the various transition properties
4247
- var testElement = document.createElement('div');
 
 
 
 
 
4248
 
4249
- /**
4250
- * @summary Whether or not transitions are supported by the current browser.
4251
- * @memberof FooGallery.utils.transition.
4252
- * @name supported
4253
- * @type {boolean}
4254
- */
4255
- _.transition.supported = (
4256
- /**
4257
- * @ignore
4258
- * @summary Performs a one time test to see if transitions are supported
4259
- * @param {HTMLElement} el - An element to test with.
4260
- * @returns {boolean} `true` if transitions are supported.
4261
- */
4262
- function(el){
4263
- var style = el.style;
4264
- return _is.string(style['transition'])
4265
- || _is.string(style['WebkitTransition'])
4266
- || _is.string(style['MozTransition'])
4267
- || _is.string(style['msTransition'])
4268
- || _is.string(style['OTransition']);
4269
- }
4270
- )(testElement);
4271
 
4272
- /**
4273
- * @summary The `transitionend` event name for the current browser.
4274
- * @memberof FooGallery.utils.transition.
4275
- * @name end
4276
- * @type {string}
4277
- * @description Depending on the browser this returns one of the following values:
4278
- *
4279
- * <ul><!--
4280
- * --><li>`"transitionend"`</li><!--
4281
- * --><li>`"webkitTransitionEnd"`</li><!--
4282
- * --><li>`"msTransitionEnd"`</li><!--
4283
- * --><li>`"oTransitionEnd"`</li><!--
4284
- * --><li>`null` - If the browser doesn't support transitions</li><!--
4285
- * --></ul>
4286
- */
4287
- _.transition.end = (
4288
- /**
4289
- * @ignore
4290
- * @summary Performs a one time test to determine which `transitionend` event to use for the current browser.
4291
- * @param {HTMLElement} el - An element to test with.
4292
- * @returns {?string} The correct `transitionend` event for the current browser, `null` if the browser doesn't support transitions.
4293
- */
4294
- function(el){
4295
- var style = el.style;
4296
- if (_is.string(style['transition'])) return 'transitionend';
4297
- if (_is.string(style['WebkitTransition'])) return 'webkitTransitionEnd';
4298
- if (_is.string(style['MozTransition'])) return 'transitionend';
4299
- if (_is.string(style['msTransition'])) return 'msTransitionEnd';
4300
- if (_is.string(style['OTransition'])) return 'oTransitionEnd';
4301
- return null;
4302
- }
4303
- )(testElement);
4304
 
4305
- /**
4306
- * @summary Gets the `transition-duration` value for the supplied jQuery element.
4307
- * @memberof FooGallery.utils.transition.
4308
- * @function duration
4309
- * @param {jQuery} $element - The jQuery element to retrieve the duration from.
4310
- * @param {number} [def=0] - The default value to return if no duration is set.
4311
- * @returns {number} The value of the `transition-duration` property converted to a millisecond value.
4312
- */
4313
- _.transition.duration = function($element, def){
4314
- def = _is.number(def) ? def : 0;
4315
- if (!_is.jq($element)) return def;
4316
- // we can use jQuery.css() method to retrieve the value cross browser
4317
- var duration = $element.css('transition-duration');
4318
- if (/^([\d.]*)+?(ms|s)/i.test(duration)){
4319
- // if we have a valid duration value split it into it's components
4320
- var parts = duration.split(","), max = 0;
4321
- parts.forEach(function(part){
4322
- var match = part.match(/^\s*?([\d.]*)+?(ms|s)\s*?$/i),
4323
- value = parseFloat(match[1]),
4324
- unit = match[2].toLowerCase();
4325
- if (unit === 's'){
4326
- // convert seconds to milliseconds
4327
- value = value * 1000;
4328
- }
4329
- if (value > max) max = value;
4330
- });
4331
- return max;
4332
- }
4333
- return def;
4334
- };
4335
 
4336
- /**
4337
- * @summary The callback function to execute when starting a transition.
4338
- * @callback FooGallery.utils.transition~startCallback
4339
- * @param {jQuery} $element - The element to start the transition on.
4340
- * @this Element
4341
- */
4342
 
4343
- /**
4344
- * @summary Start a transition by toggling the supplied `className` on the `$element`.
4345
- * @memberof FooGallery.utils.transition.
4346
- * @function start
4347
- * @param {jQuery} $element - The jQuery element to start the transition on.
4348
- * @param {(string|FooGallery.utils.transition~startCallback)} classNameOrFunc - One or more class names (separated by spaces) to be toggled or a function that performs the required actions to start the transition.
4349
- * @param {boolean} [state] - A Boolean (not just truthy/falsy) value to determine whether the class should be added or removed.
4350
- * @param {number} [timeout] - The maximum time, in milliseconds, to wait for the `transitionend` event to be raised. If not provided this will be automatically set to the elements `transition-duration` property plus an extra 50 milliseconds.
4351
- * @returns {Promise}
4352
- * @description This method lets us use CSS transitions by toggling a class and using the `transitionend` event to perform additional actions once the transition has completed across all browsers. In browsers that do not support transitions this method would behave the same as if just calling jQuery's `.toggleClass` method.
4353
- *
4354
- * The last parameter `timeout` is used to create a timer that behaves as a safety net in case the `transitionend` event is never raised and ensures the deferred returned by this method is resolved or rejected within a specified time.
4355
- * @see {@link https://developer.mozilla.org/en/docs/Web/CSS/transition-duration|transition-duration - CSS | MDN} for more information on the `transition-duration` CSS property.
4356
- */
4357
- _.transition.start = function($element, classNameOrFunc, state, timeout){
4358
- var deferred = $.Deferred(), promise = deferred.promise();
4359
-
4360
- $element = $element.first();
4361
-
4362
- if (_.transition.supported){
4363
- $element.prop('offsetTop');
4364
- var safety = $element.data('transition_safety');
4365
- if (_is.hash(safety) && _is.number(safety.timer)){
4366
- clearTimeout(safety.timer);
4367
- $element.removeData('transition_safety').off(_.transition.end + '.utils');
4368
- safety.deferred.reject();
4369
- }
4370
- timeout = _is.number(timeout) ? timeout : _.transition.duration($element) + 50;
4371
- safety = {
4372
- deferred: deferred,
4373
- timer: setTimeout(function(){
4374
- // This is the safety net in case a transition fails for some reason and the transitionend event is never raised.
4375
- // This will remove the bound event and resolve the deferred
4376
- $element.removeData('transition_safety').off(_.transition.end + '.utils');
4377
- deferred.resolve();
4378
- }, timeout)
4379
- };
4380
- $element.data('transition_safety', safety);
4381
 
4382
- $element.on(_.transition.end + '.utils', function(e){
4383
- if ($element.is(e.target)){
4384
- clearTimeout(safety.timer);
4385
- $element.removeData('transition_safety').off(_.transition.end + '.utils');
4386
- deferred.resolve();
4387
- }
4388
- });
4389
- }
4390
 
4391
- _animation.requestFrame(function() {
4392
- if (_is.fn(classNameOrFunc)){
4393
- classNameOrFunc.apply($element.get(0), [$element]);
4394
- } else {
4395
- $element.toggleClass(classNameOrFunc, state);
4396
- }
4397
- if (!_.transition.supported){
4398
- // If the browser doesn't support transitions then just resolve the deferred
4399
- deferred.resolve();
4400
- }
4401
- });
4402
 
4403
- return promise;
4404
- };
 
 
4405
 
4406
- })(
4407
- // dependencies
4408
- FooGallery.utils.$,
4409
- FooGallery.utils,
4410
- FooGallery.utils.is,
4411
- FooGallery.utils.animation
4412
- );
4413
- (function ($, _, _is, _obj, _fn) {
4414
- // only register methods if this version is the current version
4415
- if (_.version !== '0.2.2') return;
4416
 
4417
- /**
4418
- * @summary A base class providing some helper methods for prototypal inheritance.
4419
- * @memberof FooGallery.utils.
4420
- * @constructs Class
4421
- * @description This is a base class for making prototypal inheritance simpler to work with. It provides an easy way to inherit from another class and exposes a `_super` method within the scope of any overriding methods that allows a simple way to execute the overridden function.
4422
- *
4423
- * Have a look at the {@link FooGallery.utils.Class.extend|extend} and {@link FooGallery.utils.Class.override|override} method examples to see some basic usage.
4424
- * @example {@caption When using this base class the actual construction of a class is performed by the `construct` method.}
4425
- * var MyClass = FooGallery.utils.Class.extend({
4426
- * construct: function(arg1, arg2){
4427
- * // handle the construction logic here
4428
- * }
4429
- * });
4430
- *
4431
- * // use the class
4432
- * var myClass = new MyClass( "arg1:value", "arg2:value" );
4433
- */
4434
- _.Class = function(){};
4435
 
4436
- /**
4437
- * @ignore
4438
- * @summary The original function when within the scope of an overriding method.
4439
- * @memberof FooGallery.utils.Class#
4440
- * @function _super
4441
- * @param {...*} [argN] - The same arguments as the base method.
4442
- * @returns {*} The result of the base method.
4443
- * @description This is only available within the scope of an overriding method if it was created using the {@link FooGallery.utils.Class.extend|extend}, {@link FooGallery.utils.Class.override|override} or {@link FooGallery.utils.fn.addOrOverride} methods.
4444
- * @see {@link FooGallery.utils.fn.addOrOverride} to see an example of how this property is used.
4445
- */
4446
 
4447
- /**
4448
- * @summary Creates a new class that inherits from this one which in turn allows itself to be extended.
4449
- * @memberof FooGallery.utils.Class.
4450
- * @function extend
4451
- * @param {Object} [definition] - An object containing any methods to implement/override.
4452
- * @returns {function} A new class that inherits from the base class.
4453
- * @description Every class created using this method has both the {@link FooGallery.utils.Class.extend|extend} and {@link FooGallery.utils.Class.override|override} static methods added to it to allow it to be extended.
4454
- * @example {@caption The below shows an example of how to implement inheritance using this method.}{@run true}
4455
- * // create a base Person class
4456
- * var Person = FooGallery.utils.Class.extend({
4457
- * construct: function(isDancing){
4458
- * this.dancing = isDancing;
4459
- * },
4460
- * dance: function(){
4461
- * return this.dancing;
4462
- * }
4463
- * });
4464
- *
4465
- * var Ninja = Person.extend({
4466
- * construct: function(){
4467
- * // Call the inherited version of construct()
4468
- * this._super( false );
4469
- * },
4470
- * dance: function(){
4471
- * // Call the inherited version of dance()
4472
- * return this._super();
4473
- * },
4474
- * swingSword: function(){
4475
- * return true;
4476
- * }
4477
- * });
4478
- *
4479
- * var p = new Person(true);
4480
- * console.log( p.dance() ); // => true
4481
- *
4482
- * var n = new Ninja();
4483
- * console.log( n.dance() ); // => false
4484
- * console.log( n.swingSword() ); // => true
4485
- * console.log(
4486
- * p instanceof Person && p.constructor === Person && p instanceof FooGallery.utils.Class
4487
- * && n instanceof Ninja && n.constructor === Ninja && n instanceof Person && n instanceof FooGallery.utils.Class
4488
- * ); // => true
4489
- */
4490
- _.Class.extend = function(definition){
4491
- definition = _is.hash(definition) ? definition : {};
4492
- var proto = _obj.create(this.prototype); // create a new prototype to work with so we don't modify the original
4493
- // iterate over all properties in the supplied definition and update the prototype
4494
- for (var name in definition) {
4495
- if (!definition.hasOwnProperty(name)) continue;
4496
- _fn.addOrOverride(proto, name, definition[name]);
4497
- }
4498
- // if no construct method is defined add a default one that does nothing
4499
- proto.construct = _is.fn(proto.construct) ? proto.construct : function(){};
4500
-
4501
- // create the new class using the prototype made above
4502
- function Class() {
4503
- if (!_is.fn(this.construct))
4504
- throw new SyntaxError('FooGallery.utils.Class objects must be constructed with the "new" keyword.');
4505
- this.construct.apply(this, arguments);
4506
- }
4507
- Class.prototype = proto;
4508
- //noinspection JSUnresolvedVariable
4509
- Class.prototype.constructor = _is.fn(proto.__ctor__) ? proto.__ctor__ : Class;
4510
- Class.extend = _.Class.extend;
4511
- Class.override = _.Class.override;
4512
- Class.bases = _.Class.bases;
4513
- Class.__base__ = this;
4514
- return Class;
4515
- };
4516
-
4517
- /**
4518
- * @summary Overrides a single method on this class.
4519
- * @memberof FooGallery.utils.Class.
4520
- * @function override
4521
- * @param {string} name - The name of the function to override.
4522
- * @param {function} fn - The new function to override with, the `_super` method will be made available within this function.
4523
- * @description This is a helper method for overriding a single function of a {@link FooGallery.utils.Class} or one of its child classes. This uses the {@link FooGallery.utils.fn.addOrOverride} method internally and simply provides the correct prototype.
4524
- * @example {@caption The below example wraps the `Person.prototype.dance` method with a new one that inverts the result. Note the override applies even to instances of the class that are already created.}{@run true}
4525
- * var Person = FooGallery.utils.Class.extend({
4526
- * construct: function(isDancing){
4527
- * this.dancing = isDancing;
4528
- * },
4529
- * dance: function(){
4530
- * return this.dancing;
4531
- * }
4532
- * });
4533
- *
4534
- * var p = new Person(true);
4535
- * console.log( p.dance() ); // => true
4536
- *
4537
- * Person.override("dance", function(){
4538
- * // Call the original version of dance()
4539
- * return !this._super();
4540
- * });
4541
- *
4542
- * console.log( p.dance() ); // => false
4543
- */
4544
- _.Class.override = function(name, fn){
4545
- _fn.addOrOverride(this.prototype, name, fn);
4546
- };
4547
-
4548
- /**
4549
- * @summary The base class for this class.
4550
- * @memberof FooGallery.utils.Class.
4551
- * @name __base__
4552
- * @type {?FooGallery.utils.Class}
4553
- * @private
4554
- */
4555
- _.Class.__base__ = null;
4556
-
4557
- /**
4558
- * @summary Get an array of all base classes for this class.
4559
- * @memberof FooGallery.utils.Class.
4560
- * @function bases
4561
- * @returns {FooGallery.utils.Class[]}
4562
- */
4563
- _.Class.bases = function(){
4564
- function _get(klass, result){
4565
- if (!_is.array(result)) result = [];
4566
- if (_is.fn(klass) && klass.__base__ !== null){
4567
- result.unshift(klass.__base__);
4568
- return _get(klass.__base__, result);
4569
- }
4570
- return result;
4571
- }
4572
- var initial = [];
4573
- return _get(this, initial);
4574
- };
4575
- })(
4576
- // dependencies
4577
- FooGallery.utils.$,
4578
- FooGallery.utils,
4579
- FooGallery.utils.is,
4580
- FooGallery.utils.obj,
4581
- FooGallery.utils.fn
4582
- );
4583
- (function (_, _is, _str) {
4584
- // only register methods if this version is the current version
4585
- if (_.version !== '0.2.2') return;
4586
-
4587
- /**
4588
- * @summary A base event class providing just a type and defaultPrevented properties.
4589
- * @memberof FooGallery.utils.
4590
- * @class Event
4591
- * @param {string} type - The type for this event.
4592
- * @augments FooGallery.utils.Class
4593
- * @borrows FooGallery.utils.Class.extend as extend
4594
- * @borrows FooGallery.utils.Class.override as override
4595
- * @description This is a very basic event class that is used internally by the {@link FooGallery.utils.EventClass#trigger} method when the first parameter supplied is simply the event name.
4596
- *
4597
- * To trigger your own custom event you will need to inherit from this class and then supply the instantiated event object as the first parameter to the {@link FooGallery.utils.EventClass#trigger} method.
4598
- * @example {@caption The following shows how to use this class to create a custom event.}
4599
- * var MyEvent = FooGallery.utils.Event.extend({
4600
- * construct: function(type, customProp){
4601
- * this._super(type);
4602
- * this.myCustomProp = customProp;
4603
- * }
4604
- * });
4605
- *
4606
- * // to use the class you would then instantiate it and pass it as the first argument to a FooGallery.utils.EventClass's trigger method
4607
- * var eventClass = ...; // any class inheriting from FooGallery.utils.EventClass
4608
- * var event = new MyEvent( "my-event-type", true );
4609
- * eventClass.trigger(event);
4610
- */
4611
- _.Event = _.Class.extend(/** @lends FooGallery.utils.Event.prototype */{
4612
- /**
4613
- * @ignore
4614
- * @constructs
4615
- * @param {string} type
4616
- **/
4617
- construct: function(type){
4618
- if (_is.empty(type))
4619
- throw new SyntaxError('FooGallery.utils.Event objects must be supplied a `type`.');
4620
-
4621
- var self = this, parsed = _.Event.parse(type);
4622
- /**
4623
- * @summary The type of event.
4624
- * @memberof FooGallery.utils.Event#
4625
- * @name type
4626
- * @type {string}
4627
- * @readonly
4628
- */
4629
- self.type = parsed.type;
4630
- /**
4631
- * @summary The namespace of the event.
4632
- * @memberof FooGallery.utils.Event#
4633
- * @name namespace
4634
- * @type {string}
4635
- * @readonly
4636
- */
4637
- self.namespace = parsed.namespace;
4638
- /**
4639
- * @summary Whether the default action should be taken or not.
4640
- * @memberof FooGallery.utils.Event#
4641
- * @name defaultPrevented
4642
- * @type {boolean}
4643
- * @readonly
4644
- */
4645
- self.defaultPrevented = false;
4646
- /**
4647
- * @summary The original {@link FooGallery.utils.EventClass} that triggered this event.
4648
- * @memberof FooGallery.utils.Event#
4649
- * @name target
4650
- * @type {FooGallery.utils.EventClass}
4651
- */
4652
- self.target = null;
4653
- },
4654
- /**
4655
- * @summary Informs the class that raised this event that its default action should not be taken.
4656
- * @memberof FooGallery.utils.Event#
4657
- * @function preventDefault
4658
- */
4659
- preventDefault: function(){
4660
- this.defaultPrevented = true;
4661
- },
4662
- /**
4663
- * @summary Gets whether the default action should be taken or not.
4664
- * @memberof FooGallery.utils.Event#
4665
- * @function isDefaultPrevented
4666
- * @returns {boolean}
4667
- */
4668
- isDefaultPrevented: function(){
4669
- return this.defaultPrevented;
4670
- }
4671
- });
4672
-
4673
- /**
4674
- * @summary Parse the provided event string into a type and namespace.
4675
- * @memberof FooGallery.utils.Event.
4676
- * @function parse
4677
- * @param {string} event - The event to parse.
4678
- * @returns {{namespaced: boolean, type: string, namespace: string}} Returns an object containing the type and namespace for the event.
4679
- */
4680
- _.Event.parse = function(event){
4681
- event = _is.string(event) && !_is.empty(event) ? event : null;
4682
- var namespaced = _str.contains(event, ".");
4683
- return {
4684
- namespaced: namespaced,
4685
- type: namespaced ? _str.startsWith(event, ".") ? null : _str.until(event, ".") : event,
4686
- namespace: namespaced ? _str.from(event, ".") : null
4687
- };
4688
- };
4689
-
4690
- /**
4691
- * @summary A base class that implements a basic events interface.
4692
- * @memberof FooGallery.utils.
4693
- * @class EventClass
4694
- * @augments FooGallery.utils.Class
4695
- * @borrows FooGallery.utils.Class.extend as extend
4696
- * @borrows FooGallery.utils.Class.override as override
4697
- * @description This is a very basic events implementation that provides just enough to cover most needs.
4698
- */
4699
- _.EventClass = _.Class.extend(/** @lends FooGallery.utils.EventClass.prototype */{
4700
- /**
4701
- * @ignore
4702
- * @constructs
4703
- **/
4704
- construct: function(){
4705
- /**
4706
- * @summary An object containing all the required info to execute a listener.
4707
- * @typedef {Object} FooGallery.utils.EventClass~RegisteredListener
4708
- * @property {string} namespace - The namespace for the listener.
4709
- * @property {function} fn - The callback function for the listener.
4710
- * @property {*} thisArg - The `this` value to execute the callback with.
4711
- */
4712
-
4713
- /**
4714
- * @summary An object containing a mapping of events to listeners.
4715
- * @typedef {Object.<string, Array<FooGallery.utils.EventClass~RegisteredListener>>} FooGallery.utils.EventClass~RegisteredEvents
4716
- */
4717
-
4718
- /**
4719
- * @summary The object used to register event handlers.
4720
- * @memberof FooGallery.utils.EventClass#
4721
- * @name events
4722
- * @type {FooGallery.utils.EventClass~RegisteredEvents}
4723
- */
4724
- this.events = {};
4725
- },
4726
- /**
4727
- * @summary Destroy the current instance releasing used resources.
4728
- * @memberof FooGallery.utils.EventClass#
4729
- * @function destroy
4730
- */
4731
- destroy: function(){
4732
- this.events = {};
4733
- },
4734
- /**
4735
- * @summary Attach multiple event listeners to the class.
4736
- * @memberof FooGallery.utils.EventClass#
4737
- * @function on
4738
- * @param {Object.<string, function>} events - An object containing event types to listener mappings.
4739
- * @param {*} [thisArg] - The value of `this` within the listeners. Defaults to the class raising the event.
4740
- * @returns {this}
4741
- *//**
4742
- * @summary Attach an event listener for one or more events to the class.
4743
- * @memberof FooGallery.utils.EventClass#
4744
- * @function on
4745
- * @param {string} events - One or more space-separated event types.
4746
- * @param {function} listener - A function to execute when the event is triggered.
4747
- * @param {*} [thisArg] - The value of `this` within the `listener`. Defaults to the class raising the event.
4748
- * @returns {this}
4749
- */
4750
- on: function(events, listener, thisArg){
4751
- var self = this;
4752
- if (_is.object(events)){
4753
- thisArg = listener;
4754
- Object.keys(events).forEach(function(key){
4755
- if (_is.fn(events[key])){
4756
- key.split(" ").forEach(function(type){
4757
- self.addListener(type, events[key], thisArg);
4758
- });
4759
- }
4760
- });
4761
- } else if (_is.string(events) && _is.fn(listener)) {
4762
- events.split(" ").forEach(function(type){
4763
- self.addListener(type, listener, thisArg);
4764
- });
4765
- }
4766
-
4767
- return self;
4768
- },
4769
- /**
4770
- * @summary Adds a single event listener to the current class.
4771
- * @memberof FooGallery.utils.EventClass#
4772
- * @function addListener
4773
- * @param {string} event - The event type, this can not contain any whitespace.
4774
- * @param {function} listener - A function to execute when the event is triggered.
4775
- * @param {*} [thisArg] - The value of `this` within the `listener`. Defaults to the class raising the event.
4776
- * @returns {boolean} Returns `true` if added.
4777
- */
4778
- addListener: function(event, listener, thisArg){
4779
- if (!_is.string(event) || /\s/.test(event) || !_is.fn(listener)) return false;
4780
-
4781
- var self = this, parsed = _.Event.parse(event);
4782
- thisArg = _is.undef(thisArg) ? self : thisArg;
4783
-
4784
- if (!_is.array(self.events[parsed.type])){
4785
- self.events[parsed.type] = [];
4786
- }
4787
- var exists = self.events[parsed.type].some(function(h){
4788
- return h.namespace === parsed.namespace && h.fn === listener && h.thisArg === thisArg;
4789
- });
4790
- if (!exists){
4791
- self.events[parsed.type].push({
4792
- namespace: parsed.namespace,
4793
- fn: listener,
4794
- thisArg: thisArg
4795
- });
4796
- return true;
4797
- }
4798
- return false;
4799
- },
4800
- /**
4801
- * @summary Remove multiple event listeners from the class.
4802
- * @memberof FooGallery.utils.EventClass#
4803
- * @function off
4804
- * @param {Object.<string, function>} events - An object containing event types to listener mappings.
4805
- * @param {*} [thisArg] - The value of `this` within the `listener` function. Defaults to the class raising the event.
4806
- * @returns {this}
4807
- *//**
4808
- * @summary Remove an event listener from the class.
4809
- * @memberof FooGallery.utils.EventClass#
4810
- * @function off
4811
- * @param {string} events - One or more space-separated event types.
4812
- * @param {function} listener - A function to execute when the event is triggered.
4813
- * @param {*} [thisArg] - The value of `this` within the `listener`. Defaults to the class raising the event.
4814
- * @returns {this}
4815
- */
4816
- off: function(events, listener, thisArg){
4817
- var self = this;
4818
- if (_is.object(events)){
4819
- thisArg = listener;
4820
- Object.keys(events).forEach(function(key){
4821
- key.split(" ").forEach(function(type){
4822
- self.removeListener(type, events[key], thisArg);
4823
- });
4824
- });
4825
- } else if (_is.string(events)) {
4826
- events.split(" ").forEach(function(type){
4827
- self.removeListener(type, listener, thisArg);
4828
- });
4829
- }
4830
-
4831
- return self;
4832
- },
4833
- /**
4834
- * @summary Removes a single event listener from the current class.
4835
- * @memberof FooGallery.utils.EventClass#
4836
- * @function removeListener
4837
- * @param {string} event - The event type, this can not contain any whitespace.
4838
- * @param {function} [listener] - The listener registered to the event type.
4839
- * @param {*} [thisArg] - The value of `this` registered for the `listener`. Defaults to the class raising the event.
4840
- * @returns {boolean} Returns `true` if removed.
4841
- */
4842
- removeListener: function(event, listener, thisArg){
4843
- if (!_is.string(event) || /\s/.test(event)) return false;
4844
-
4845
- var self = this, parsed = _.Event.parse(event), types = [];
4846
- thisArg = _is.undef(thisArg) ? self : thisArg;
4847
-
4848
- if (!_is.empty(parsed.type)){
4849
- types.push(parsed.type);
4850
- } else if (!_is.empty(parsed.namespace)){
4851
- types.push.apply(types, Object.keys(self.events));
4852
- }
4853
-
4854
- types.forEach(function(type){
4855
- if (!_is.array(self.events[type])) return;
4856
- self.events[type] = self.events[type].filter(function (h) {
4857
- if (listener != null){
4858
- return !(h.namespace === parsed.namespace && h.fn === listener && h.thisArg === thisArg);
4859
- }
4860
- if (parsed.namespace != null){
4861
- return h.namespace !== parsed.namespace;
4862
- }
4863
- return false;
4864
- });
4865
- if (self.events[type].length === 0){
4866
- delete self.events[type];
4867
- }
4868
- });
4869
- return true;
4870
- },
4871
- /**
4872
- * @summary Trigger an event on the current class.
4873
- * @memberof FooGallery.utils.EventClass#
4874
- * @function trigger
4875
- * @param {(string|FooGallery.utils.Event)} event - Either a space-separated string of event types or a custom event object to raise.
4876
- * @param {Array} [args] - An array of additional arguments to supply to the listeners after the event object.
4877
- * @returns {(FooGallery.utils.Event|FooGallery.utils.Event[]|null)} Returns the {@link FooGallery.utils.Event|event object} of the triggered event. If more than one event was triggered an array of {@link FooGallery.utils.Event|event objects} is returned. If no `event` was supplied or triggered `null` is returned.
4878
- */
4879
- trigger: function(event, args){
4880
- args = _is.array(args) ? args : [];
4881
- var self = this, result = [];
4882
- if (event instanceof _.Event){
4883
- result.push(event);
4884
- self.emit(event, args);
4885
- } else if (_is.string(event)) {
4886
- event.split(" ").forEach(function(type){
4887
- var e = new _.Event(type);
4888
- result.push(e)
4889
- self.emit(e, args);
4890
- });
4891
- }
4892
- return _is.empty(result) ? null : (result.length === 1 ? result[0] : result);
4893
- },
4894
- /**
4895
- * @summary Emits the supplied event on the current class.
4896
- * @memberof FooGallery.utils.EventClass#
4897
- * @function emit
4898
- * @param {FooGallery.utils.Event} event - The event object to emit.
4899
- * @param {Array} [args] - An array of additional arguments to supply to the listener after the event object.
4900
- */
4901
- emit: function(event, args){
4902
- if (!(event instanceof FooGallery.utils.Event)) return;
4903
- var self = this;
4904
- args = _is.array(args) ? args : [];
4905
- if (event.target === null) event.target = self;
4906
- if (_is.array(self.events[event.type])) {
4907
- self.events[event.type].forEach(function (h) {
4908
- if (event.namespace != null && h.namespace !== event.namespace) return;
4909
- h.fn.apply(h.thisArg, [event].concat(args));
4910
- });
4911
- }
4912
- if (_is.array(self.events["__all__"])){
4913
- self.events["__all__"].forEach(function (h) {
4914
- h.fn.apply(h.thisArg, [event].concat(args));
4915
- });
4916
- }
4917
- }
4918
- });
4919
-
4920
- })(
4921
- // dependencies
4922
- FooGallery.utils,
4923
- FooGallery.utils.is,
4924
- FooGallery.utils.str
4925
- );
4926
- (function($, _, _is){
4927
- // only register methods if this version is the current version
4928
- if (_.version !== '0.2.2') return;
4929
-
4930
- /**
4931
- * @summary A simple bounding rectangle class.
4932
- * @memberof FooGallery.utils.
4933
- * @class Bounds
4934
- * @augments FooGallery.utils.Class
4935
- * @borrows FooGallery.utils.Class.extend as extend
4936
- * @borrows FooGallery.utils.Class.override as override
4937
- */
4938
- _.Bounds = _.Class.extend(/** @lends FooGallery.utils.Bounds.prototype */{
4939
- /**
4940
- * @ignore
4941
- * @constructs
4942
- **/
4943
- construct: function(){
4944
- var self = this;
4945
- /**
4946
- * @summary The top position.
4947
- * @memberof FooGallery.utils.Bounds#
4948
- * @name top
4949
- * @type {number}
4950
- */
4951
- self.top = 0;
4952
- /**
4953
- * @summary The right position.
4954
- * @memberof FooGallery.utils.Bounds#
4955
- * @name right
4956
- * @type {number}
4957
- */
4958
- self.right = 0;
4959
- /**
4960
- * @summary The bottom position.
4961
- * @memberof FooGallery.utils.Bounds#
4962
- * @name bottom
4963
- * @type {number}
4964
- */
4965
- self.bottom = 0;
4966
- /**
4967
- * @summary The left position.
4968
- * @memberof FooGallery.utils.Bounds#
4969
- * @name left
4970
- * @type {number}
4971
- */
4972
- self.left = 0;
4973
- /**
4974
- * @summary The width of the rectangle described by the position properties.
4975
- * @memberof FooGallery.utils.Bounds#
4976
- * @name width
4977
- * @type {number}
4978
- */
4979
- self.width = 0;
4980
- /**
4981
- * @summary The height of the rectangle described by the position properties.
4982
- * @memberof FooGallery.utils.Bounds#
4983
- * @name height
4984
- * @type {number}
4985
- */
4986
- self.height = 0;
4987
- },
4988
- /**
4989
- * @summary Inflate the bounds by the specified amount.
4990
- * @memberof FooGallery.utils.Bounds#
4991
- * @function inflate
4992
- * @param {number} amount - A positive number will expand the bounds while a negative one will shrink it.
4993
- * @returns {FooGallery.utils.Bounds}
4994
- */
4995
- inflate: function(amount){
4996
- var self = this;
4997
- if (_is.number(amount)){
4998
- self.top -= amount;
4999
- self.right += amount;
5000
- self.bottom += amount;
5001
- self.left -= amount;
5002
- self.width += amount * 2;
5003
- self.height += amount * 2;
5004
- }
5005
- return self;
5006
- },
5007
- /**
5008
- * @summary Checks if the supplied bounds object intersects with this one.
5009
- * @memberof FooGallery.utils.Bounds#
5010
- * @function intersects
5011
- * @param {FooGallery.utils.Bounds} bounds - The bounds to check.
5012
- * @returns {boolean}
5013
- */
5014
- intersects: function(bounds){
5015
- var self = this;
5016
- return self.left <= bounds.right && bounds.left <= self.right && self.top <= bounds.bottom && bounds.top <= self.bottom;
5017
- }
5018
- });
5019
-
5020
- var __$window;
5021
- /**
5022
- * @summary Gets the bounding rectangle of the current viewport.
5023
- * @memberof FooGallery.utils.
5024
- * @function getViewportBounds
5025
- * @param {number} [inflate] - An amount to inflate the bounds by. A positive number will expand the bounds outside of the visible viewport while a negative one would shrink it.
5026
- * @returns {FooGallery.utils.Bounds}
5027
- */
5028
- _.getViewportBounds = function(inflate){
5029
- if (!__$window) __$window = $(window);
5030
- var bounds = new _.Bounds();
5031
- bounds.top = __$window.scrollTop();
5032
- bounds.left = __$window.scrollLeft();
5033
- bounds.width = __$window.width();
5034
- bounds.height = __$window.height();
5035
- bounds.right = bounds.left + bounds.width;
5036
- bounds.bottom = bounds.top + bounds.height;
5037
- bounds.inflate(inflate);
5038
- return bounds;
5039
- };
5040
-
5041
- /**
5042
- * @summary Get the bounding rectangle for the supplied element.
5043
- * @memberof FooGallery.utils.
5044
- * @function getElementBounds
5045
- * @param {(jQuery|HTMLElement|string)} element - The jQuery wrapper around the element, the element itself, or a CSS selector to retrieve the element with.
5046
- * @returns {FooGallery.utils.Bounds}
5047
- */
5048
- _.getElementBounds = function(element){
5049
- if (!_is.jq(element)) element = $(element);
5050
- var bounds = new _.Bounds();
5051
- if (element.length !== 0){
5052
- var offset = element.offset();
5053
- bounds.top = offset.top;
5054
- bounds.left = offset.left;
5055
- bounds.width = element.width();
5056
- bounds.height = element.height();
5057
- }
5058
- bounds.right = bounds.left + bounds.width;
5059
- bounds.bottom = bounds.top + bounds.height;
5060
- return bounds;
5061
- };
5062
-
5063
- })(
5064
- FooGallery.utils.$,
5065
- FooGallery.utils,
5066
- FooGallery.utils.is
5067
- );
5068
- (function($, _, _is, _fn, _obj){
5069
- // only register methods if this version is the current version
5070
- if (_.version !== '0.2.2') return;
5071
-
5072
- /**
5073
- * @summary A simple timer that triggers events.
5074
- * @memberof FooGallery.utils.
5075
- * @class Timer
5076
- * @param {number} [interval=1000] - The internal tick interval of the timer.
5077
- */
5078
- _.Timer = _.EventClass.extend(/** @lends FooGallery.utils.Timer */{
5079
- /**
5080
- * @ignore
5081
- * @constructs
5082
- * @param {number} [interval=1000]
5083
- */
5084
- construct: function(interval){
5085
- this._super();
5086
- /**
5087
- * @summary The internal tick interval of the timer in milliseconds.
5088
- * @memberof FooGallery.utils.Timer#
5089
- * @name interval
5090
- * @type {number}
5091
- * @default 1000
5092
- * @readonly
5093
- */
5094
- this.interval = _is.number(interval) ? interval : 1000;
5095
- /**
5096
- * @summary Whether the timer is currently running or not.
5097
- * @memberof FooGallery.utils.Timer#
5098
- * @name isRunning
5099
- * @type {boolean}
5100
- * @default false
5101
- * @readonly
5102
- */
5103
- this.isRunning = false;
5104
- /**
5105
- * @summary Whether the timer is currently paused or not.
5106
- * @memberof FooGallery.utils.Timer#
5107
- * @name isPaused
5108
- * @type {boolean}
5109
- * @default false
5110
- * @readonly
5111
- */
5112
- this.isPaused = false;
5113
- /**
5114
- * @summary Whether the timer can resume from a previous state or not.
5115
- * @memberof FooGallery.utils.Timer#
5116
- * @name canResume
5117
- * @type {boolean}
5118
- * @default false
5119
- * @readonly
5120
- */
5121
- this.canResume = false;
5122
- /**
5123
- * @summary Whether the timer can restart or not.
5124
- * @memberof FooGallery.utils.Timer#
5125
- * @name canRestart
5126
- * @type {boolean}
5127
- * @default false
5128
- * @readonly
5129
- */
5130
- this.canRestart = false;
5131
- /**
5132
- * @summary The internal tick timeout ID.
5133
- * @memberof FooGallery.utils.Timer#
5134
- * @name __timeout
5135
- * @type {?number}
5136
- * @default null
5137
- * @private
5138
- */
5139
- this.__timeout = null;
5140
- /**
5141
- * @summary Whether the timer is incrementing or decrementing.
5142
- * @memberof FooGallery.utils.Timer#
5143
- * @name __decrement
5144
- * @type {boolean}
5145
- * @default false
5146
- * @private
5147
- */
5148
- this.__decrement = false;
5149
- /**
5150
- * @summary The total time for the timer.
5151
- * @memberof FooGallery.utils.Timer#
5152
- * @name __time
5153
- * @type {number}
5154
- * @default 0
5155
- * @private
5156
- */
5157
- this.__time = 0;
5158
- /**
5159
- * @summary The remaining time for the timer.
5160
- * @memberof FooGallery.utils.Timer#
5161
- * @name __remaining
5162
- * @type {number}
5163
- * @default 0
5164
- * @private
5165
- */
5166
- this.__remaining = 0;
5167
- /**
5168
- * @summary The current time for the timer.
5169
- * @memberof FooGallery.utils.Timer#
5170
- * @name __current
5171
- * @type {number}
5172
- * @default 0
5173
- * @private
5174
- */
5175
- this.__current = 0;
5176
- /**
5177
- * @summary The final time for the timer.
5178
- * @memberof FooGallery.utils.Timer#
5179
- * @name __finish
5180
- * @type {number}
5181
- * @default 0
5182
- * @private
5183
- */
5184
- this.__finish = 0;
5185
- /**
5186
- * @summary The last arguments supplied to the {@link FooGallery.utils.Timer#start|start} method.
5187
- * @memberof FooGallery.utils.Timer#
5188
- * @name __restart
5189
- * @type {Array}
5190
- * @default []
5191
- * @private
5192
- */
5193
- this.__restart = [];
5194
- },
5195
- /**
5196
- * @summary Resets the timer back to a fresh starting state.
5197
- * @memberof FooGallery.utils.Timer#
5198
- * @function __reset
5199
- * @private
5200
- */
5201
- __reset: function(){
5202
- clearTimeout(this.__timeout);
5203
- this.__timeout = null;
5204
- this.__decrement = false;
5205
- this.__time = 0;
5206
- this.__remaining = 0;
5207
- this.__current = 0;
5208
- this.__finish = 0;
5209
- this.isRunning = false;
5210
- this.isPaused = false;
5211
- this.canResume = false;
5212
- },
5213
- /**
5214
- * @summary Generates event args to be passed to listeners of the timer events.
5215
- * @memberof FooGallery.utils.Timer#
5216
- * @function __eventArgs
5217
- * @param {...*} [args] - Any number of additional arguments to pass to an event listener.
5218
- * @return {Array} - The first 3 values of the result will always be the current time, the total time and boolean indicating if the timer is decremental.
5219
- * @private
5220
- */
5221
- __eventArgs: function(args){
5222
- return [
5223
- this.__current,
5224
- this.__time,
5225
- this.__decrement
5226
- ].concat(_fn.arg2arr(arguments));
5227
- },
5228
- /**
5229
- * @summary Performs the tick for the timer checking and modifying the various internal states.
5230
- * @memberof FooGallery.utils.Timer#
5231
- * @function __tick
5232
- * @private
5233
- */
5234
- __tick: function(){
5235
- var self = this;
5236
- self.trigger("tick", self.__eventArgs());
5237
- if (self.__current === self.__finish){
5238
- self.trigger("complete", self.__eventArgs());
5239
- self.__reset();
5240
- } else {
5241
- if (self.__decrement){
5242
- self.__current--;
5243
- } else {
5244
- self.__current++;
5245
- }
5246
- self.__remaining--;
5247
- self.canResume = self.__remaining > 0;
5248
- self.__timeout = setTimeout(function () {
5249
- self.__tick();
5250
- }, self.interval);
5251
- }
5252
- },
5253
- /**
5254
- * @summary Starts the timer using the supplied `time` and whether or not to increment or decrement from the value.
5255
- * @memberof FooGallery.utils.Timer#
5256
- * @function start
5257
- * @param {number} time - The total time in seconds for the timer.
5258
- * @param {boolean} [decrement=false] - Whether the timer should increment or decrement from or to the supplied time.
5259
- */
5260
- start: function(time, decrement){
5261
- var self = this;
5262
- if (self.isRunning) return;
5263
- decrement = _is.boolean(decrement) ? decrement : false;
5264
- self.__restart = [time, decrement];
5265
- self.__decrement = decrement;
5266
- self.__time = time;
5267
- self.__remaining = time;
5268
- self.__current = decrement ? time : 0;
5269
- self.__finish = decrement ? 0 : time;
5270
- self.canRestart = true;
5271
- self.isRunning = true;
5272
- self.isPaused = false;
5273
- self.trigger("start", self.__eventArgs());
5274
- self.__tick();
5275
- },
5276
- /**
5277
- * @summary Starts the timer counting down to `0` from the supplied `time`.
5278
- * @memberof FooGallery.utils.Timer#
5279
- * @function countdown
5280
- * @param {number} time - The total time in seconds for the timer.
5281
- */
5282
- countdown: function(time){
5283
- this.start(time, true);
5284
- },
5285
- /**
5286
- * @summary Starts the timer counting up from `0` to the supplied `time`.
5287
- * @memberof FooGallery.utils.Timer#
5288
- * @function countup
5289
- * @param {number} time - The total time in seconds for the timer.
5290
- */
5291
- countup: function(time){
5292
- this.start(time, false);
5293
- },
5294
- /**
5295
- * @summary Stops and then restarts the timer using the last arguments supplied to the {@link FooGallery.utils.Timer#start|start} method.
5296
- * @memberof FooGallery.utils.Timer#
5297
- * @function restart
5298
- */
5299
- restart: function(){
5300
- this.stop();
5301
- if (this.canRestart){
5302
- this.start.apply(this, this.__restart);
5303
- }
5304
- },
5305
- /**
5306
- * @summary Stops the timer.
5307
- * @memberof FooGallery.utils.Timer#
5308
- * @function stop
5309
- */
5310
- stop: function(){
5311
- if (this.isRunning || this.isPaused){
5312
- this.__reset();
5313
- this.trigger("stop", this.__eventArgs());
5314
- }
5315
  },
5316
- /**
5317
- * @summary Pauses the timer and returns the remaining seconds.
5318
- * @memberof FooGallery.utils.Timer#
5319
- * @function pause
5320
- * @return {number} - The number of seconds remaining for the timer.
5321
- */
5322
- pause: function(){
5323
- var self = this;
5324
- if (self.__timeout != null){
5325
- clearTimeout(self.__timeout);
5326
- self.__timeout = null;
5327
- }
5328
- if (self.isRunning){
5329
- self.isRunning = false;
5330
- self.isPaused = true;
5331
- self.trigger("pause", self.__eventArgs());
5332
- }
5333
- return self.__remaining;
5334
  },
5335
- /**
5336
- * @summary Resumes the timer from a previously paused state.
5337
- * @memberof FooGallery.utils.Timer#
5338
- * @function resume
5339
- */
5340
- resume: function(){
5341
- var self = this;
5342
- if (self.canResume){
5343
- self.isRunning = true;
5344
- self.isPaused = false;
5345
- self.trigger("resume", self.__eventArgs());
5346
- self.__tick();
5347
- }
5348
  },
5349
- /**
5350
- * @summary Resets the timer back to a fresh starting state.
5351
- * @memberof FooGallery.utils.Timer#
5352
- * @function reset
5353
- */
5354
- reset: function(){
5355
- this.__reset();
5356
- this.trigger("reset", this.__eventArgs());
 
5357
  }
5358
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5359
 
5360
- })(
5361
- FooGallery.utils.$,
5362
- FooGallery.utils,
5363
- FooGallery.utils.is,
5364
- FooGallery.utils.fn,
5365
- FooGallery.utils.obj
5366
- );
 
5367
 
5368
- (function($, _, _is, _fn){
5369
- // only register methods if this version is the current version
5370
- if (_.version !== '0.2.2') return;
5371
 
5372
- /**
5373
- * @summary A factory for classes allowing them to be registered and created using a friendly name.
5374
- * @memberof FooGallery.utils.
5375
- * @class Factory
5376
- * @description This class allows other classes to register themselves for use at a later time. Depending on how you intend to use the registered classes you can also specify a load and execution order through the `priority` parameter of the {@link FooGallery.utils.Factory#register|register} method.
5377
- * @augments FooGallery.utils.Class
5378
- * @borrows FooGallery.utils.Class.extend as extend
5379
- * @borrows FooGallery.utils.Class.override as override
5380
- */
5381
- _.Factory = _.Class.extend(/** @lends FooGallery.utils.Factory.prototype */{
5382
- /**
5383
- * @ignore
5384
- * @constructs
5385
- **/
5386
- construct: function(){
5387
- /**
5388
- * @summary An object containing all the required info to create a new instance of a registered class.
5389
- * @typedef {Object} FooGallery.utils.Factory~RegisteredClass
5390
- * @property {string} name - The friendly name of the registered class.
5391
- * @property {function} klass - The constructor for the registered class.
5392
- * @property {number} priority - The priority for the registered class.
5393
- */
5394
 
5395
- /**
5396
- * @summary An object containing all registered classes.
5397
- * @memberof FooGallery.utils.Factory#
5398
- * @name registered
5399
- * @type {Object.<string, FooGallery.utils.Factory~RegisteredClass>}
5400
- * @readonly
5401
- * @example {@caption The following shows the structure of this object. The `<name>` placeholders would be the name the class was registered with.}
5402
- * {
5403
- * "<name>": {
5404
- * "name": <string>,
5405
- * "klass": <function>,
5406
- * "priority": <number>
5407
- * },
5408
- * "<name>": {
5409
- * "name": <string>,
5410
- * "klass": <function>,
5411
- * "priority": <number>
5412
- * },
5413
- * ...
5414
- * }
5415
- */
5416
- this.registered = {};
5417
- },
5418
- /**
5419
- * @summary Checks if the factory contains a class registered using the supplied `name`.
5420
- * @memberof FooGallery.utils.Factory#
5421
- * @function contains
5422
- * @param {string} name - The name of the class to check.
5423
- * @returns {boolean}
5424
- * @example {@run true}
5425
- * // create a new instance of the factory, this is usually exposed by the class that will be using the factory.
5426
- * var factory = new FooGallery.utils.Factory();
5427
- *
5428
- * // create a class to register
5429
- * function Test(){}
5430
- *
5431
- * // register the class with the factory with the default priority
5432
- * factory.register( "test", Test );
5433
- *
5434
- * // test if the class was registered
5435
- * console.log( factory.contains( "test" ) ); // => true
5436
- */
5437
- contains: function(name){
5438
- return !_is.undef(this.registered[name]);
5439
- },
5440
- /**
5441
- * @summary Creates new instances of all registered classes using there registered priority and the supplied arguments.
5442
- * @memberof FooGallery.utils.Factory#
5443
- * @function load
5444
- * @param {Object.<string, (function|string)>} overrides - An object containing classes to override any matching registered classes with, if no overrides are required you can pass `false` or `null`.
5445
- * @param {*} arg1 - The first argument to supply when creating new instances of all registered classes.
5446
- * @param {...*} [argN] - Any number of additional arguments to supply when creating new instances of all registered classes.
5447
- * @returns {Array.<Object>} An array containing new instances of all registered classes.
5448
- * @description The class indexes within the result array are determined by the `priority` they were registered with, the higher the `priority` the lower the index.
5449
- *
5450
- * This method is designed to be used when all registered classes share a common interface or base type and constructor arguments.
5451
- * @example {@caption The following loads all registered classes into an array ordered by there priority.}{@run true}
5452
- * // create a new instance of the factory, this is usually exposed by the class that will be using the factory.
5453
- * var factory = new FooGallery.utils.Factory();
5454
- *
5455
- * // create a base Extension class
5456
- * var Extension = FooGallery.utils.Class.extend({
5457
- * construct: function( type, options ){
5458
- * this.type = type;
5459
- * this.options = options;
5460
- * },
5461
- * getType: function(){
5462
- * return this.type;
5463
- * }
5464
- * });
5465
- *
5466
- * // create various item, this would usually be in another file
5467
- * var MyExtension1 = Extension.extend({
5468
- * construct: function(options){
5469
- * this._super( "my-extension-1", options );
5470
- * }
5471
- * });
5472
- * factory.register( "my-extension-1", MyExtension1, 0 );
5473
- *
5474
- * // create various item, this would usually be in another file
5475
- * var MyExtension2 = Extension.extend({
5476
- * construct: function(options){
5477
- * this._super( "my-extension-2", options );
5478
- * }
5479
- * });
5480
- * factory.register( "my-extension-2", MyExtension2, 1 );
5481
- *
5482
- * // load all registered classes according to there priority passing the options to all constructors
5483
- * var loaded = factory.load( null, {"something": true} );
5484
- *
5485
- * // only two classes should be loaded
5486
- * console.log( loaded.length ); // => 2
5487
- *
5488
- * // the MyExtension2 class is loaded first due to it's priority being higher than the MyExtension1 class.
5489
- * console.log( loaded[0] instanceof MyExtension2 && loaded[0] instanceof Extension ); // => true
5490
- * console.log( loaded[1] instanceof MyExtension1 && loaded[1] instanceof Extension ); // => true
5491
- *
5492
- * // do something with the loaded classes
5493
- * @example {@caption The following loads all registered classes into an array ordered by there priority but uses the overrides parameter to swap out one of them for a custom implementation.}{@run true}
5494
- * // create a new instance of the factory, this is usually exposed by the class that will be using the factory.
5495
- * var factory = new FooGallery.utils.Factory();
5496
- *
5497
- * // create a base Extension class
5498
- * var Extension = FooGallery.utils.Class.extend({
5499
- * construct: function( type, options ){
5500
- * this.type = type;
5501
- * this.options = options;
5502
- * },
5503
- * getType: function(){
5504
- * return this.type;
5505
- * }
5506
- * });
5507
- *
5508
- * // create a new extension, this would usually be in another file
5509
- * var MyExtension1 = Extension.extend({
5510
- * construct: function(options){
5511
- * this._super( "my-extension-1", options );
5512
- * }
5513
- * });
5514
- * factory.register( "my-extension-1", MyExtension1, 0 );
5515
- *
5516
- * // create a new extension, this would usually be in another file
5517
- * var MyExtension2 = Extension.extend({
5518
- * construct: function(options){
5519
- * this._super( "my-extension-2", options );
5520
- * }
5521
- * });
5522
- * factory.register( "my-extension-2", MyExtension2, 1 );
5523
- *
5524
- * // create a custom extension that is not registered but overrides the default "my-extension-1"
5525
- * var UpdatedMyExtension1 = MyExtension1.extend({
5526
- * construct: function(options){
5527
- * this._super( options );
5528
- * // do something different to the original MyExtension1 class
5529
- * }
5530
- * });
5531
- *
5532
- * // load all registered classes but swaps out the registered "my-extension-1" for the supplied override.
5533
- * var loaded = factory.load( {"my-extension-1": UpdatedMyExtension1}, {"something": true} );
5534
- *
5535
- * // only two classes should be loaded
5536
- * console.log( loaded.length ); // => 2
5537
- *
5538
- * // the MyExtension2 class is loaded first due to it's priority being higher than the UpdatedMyExtension1 class which inherited a priority of 0.
5539
- * console.log( loaded[0] instanceof MyExtension2 && loaded[0] instanceof Extension ); // => true
5540
- * console.log( loaded[1] instanceof UpdatedMyExtension1 && loaded[1] instanceof MyExtension1 && loaded[1] instanceof Extension ); // => true
5541
- *
5542
- * // do something with the loaded classes
5543
- */
5544
- load: function(overrides, arg1, argN){
5545
- var self = this,
5546
- args = _fn.arg2arr(arguments),
5547
- reg = [],
5548
- loaded = [],
5549
- name, klass;
5550
-
5551
- overrides = args.shift() || {};
5552
- for (name in self.registered){
5553
- if (!self.registered.hasOwnProperty(name)) continue;
5554
- var component = self.registered[name];
5555
- if (overrides.hasOwnProperty(name)){
5556
- klass = overrides[name];
5557
- if (_is.string(klass)) klass = _fn.fetch(overrides[name]);
5558
- if (_is.fn(klass)){
5559
- component = {name: name, klass: klass, priority: self.registered[name].priority};
5560
- }
5561
- }
5562
- reg.push(component);
5563
- }
5564
 
5565
- for (name in overrides){
5566
- if (!overrides.hasOwnProperty(name) || self.registered.hasOwnProperty(name)) continue;
5567
- klass = overrides[name];
5568
- if (_is.string(klass)) klass = _fn.fetch(overrides[name]);
5569
- if (_is.fn(klass)){
5570
- reg.push({name: name, klass: klass, priority: 0});
5571
- }
5572
- }
5573
 
5574
- reg.sort(function(a, b){ return b.priority - a.priority; });
5575
- $.each(reg, function(i, r){
5576
- if (_is.fn(r.klass)){
5577
- loaded.push(_fn.apply(r.klass, args));
5578
- }
5579
- });
5580
- return loaded;
5581
- },
5582
- /**
5583
- * @summary Create a new instance of a class registered with the supplied `name` and arguments.
5584
- * @memberof FooGallery.utils.Factory#
5585
- * @function make
5586
- * @param {string} name - The name of the class to create.
5587
- * @param {*} arg1 - The first argument to supply to the new instance.
5588
- * @param {...*} [argN] - Any number of additional arguments to supply to the new instance.
5589
- * @returns {Object}
5590
- * @example {@caption The following shows how to create a new instance of a registered class.}{@run true}
5591
- * // create a new instance of the factory, this is usually done by the class that will be using it.
5592
- * var factory = new FooGallery.utils.Factory();
5593
- *
5594
- * // create a Logger class to register, this would usually be in another file
5595
- * var Logger = FooGallery.utils.Class.extend({
5596
- * write: function( message ){
5597
- * console.log( "Logger#write: " + message );
5598
- * }
5599
- * });
5600
- *
5601
- * factory.register( "logger", Logger );
5602
- *
5603
- * // create a new instances of the class registered as "logger"
5604
- * var logger = factory.make( "logger" );
5605
- * logger.write( "My message" ); // => "Logger#write: My message"
5606
- */
5607
- make: function(name, arg1, argN){
5608
- var self = this, args = _fn.arg2arr(arguments), reg;
5609
- name = args.shift();
5610
- reg = self.registered[name];
5611
- if (_is.hash(reg) && _is.fn(reg.klass)){
5612
- return _fn.apply(reg.klass, args);
5613
- }
5614
- return null;
5615
- },
5616
- /**
5617
- * @summary Gets an array of all registered names.
5618
- * @memberof FooGallery.utils.Factory#
5619
- * @function names
5620
- * @param {boolean} [prioritize=false] - Whether or not to order the names by the priority they were registered with.
5621
- * @returns {Array.<string>}
5622
- * @example {@run true}
5623
- * // create a new instance of the factory, this is usually exposed by the class that will be using the factory.
5624
- * var factory = new FooGallery.utils.Factory();
5625
- *
5626
- * // create some classes to register
5627
- * function Test1(){}
5628
- * function Test2(){}
5629
- *
5630
- * // register the classes with the factory with the default priority
5631
- * factory.register( "test-1", Test1 );
5632
- * factory.register( "test-2", Test2, 1 );
5633
- *
5634
- * // log all registered names
5635
- * console.log( factory.names() ); // => ["test-1","test-2"]
5636
- * console.log( factory.names( true ) ); // => ["test-2","test-1"] ~ "test-2" appears before "test-1" as it was registered with a higher priority
5637
- */
5638
- names: function( prioritize ){
5639
- prioritize = _is.boolean(prioritize) ? prioritize : false;
5640
- var names = [], name;
5641
- if (prioritize){
5642
- var reg = [];
5643
- for (name in this.registered){
5644
- if (!this.registered.hasOwnProperty(name)) continue;
5645
- reg.push(this.registered[name]);
5646
- }
5647
- reg.sort(function(a, b){ return b.priority - a.priority; });
5648
- $.each(reg, function(i, r){
5649
- names.push(r.name);
5650
- });
5651
- } else {
5652
- for (name in this.registered){
5653
- if (!this.registered.hasOwnProperty(name)) continue;
5654
- names.push(name);
5655
- }
5656
- }
5657
- return names;
5658
- },
5659
- /**
5660
- * @summary Registers a `klass` constructor with the factory using the given `name`.
5661
- * @memberof FooGallery.utils.Factory#
5662
- * @function register
5663
- * @param {string} name - The friendly name of the class.
5664
- * @param {function} klass - The class constructor to register.
5665
- * @param {number} [priority=0] - This determines the index for the class when using either the {@link FooGallery.utils.Factory#load|load} or {@link FooGallery.utils.Factory#names|names} methods, a higher value equals a lower index.
5666
- * @returns {boolean} `true` if the `klass` was successfully registered.
5667
- * @description Once a class is registered you can use either the {@link FooGallery.utils.Factory#load|load} or {@link FooGallery.utils.Factory#make|make} methods to create new instances depending on your use case.
5668
- * @example {@run true}
5669
- * // create a new instance of the factory, this is usually exposed by the class that will be using the factory.
5670
- * var factory = new FooGallery.utils.Factory();
5671
- *
5672
- * // create a class to register
5673
- * function Test(){}
5674
- *
5675
- * // register the class with the factory with the default priority
5676
- * var succeeded = factory.register( "test", Test );
5677
- *
5678
- * console.log( succeeded ); // => true
5679
- * console.log( factory.registered.hasOwnProperty( "test" ) ); // => true
5680
- * console.log( factory.registered[ "test" ].name === "test" ); // => true
5681
- * console.log( factory.registered[ "test" ].klass === Test ); // => true
5682
- * console.log( factory.registered[ "test" ].priority === 0 ); // => true
5683
- */
5684
- register: function(name, klass, priority){
5685
- if (!_is.string(name) || _is.empty(name) || !_is.fn(klass)) return false;
5686
- priority = _is.number(priority) ? priority : 0;
5687
- var current = this.registered[name];
5688
- this.registered[name] = {
5689
- name: name,
5690
- klass: klass,
5691
- priority: !_is.undef(current) ? current.priority : priority
5692
- };
5693
- return true;
5694
- }
5695
- });
5696
 
5697
- })(
5698
- // dependencies
5699
- FooGallery.utils.$,
5700
- FooGallery.utils,
5701
- FooGallery.utils.is,
5702
- FooGallery.utils.fn
5703
- );
5704
- (function($, _, _fn){
5705
- // only register methods if this version is the current version
5706
- if (_.version !== '0.2.2') return;
 
 
 
 
 
5707
 
5708
  /**
5709
- * @summary A wrapper around the fullscreen API to ensure cross browser compatibility.
5710
- * @memberof FooGallery.utils.
5711
- * @class FullscreenAPI
5712
- * @augments FooGallery.utils.EventClass
5713
- * @borrows FooGallery.utils.EventClass.extend as extend
5714
- * @borrows FooGallery.utils.EventClass.override as override
5715
  */
5716
- _.FullscreenAPI = _.EventClass.extend(/** @lends FooGallery.utils.FullscreenAPI */{
5717
- /**
5718
- * @ignore
5719
- * @constructs
5720
- */
5721
- construct: function(){
5722
- this._super();
5723
- /**
5724
- * @summary An object containing a single browsers various methods and events needed for this wrapper.
5725
- * @typedef {?Object} FooGallery.utils.FullscreenAPI~BrowserAPI
5726
- * @property {string} enabled
5727
- * @property {string} element
5728
- * @property {string} request
5729
- * @property {string} exit
5730
- * @property {Object} events
5731
- * @property {string} events.change
5732
- * @property {string} events.error
5733
- */
5734
 
5735
- /**
5736
- * @summary An object containing the supported fullscreen browser API's.
5737
- * @typedef {Object.<string, FooGallery.utils.FullscreenAPI~BrowserAPI>} FooGallery.utils.FullscreenAPI~SupportedBrowsers
5738
- */
5739
 
5740
- /**
5741
- * @summary Contains the various browser specific method and event names.
5742
- * @memberof FooGallery.utils.FullscreenAPI#
5743
- * @name apis
5744
- * @type {FooGallery.utils.FullscreenAPI~SupportedBrowsers}
5745
- */
5746
- this.apis = {
5747
- w3: {
5748
- enabled: "fullscreenEnabled",
5749
- element: "fullscreenElement",
5750
- request: "requestFullscreen",
5751
- exit: "exitFullscreen",
5752
- events: {
5753
- change: "fullscreenchange",
5754
- error: "fullscreenerror"
5755
- }
5756
- },
5757
- webkit: {
5758
- enabled: "webkitFullscreenEnabled",
5759
- element: "webkitCurrentFullScreenElement",
5760
- request: "webkitRequestFullscreen",
5761
- exit: "webkitExitFullscreen",
5762
- events: {
5763
- change: "webkitfullscreenchange",
5764
- error: "webkitfullscreenerror"
5765
- }
5766
- },
5767
- moz: {
5768
- enabled: "mozFullScreenEnabled",
5769
- element: "mozFullScreenElement",
5770
- request: "mozRequestFullScreen",
5771
- exit: "mozCancelFullScreen",
5772
- events: {
5773
- change: "mozfullscreenchange",
5774
- error: "mozfullscreenerror"
5775
- }
5776
- },
5777
- ms: {
5778
- enabled: "msFullscreenEnabled",
5779
- element: "msFullscreenElement",
5780
- request: "msRequestFullscreen",
5781
- exit: "msExitFullscreen",
5782
- events: {
5783
- change: "MSFullscreenChange",
5784
- error: "MSFullscreenError"
5785
- }
5786
- }
5787
- };
5788
- /**
5789
- * @summary The current browsers specific method and event names.
5790
- * @memberof FooGallery.utils.FullscreenAPI#
5791
- * @name api
5792
- * @type {FooGallery.utils.FullscreenAPI~BrowserAPI}
5793
- */
5794
- this.api = this.getAPI();
5795
- /**
5796
- * @summary Whether or not the fullscreen API is supported in the current browser.
5797
- * @memberof FooGallery.utils.FullscreenAPI#
5798
- * @name supported
5799
- * @type {boolean}
5800
- */
5801
- this.supported = this.api != null;
5802
- this.__listen();
5803
- },
5804
- /**
5805
- * @summary Destroys the current wrapper unbinding events and freeing up resources.
5806
- * @memberof FooGallery.utils.FullscreenAPI#
5807
- * @function destroy
5808
- * @returns {boolean}
5809
- */
5810
- destroy: function(){
5811
- this.__stopListening();
5812
- return this._super();
5813
- },
5814
- /**
5815
- * @summary Fetches the correct API for the current browser.
5816
- * @memberof FooGallery.utils.FullscreenAPI#
5817
- * @function getAPI
5818
- * @return {?FooGallery.utils.FullscreenAPI~BrowserAPI} Returns `null` if the fullscreen API is not supported.
5819
- */
5820
- getAPI: function(){
5821
- for (var vendor in this.apis) {
5822
- if (!this.apis.hasOwnProperty(vendor)) continue;
5823
- // Check if document has the "enabled" property
5824
- if (this.apis[vendor].enabled in document) {
5825
- // It seems this browser supports the fullscreen API
5826
- return this.apis[vendor];
5827
- }
5828
- }
5829
- return null;
5830
- },
5831
- /**
5832
- * @summary Gets the current fullscreen element or null.
5833
- * @memberof FooGallery.utils.FullscreenAPI#
5834
- * @function element
5835
- * @returns {?Element}
5836
- */
5837
- element: function(){
5838
- return this.supported ? document[this.api.element] : null;
5839
- },
5840
- /**
5841
- * @summary Requests the browser to place the specified element into fullscreen mode.
5842
- * @memberof FooGallery.utils.FullscreenAPI#
5843
- * @function request
5844
- * @param {Element} element - The element to place into fullscreen mode.
5845
- * @returns {Promise} A Promise which is resolved once the element is placed into fullscreen mode.
5846
- */
5847
- request: function(element){
5848
- if (this.supported && !!element[this.api.request]){
5849
- var result = element[this.api.request]();
5850
- return !result ? $.Deferred(this.__resolver(this.api.request)).promise() : result;
5851
- }
5852
- return _fn.rejected;
5853
- },
5854
- /**
5855
- * @summary Requests that the browser switch from fullscreen mode back to windowed mode.
5856
- * @memberof FooGallery.utils.FullscreenAPI#
5857
- * @function exit
5858
- * @returns {Promise} A Promise which is resolved once fullscreen mode is exited.
5859
- */
5860
- exit: function(){
5861
- if (this.supported && !!this.element()){
5862
- var result = document[this.api.exit]();
5863
- return !result ? $.Deferred(this.__resolver(this.api.exit)).promise() : result;
5864
- }
5865
- return _fn.rejected;
5866
- },
5867
- /**
5868
- * @summary Toggles the supplied element between fullscreen and windowed modes.
5869
- * @memberof FooGallery.utils.FullscreenAPI#
5870
- * @function toggle
5871
- * @param {Element} element - The element to switch between modes.
5872
- * @returns {Promise} A Promise that is resolved once fullscreen mode is either entered or exited.
5873
- */
5874
- toggle: function(element){
5875
- return !!this.element() ? this.exit() : this.request(element);
5876
- },
5877
- /**
5878
- * @summary Starts listening to the document level fullscreen events and triggers an abbreviated version on this class.
5879
- * @memberof FooGallery.utils.FullscreenAPI#
5880
- * @function __listen
5881
- * @private
5882
- */
5883
- __listen: function(){
5884
- var self = this;
5885
- if (!self.supported) return;
5886
- $(document).on(self.api.events.change + ".utils", function() {
5887
- self.trigger("change");
5888
- }).on(self.api.events.error + ".utils", function() {
5889
- self.trigger("error");
5890
- });
5891
- },
5892
- /**
5893
- * @summary Stops listening to the document level fullscreen events.
5894
- * @memberof FooGallery.utils.FullscreenAPI#
5895
- * @function __stopListening
5896
- * @private
5897
- */
5898
- __stopListening: function(){
5899
- var self = this;
5900
- if (!self.supported) return;
5901
- $(document).off(self.api.events.change + ".utils")
5902
- .off(self.api.events.error + ".utils");
5903
- },
5904
- /**
5905
- * @summary Creates a resolver function to patch browsers which do not return a Promise from there request and exit methods.
5906
- * @memberof FooGallery.utils.FullscreenAPI#
5907
- * @function __resolver
5908
- * @param {string} method - The request or exit method the resolver is being created for.
5909
- * @returns {resolver}
5910
- * @private
5911
- */
5912
- __resolver: function(method){
5913
- var self = this;
5914
- /**
5915
- * @summary Binds to the fullscreen change and error events and resolves or rejects the supplied deferred accordingly.
5916
- * @callback FooGallery.utils.FullscreenAPI~resolver
5917
- * @param {jQuery.Deferred} def - The jQuery.Deferred object to resolve.
5918
- */
5919
- return function resolver(def) {
5920
- // Reject the promise if asked to exitFullscreen and there is no element currently in fullscreen
5921
- if (method === self.api.exit && !!self.element()) {
5922
- setTimeout(function() {
5923
- def.reject(new TypeError());
5924
- }, 1);
5925
- return;
5926
- }
5927
 
5928
- // When receiving an internal fullscreenchange event, fulfill the promise
5929
- function change() {
5930
- def.resolve();
5931
- $(document).off(self.api.events.change, change)
5932
- .off(self.api.events.error, error);
5933
- }
 
 
 
 
 
 
 
 
 
5934
 
5935
- // When receiving an internal fullscreenerror event, reject the promise
5936
- function error() {
5937
- def.reject(new TypeError());
5938
- $(document).off(self.api.events.change, change)
5939
- .off(self.api.events.error, error);
5940
- }
 
 
 
 
 
5941
 
5942
- $(document).on(self.api.events.change, change)
5943
- .on(self.api.events.error, error);
5944
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5945
  }
5946
- });
5947
 
5948
- })(
5949
- FooGallery.utils.$,
5950
- FooGallery.utils,
5951
- FooGallery.utils.fn
5952
- );
5953
- (function ($, _, _utils, _is, _fn) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5954
 
5955
- /**
5956
- * @summary The url of an empty 1x1 pixel image used as the default value for the `placeholder` and `error` {@link FooGallery.defaults|options}.
5957
- * @memberof FooGallery
5958
- * @name EMPTY_IMAGE
5959
- * @type {string}
5960
- * @default "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
5961
- */
5962
- _.EMPTY_IMAGE = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5963
 
5964
  /**
5965
  * @summary The name to use when getting or setting an instance of a {@link FooGallery.Template|template} on an element using jQuery's `.data()` method.
@@ -5998,12 +5495,6 @@
5998
  return tmpl instanceof _.Template ? tmpl.initialize() : _fn.rejected;
5999
  };
6000
 
6001
- _.initAll = function (options) {
6002
- return _fn.when($(".foogallery").map(function (i, element) {
6003
- return _.init(options, element);
6004
- }).get());
6005
- };
6006
-
6007
  /**
6008
  * @summary Expose FooGallery as a jQuery plugin.
6009
  * @memberof external:"jQuery.fn"#
@@ -6121,8 +5612,82 @@
6121
  return _.supportedExifProperties.indexOf(key) !== -1 && !_is.empty(value[key]);
6122
  });
6123
  }
6124
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6125
  };
 
 
 
 
6126
 
6127
  })(
6128
  FooGallery.$,
@@ -6132,6 +5697,76 @@
6132
  FooGallery.utils.fn,
6133
  FooGallery.utils.str
6134
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6135
  (function($, _, _utils, _is, _obj) {
6136
 
6137
  var DATA_NAME = "__FooGallerySwipe__",
@@ -6451,15 +6086,220 @@
6451
  FooGallery.utils.is,
6452
  FooGallery.utils.obj
6453
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6454
  (function ($, _, _utils, _is, _fn, _obj) {
6455
 
6456
- _.TemplateFactory = _utils.Factory.extend(/** @lends FooGallery.TemplateFactory */{
6457
  /**
6458
  * @summary A factory for galleries allowing them to be easily registered and created.
6459
  * @memberof FooGallery
6460
  * @constructs TemplateFactory
6461
  * @description The plugin makes use of an instance of this class exposed as {@link FooGallery.template}.
6462
- * @augments FooGallery.utils.Factory
6463
  * @borrows FooGallery.utils.Class.extend as extend
6464
  * @borrows FooGallery.utils.Class.override as override
6465
  */
@@ -6516,223 +6356,79 @@
6516
  * @memberof FooGallery.TemplateFactory#
6517
  * @function make
6518
  * @param {(object|FooGallery~Options)} [options] - The options for the template. If not supplied this will fall back to using the {@link FooGallery.defaults|defaults}.
6519
- * @param {(jQuery|HTMLElement|string)} [element] - The jQuery object, HTMLElement or selector of the template element to create. If not supplied the {@link FooGallery~Options#type|type} options' value is used.
6520
- * @returns {FooGallery.Template}
6521
- */
6522
- make: function (options, element) {
6523
- element = _is.jq(element) ? element : $(element);
6524
- options = _obj.extend({}, options, element.data("foogallery"));
6525
- var self = this, type = self.type(options, element);
6526
- if (!self.contains(type)) return null;
6527
- options = self.options(type, options);
6528
- return self._super(type, options, element);
6529
- },
6530
- type: function (options, element) {
6531
- element = _is.jq(element) ? element : $(element);
6532
- var self = this, type = _is.hash(options) && _is.hash(options) && _is.string(options.type) && self.contains(options.type) ? options.type : null;
6533
- if (type === null && element.length > 0) {
6534
- var reg = self.registered, names = self.names(true);
6535
- for (var i = 0, l = names.length; i < l; i++) {
6536
- if (!reg.hasOwnProperty(names[i]) || names[i] === "core") continue;
6537
- var name = names[i], cls = reg[name].cls;
6538
- if (!_is.string(cls.container)) continue;
6539
- var selector = _utils.selectify(cls.container);
6540
- if (element.is(selector)) {
6541
- type = names[i];
6542
- break;
6543
- }
6544
- }
6545
- }
6546
- return type;
6547
- },
6548
- configure: function (name, options, classes, il8n) {
6549
- var self = this;
6550
- if (self.contains(name)) {
6551
- var reg = self.registered;
6552
- _obj.extend(reg[name].opt, options);
6553
- _obj.extend(reg[name].cls, classes);
6554
- _obj.extend(reg[name].il8n, il8n);
6555
- }
6556
- },
6557
- options: function (name, options) {
6558
- options = _obj.extend({type: name}, options);
6559
- var self = this, reg = self.registered,
6560
- def = reg["core"].opt,
6561
- cls = reg["core"].cls,
6562
- il8n = reg["core"].il8n;
6563
-
6564
- if (!_is.hash(options.cls)) options.cls = {};
6565
- if (!_is.hash(options.il8n)) options.il8n = {};
6566
- if (!_is.undef(_.filtering)) options = _.filtering.merge(options);
6567
- if (!_is.undef(_.paging)) options = _.paging.merge(options);
6568
-
6569
- if (name !== "core" && self.contains(name)) {
6570
- options = _obj.extend({}, def, reg[name].opt, options);
6571
- options.cls = _obj.extend({}, cls, reg[name].cls, options.cls);
6572
- options.il8n = _obj.extend({}, il8n, reg[name].il8n, options.il8n);
6573
- } else {
6574
- options = _obj.extend({}, def, options);
6575
- options.cls = _obj.extend({}, cls, options.cls);
6576
- options.il8n = _obj.extend({}, il8n, options.il8n);
6577
- }
6578
- return options;
6579
- }
6580
- });
6581
-
6582
- /**
6583
- * @summary The factory used to register and create the various template types of FooGallery.
6584
- * @memberof FooGallery
6585
- * @name template
6586
- * @type {FooGallery.TemplateFactory}
6587
- */
6588
- _.template = new _.TemplateFactory();
6589
-
6590
- })(
6591
- FooGallery.$,
6592
- FooGallery,
6593
- FooGallery.utils,
6594
- FooGallery.utils.is,
6595
- FooGallery.utils.fn,
6596
- FooGallery.utils.obj
6597
- );
6598
- (function(_, _utils, _is, _fn, _obj){
6599
-
6600
- _.PagingFactory = _utils.Factory.extend(/** @lends FooGallery.PagingFactory */{
6601
- /**
6602
- * @summary A factory for paging types allowing them to be easily registered and created.
6603
- * @memberof FooGallery
6604
- * @constructs PagingFactory
6605
- * @description The plugin makes use of an instance of this class exposed as {@link FooGallery.paging}.
6606
- * @augments FooGallery.Factory
6607
- * @borrows FooGallery.Factory.extend as extend
6608
- * @borrows FooGallery.Factory.override as override
6609
- */
6610
- construct: function(){
6611
- /**
6612
- * @summary An object containing all registered paging types.
6613
- * @memberof FooGallery.PagingFactory#
6614
- * @name registered
6615
- * @type {Object.<string, Object>}
6616
- * @readonly
6617
- * @example {@caption The following shows the structure of this object. The `<name>` placeholders would be the name the class was registered with.}
6618
- * {
6619
- * "<name>": {
6620
- * "name": <string>,
6621
- * "klass": <function>,
6622
- * "ctrl": <function>,
6623
- * "priority": <number>
6624
- * },
6625
- * "<name>": {
6626
- * "name": <string>,
6627
- * "klass": <function>,
6628
- * "ctrl": <function>,
6629
- * "priority": <number>
6630
- * },
6631
- * ...
6632
- * }
6633
- */
6634
- this.registered = {};
6635
- },
6636
- /**
6637
- * @summary Registers a paging `type` constructor with the factory using the given `name` and `test` function.
6638
- * @memberof FooGallery.PagingFactory#
6639
- * @function register
6640
- * @param {string} name - The friendly name of the class.
6641
- * @param {FooGallery.Paging} type - The paging type constructor to register.
6642
- * @param {FooGallery.PagingControl} [ctrl] - An optional control to register for the paging type.
6643
- * @param {object} [options={}] - The default options for the paging type.
6644
- * @param {object} [classes={}] - The CSS classes for the paging type.
6645
- * @param {object} [il8n={}] - The il8n strings for the paging type.
6646
- * @param {number} [priority=0] - This determines the index for the class when using either the {@link FooGallery.PagingFactory#load|load} or {@link FooGallery.PagingFactory#names|names} methods, a higher value equals a lower index.
6647
- * @returns {boolean} `true` if the `klass` was successfully registered.
6648
- */
6649
- register: function(name, type, ctrl, options, classes, il8n, priority){
6650
- var self = this, result = self._super(name, type, priority);
6651
- if (result){
6652
- var reg = self.registered;
6653
- reg[name].ctrl = _is.fn(ctrl) ? ctrl : null;
6654
- reg[name].opt = _is.hash(options) ? options : {};
6655
- reg[name].cls = _is.hash(classes) ? classes : {};
6656
- reg[name].il8n = _is.hash(il8n) ? il8n : {};
6657
- }
6658
- return result;
6659
- },
6660
- type: function(options){
6661
- var self = this, opt;
6662
- return _is.hash(options) && _is.hash(opt = options.paging) && _is.string(opt.type) && self.contains(opt.type) ? opt.type : null;
6663
- },
6664
- merge: function(options){
6665
- options = _obj.extend({}, options);
6666
- var self = this, type = self.type(options),
6667
- reg = self.registered,
6668
- def = reg["default"].opt,
6669
- def_cls = reg["default"].cls,
6670
- def_il8n = reg["default"].il8n,
6671
- opt = _is.hash(options.paging) ? options.paging : {},
6672
- cls = _is.hash(options.cls) && _is.hash(options.cls.paging) ? _obj.extend({}, options.cls.paging) : {},
6673
- il8n = _is.hash(options.il8n) && _is.hash(options.il8n.paging) ? _obj.extend({}, options.il8n.paging) : {};
6674
-
6675
- if (!_is.hash(options.cls)) options.cls = {};
6676
- if (!_is.hash(options.il8n)) options.il8n = {};
6677
- if (type !== "default" && self.contains(type)){
6678
- options.paging = _obj.extend({}, def, reg[type].opt, opt, {type: type});
6679
- options.cls = _obj.extend(options.cls, {paging: def_cls}, {paging: reg[type].cls}, {paging: cls});
6680
- options.il8n = _obj.extend(options.il8n, {paging: def_il8n}, {paging: reg[type].il8n}, {paging: il8n});
6681
- } else {
6682
- options.paging = _obj.extend({}, def, opt, {type: type});
6683
- options.cls = _obj.extend(options.cls, {paging: def_cls}, {paging: cls});
6684
- options.il8n = _obj.extend(options.il8n, {paging: def_il8n}, {paging: il8n});
6685
  }
6686
- return options;
6687
  },
6688
- configure: function(name, options, classes, il8n){
6689
  var self = this;
6690
- if (self.contains(name)){
6691
  var reg = self.registered;
6692
  _obj.extend(reg[name].opt, options);
6693
  _obj.extend(reg[name].cls, classes);
6694
  _obj.extend(reg[name].il8n, il8n);
6695
  }
6696
  },
6697
- /**
6698
- * @summary Checks if the factory contains a control registered using the supplied `name`.
6699
- * @memberof FooGallery.PagingFactory#
6700
- * @function hasCtrl
6701
- * @param {string} name - The friendly name of the class.
6702
- * @returns {boolean}
6703
- */
6704
- hasCtrl: function(name){
6705
- var self = this, reg = self.registered[name];
6706
- return _is.hash(reg) && _is.fn(reg.ctrl);
6707
- },
6708
- /**
6709
- * @summary Create a new instance of a control class registered with the supplied `name` and arguments.
6710
- * @memberof FooGallery.PagingFactory#
6711
- * @function makeCtrl
6712
- * @param {string} name - The friendly name of the class.
6713
- * @param {FooGallery.Template} template - The template creating the control.
6714
- * @param {FooGallery.Paging} parent - The parent paging class creating the control.
6715
- * @param {string} position - The position the control will be displayed at.
6716
- * @returns {?FooGallery.PagingControl}
6717
- */
6718
- makeCtrl: function(name, template, parent, position){
6719
- var self = this, reg = self.registered[name];
6720
- if (_is.hash(reg) && _is.fn(reg.ctrl)){
6721
- return new reg.ctrl(template, parent, position);
6722
  }
6723
- return null;
6724
  }
6725
  });
6726
 
6727
  /**
6728
- * @summary The factory used to register and create the various paging types of FooGallery.
6729
  * @memberof FooGallery
6730
- * @name paging
6731
- * @type {FooGallery.PagingFactory}
6732
  */
6733
- _.paging = new _.PagingFactory();
6734
 
6735
  })(
 
6736
  FooGallery,
6737
  FooGallery.utils,
6738
  FooGallery.utils.is,
@@ -6771,6 +6467,13 @@
6771
  * @type {jQuery}
6772
  */
6773
  self.$el = _is.jq(element) ? element : $(element);
 
 
 
 
 
 
 
6774
  /**
6775
  * @summary The jQuery object for the template containers scroll parent.
6776
  * @memberof FooGallery.Template#
@@ -6856,9 +6559,21 @@
6856
  * @private
6857
  */
6858
  self._initialize = null;
6859
- self._checkTimeout = null;
6860
  self._layoutTimeout = null;
 
 
 
 
 
 
6861
  self._layoutWidths = [];
 
 
 
 
 
 
6862
  self.initializing = false;
6863
  self.initialized = false;
6864
  self.destroying = false;
@@ -6869,9 +6584,12 @@
6869
  create: false,
6870
  children: false
6871
  };
6872
- self.robserver = new ResizeObserver(function () {
6873
- if (self.$el.is(":visible")) self.layout();
6874
- });
 
 
 
6875
  },
6876
 
6877
  // ################
@@ -6888,7 +6606,6 @@
6888
  * @fires FooGallery.Template~"pre-init.foogallery"
6889
  * @fires FooGallery.Template~"init.foogallery"
6890
  * @fires FooGallery.Template~"post-init.foogallery"
6891
- * @fires FooGallery.Template~"first-load.foogallery"
6892
  * @fires FooGallery.Template~"ready.foogallery"
6893
  */
6894
  initialize: function (parent) {
@@ -6898,10 +6615,8 @@
6898
  if (self.preInit(parent)){
6899
  self.init().then(function(){
6900
  if (self.postInit()){
6901
- self.firstLoad().then(function(){
6902
- self.ready();
6903
- def.resolve(self);
6904
- }).fail(def.reject);
6905
  } else {
6906
  def.reject("post-init failed");
6907
  }
@@ -6911,7 +6626,7 @@
6911
  }
6912
  }).fail(function (err) {
6913
  console.log("initialize failed", self, err);
6914
- self.destroy();
6915
  }).promise();
6916
  },
6917
  /**
@@ -6933,6 +6648,7 @@
6933
  }
6934
  if (self.$el.length === 0) {
6935
  self.$el = self.create();
 
6936
  self._undo.create = true;
6937
  }
6938
  if (parent.length > 0) {
@@ -6949,7 +6665,7 @@
6949
 
6950
  // at this point we have our container element free of pre-existing instances so let's bind any event listeners supplied by the .on option
6951
  if (!_is.empty(self.opt.on)) {
6952
- self.$el.on(self.opt.on);
6953
  }
6954
  self._undo.classes = self.$el.attr("class");
6955
  self._undo.style = self.$el.attr("style");
@@ -6962,7 +6678,6 @@
6962
  if (selector != null && !self.$el.is(selector)) {
6963
  self.$el.addClass(self.opt.classes);
6964
  }
6965
- self.robserver.observe(self.$el.get(0));
6966
 
6967
  // if the container currently has no children make them
6968
  if (self.$el.children().not(self.sel.item.elem).length === 0) {
@@ -6997,7 +6712,7 @@
6997
  * }
6998
  * });
6999
  */
7000
- return !self.raise("pre-init").isDefaultPrevented();
7001
  },
7002
  /**
7003
  * @summary Occurs as the template is initialized.
@@ -7049,8 +6764,8 @@
7049
  * }
7050
  * });
7051
  */
7052
- var e = self.raise("init");
7053
- if (e.isDefaultPrevented()) return _fn.rejectWith("init default prevented");
7054
  return self.items.fetch();
7055
  },
7056
  /**
@@ -7104,44 +6819,14 @@
7104
  * }
7105
  * });
7106
  */
7107
- var e = self.raise("post-init");
7108
  if (e.isDefaultPrevented()) return false;
7109
  self.state.init();
7110
- self.$scrollParent.on("scroll" + self.namespace, {self: self}, _fn.throttle(function () {
7111
- self.loadAvailable();
7112
- }, 50));
7113
  $(window).on("popstate" + self.namespace, {self: self}, self.onWindowPopState);
 
7114
  return true;
7115
  },
7116
- /**
7117
- * @summary Occurs after all template initialization work is completed.
7118
- * @memberof FooGallery.Template#
7119
- * @function firstLoad
7120
- * @returns {Promise}
7121
- * @fires FooGallery.Template~"first-load.foogallery"
7122
- */
7123
- firstLoad: function(){
7124
- var self = this;
7125
- if (self.destroying) return _fn.rejected;
7126
- /**
7127
- * @summary Raised after the template is fully initialized but before the first load occurs.
7128
- * @event FooGallery.Template~"first-load.foogallery"
7129
- * @type {jQuery.Event}
7130
- * @param {jQuery.Event} event - The jQuery.Event object for the current event.
7131
- * @param {FooGallery.Template} template - The template raising the event.
7132
- * @description This event is raised after all post-initialization work such as setting the initial state is performed but before the first load of items takes place.
7133
- * @example {@caption To listen for this event and perform some action when it occurs you would bind to it as follows.}
7134
- * $(".foogallery").foogallery({
7135
- * on: {
7136
- * "first-load.foogallery": function(event, template){
7137
- * // do something
7138
- * }
7139
- * }
7140
- * });
7141
- */
7142
- self.raise("first-load");
7143
- return self.loadAvailable();
7144
- },
7145
  /**
7146
  * @summary Occurs once the template is ready.
7147
  * @memberof FooGallery.Template#
@@ -7154,8 +6839,6 @@
7154
  if (self.destroying) return false;
7155
  self.initializing = false;
7156
  self.initialized = true;
7157
- // performed purely to re-check if any items need to be loaded after content has possibly shifted
7158
- self._check(1000);
7159
  /**
7160
  * @summary Raised after the template is fully initialized and is ready to be interacted with.
7161
  * @event FooGallery.Template~"ready.foogallery"
@@ -7172,7 +6855,7 @@
7172
  * }
7173
  * });
7174
  */
7175
- self.raise("ready");
7176
  return true;
7177
  },
7178
  /**
@@ -7251,10 +6934,8 @@
7251
  * }
7252
  * });
7253
  */
7254
- self.raise("destroy");
7255
  self.robserver.disconnect();
7256
- if (self._checkTimeout) clearTimeout(self._checkTimeout);
7257
- self.$scrollParent.off(self.namespace);
7258
  $(window).off(self.namespace);
7259
  self.state.destroy(preserveState);
7260
  if (self.filter) self.filter.destroy();
@@ -7278,7 +6959,7 @@
7278
  * }
7279
  * });
7280
  */
7281
- self.raise("destroyed");
7282
  self.$el.removeData(_.DATA_TEMPLATE);
7283
 
7284
  if (_is.empty(self._undo.classes)) self.$el.removeAttr("class");
@@ -7323,78 +7004,25 @@
7323
  return this.pages ? this.pages.available() : this.items.available();
7324
  },
7325
 
7326
- /**
7327
- * @summary Check if any available items need to be loaded and loads them.
7328
- * @memberof FooGallery.Template#
7329
- * @function loadAvailable
7330
- * @returns {Promise<FooGallery.Item[]>} Resolves with an array of {@link FooGallery.Item|items} as the first argument. If no items are loaded this array is empty.
7331
- */
7332
- loadAvailable: function () {
7333
- return this.items.load(this.getAvailable());
7334
- },
7335
-
7336
- getItems: function(){
7337
- return this.pages ? this.pages.items() : this.items.available();
7338
- },
7339
-
7340
- /**
7341
- * @summary Check if any available items need to be loaded and loads them.
7342
- * @memberof FooGallery.Template#
7343
- * @function _check
7344
- * @private
7345
- */
7346
- _check: function (delay) {
7347
- delay = _is.number(delay) ? delay : 0;
7348
- var self = this;
7349
- if (self._checkTimeout) clearTimeout(self._checkTimeout);
7350
- return self._checkTimeout = setTimeout(function () {
7351
- self._checkTimeout = null;
7352
- if (self.initialized && (!self.destroying || !self.destroyed)) {
7353
- self.loadAvailable();
7354
- }
7355
- }, delay);
7356
- },
7357
-
7358
  // #############
7359
  // ## Utility ##
7360
  // #############
7361
 
7362
  /**
7363
- * @summary Raises the supplied `eventName` on the template {@link FooGallery.Template#$el|element}.
7364
  * @memberof FooGallery.Template#
7365
- * @function raise
7366
- * @param {string} eventName - The name of the event to raise.
7367
- * @param {Array} [args] - An additional arguments to supply to the listeners for the event.
7368
- * @returns {?jQuery.Event} The jQuery.Event object or null if no `eventName` was supplied.
7369
- * @description This method also executes any listeners set on the template object itself. These listeners are not bound to the element but are executed after the event is raised but before any default logic is executed. The names of these listeners use the following convention; prefix the `eventName` with `"on-"` and then camel-case the result. e.g. `"pre-init"` becomes `onPreInit`.
7370
- * @example {@caption The following displays a listener for the `"pre-init.foogallery"` event in a sub-classed template.}
7371
- * FooGallery.MyTemplate = FooGallery.Template.extend({
7372
- * onPreInit: function(event, template){
7373
- * // do something
7374
- * }
7375
- * });
7376
  */
7377
- raise: function (eventName, args) {
7378
- if (this.destroying || this.destroyed || !_is.string(eventName) || _is.empty(eventName)) return null;
7379
- args = _is.array(args) ? args : [];
7380
- var self = this,
7381
- name = eventName.split(".")[0],
7382
- listener = _str.camel("on-" + name),
7383
- event = $.Event(name + ".foogallery");
7384
- args.unshift(self); // add self
7385
- var e = self.trigger(name, args);
7386
- if (e.defaultPrevented) event.preventDefault();
7387
- self.$el.trigger(event, args);
7388
- if (_is.fn(self[listener])) {
7389
- args.unshift(event); // add event
7390
- self[listener].apply(self.$el.get(0), args);
7391
- }
7392
- return event;
7393
- },
7394
-
7395
- layout: function () {
7396
- var self = this, width = self.getContainerWidth();
7397
- if (self._initialize === null || self._checkWidth(width)) return;
7398
  /**
7399
  * @summary Raised when the templates' {@link FooGallery.Template#layout|layout} method is called.
7400
  * @event FooGallery.Template~"layout.foogallery"
@@ -7411,10 +7039,12 @@
7411
  * }
7412
  * });
7413
  */
7414
- self.raise("layout", [width]);
7415
  },
7416
  /**
7417
  * @summary This method was added to prevent an infinite loop in the ResizeObserver.
 
 
7418
  * @description When the viewport has no scrollbar by default and is then resized down until the gallery layout requires a scrollbar
7419
  * to show. There could be an infinite loop as follows:
7420
  * 1. No scrollbar shown, layout occurs, scrollbar is then required.
@@ -7437,21 +7067,6 @@
7437
  return exists;
7438
  },
7439
 
7440
- /**
7441
- * @summary Gets the width of the FooGallery container.
7442
- * @memberof FooGallery.Template#
7443
- * @function
7444
- * @name getContainerWidth
7445
- * @returns {number}
7446
- */
7447
- getContainerWidth: function(){
7448
- var self = this, visible = self.$el.is(':visible');
7449
- if (!visible){
7450
- return self.$el.parents(':visible:first').innerWidth();
7451
- }
7452
- return self.$el.width();
7453
- },
7454
-
7455
  /**
7456
  * @summary Gets a specific type of CSS class from the template.
7457
  * @memberof FooGallery.Template#
@@ -7484,7 +7099,6 @@
7484
  var self = e.data.self, state = e.originalEvent.state;
7485
  if (!_is.empty(state) && state.id === self.id) {
7486
  self.state.set(state);
7487
- self.loadAvailable();
7488
  }
7489
  }
7490
  });
@@ -7495,13 +7109,11 @@
7495
  classes: "",
7496
  on: {},
7497
  lazy: true,
7498
- viewport: 200,
7499
  items: [],
7500
- fixLayout: true,
7501
  scrollParent: null,
7502
  delay: 0,
7503
  throttle: 50,
7504
- timeout: 60000,
7505
  srcset: "data-srcset-fg",
7506
  src: "data-src-fg",
7507
  template: {},
@@ -7510,6 +7122,7 @@
7510
  loadingIcon: /(?:\s|^)(fg-loading-(?:default|bars|dots|partial|pulse|trail))(?:\s|$)/,
7511
  hoverIcon: /(?:\s|^)(fg-hover-(?:zoom|zoom2|zoom3|plus|circle-plus|eye|external|tint))(?:\s|$)/,
7512
  videoIcon: /(?:\s|^)(fg-video-(?:default|1|2|3|4))(?:\s|$)/,
 
7513
  hoverColor: /(?:\s|^)(fg-hover-(?:colorize|grayscale))(?:\s|$)/,
7514
  hoverScale: /(?:\s|^)(fg-hover-scale)(?:\s|$)/,
7515
  stickyVideoIcon: /(?:\s|^)(fg-video-sticky)(?:\s|$)/,
@@ -7528,13 +7141,10 @@
7528
  * @property {string} [classes=""] - A space delimited string of any additional CSS classes to append to the container element of the template.
7529
  * @property {object} [on={}] - An object containing any template events to bind to.
7530
  * @property {boolean} [lazy=true] - Whether or not to enable lazy loading of images.
7531
- * @property {number} [viewport=200] - The number of pixels to inflate the viewport by when checking to lazy load items.
7532
  * @property {(FooGallery.Item~Options[]|FooGallery.Item[]| string)} [items=[]] - An array of items to load when required. A url can be provided and the items will be fetched using an ajax call, the response should be a properly formatted JSON array of {@link FooGallery.Item~Options|item} object.
7533
- * @property {boolean} [fixLayout=true] - Whether or not the items' size should be set with CSS until the image is loaded.
7534
  * @property {string} [scrollParent=null] - The selector used to bind to the scroll parent for the gallery. If not supplied the template will attempt to find the element itself.
7535
  * @property {number} [delay=0] - The number of milliseconds to delay the initialization of a template.
7536
  * @property {number} [throttle=50] - The number of milliseconds to wait once scrolling has stopped before performing any work.
7537
- * @property {number} [timeout=60000] - The number of milliseconds to wait before forcing a timeout when loading items.
7538
  * @property {string} [src="data-src-fg"] - The name of the attribute to retrieve an images src url from.
7539
  * @property {string} [srcset="data-srcset-fg"] - The name of the attribute to retrieve an images srcset url from.
7540
  * @property {object} [template={}] - An object containing any additional custom options for the template.
@@ -7576,17 +7186,17 @@
7576
  );
7577
  (function(_, _utils, _is){
7578
 
7579
- _.Component = _utils.Class.extend(/** @lend FooGallery.Component */{
7580
  /**
7581
  * @summary The base class for all child components of a {@link FooGallery.Template|template}.
7582
- * @memberof FooGallery
7583
- * @constructs Component
7584
  * @param {FooGallery.Template} template - The template creating the component.
7585
- * @augments FooGallery.utils.Class
7586
  * @borrows FooGallery.utils.Class.extend as extend
7587
  * @borrows FooGallery.utils.Class.override as override
7588
  */
7589
  construct: function(template){
 
7590
  /**
7591
  * @summary The template that created this component.
7592
  * @memberof FooGallery.Component#
@@ -7602,71 +7212,7 @@
7602
  */
7603
  destroy: function(){
7604
  this.tmpl = null;
7605
- }
7606
- });
7607
-
7608
- _.EventComponent = _utils.EventClass.extend(/** @lend FooGallery.EventComponent */{
7609
- /**
7610
- * @summary The base class for all child components of a {@link FooGallery.Template|template} that raise there own events.
7611
- * @constructs
7612
- * @param {FooGallery.Template} template - The template creating the component.
7613
- * @param {string} prefix - A prefix to prepend to any events bubbled up to the template.
7614
- * @augments FooGallery.utils.EventClass
7615
- * @borrows FooGallery.utils.Class.extend as extend
7616
- * @borrows FooGallery.utils.Class.override as override
7617
- */
7618
- construct: function(template, prefix){
7619
- this._super(template);
7620
- /**
7621
- * @summary The template that created this component.
7622
- * @memberof FooGallery.EventComponent#
7623
- * @name tmpl
7624
- * @type {FooGallery.Template}
7625
- */
7626
- this.tmpl = template;
7627
- /**
7628
- * @summary A prefix to prepend to any events bubbled up to the template.
7629
- * @memberof FooGallery.EventComponent#
7630
- * @name tmplEventPrefix
7631
- * @type {string}
7632
- */
7633
- this.tmplEventPrefix = prefix;
7634
- },
7635
- /**
7636
- * @summary Destroy the component making it ready for garbage collection.
7637
- * @memberof FooGallery.EventComponent#
7638
- * @function destroy
7639
- */
7640
- destroy: function(){
7641
  this._super();
7642
- this.tmpl = null;
7643
- },
7644
- /**
7645
- * @summary Trigger an event on the current component.
7646
- * @memberof FooGallery.EventComponent#
7647
- * @function trigger
7648
- * @param {(string|FooGallery.utils.Event)} event - Either a space-separated string of event types or a custom event object to raise.
7649
- * @param {Array} [args] - An array of additional arguments to supply to the handlers after the event object.
7650
- * @returns {(FooGallery.utils.Event|FooGallery.utils.Event[]|null)} Returns the {@link FooGallery.utils.Event|event object} of the triggered event. If more than one event was triggered an array of {@link FooGallery.utils.Event|event objects} is returned. If no `event` was supplied or triggered `null` is returned.
7651
- */
7652
- trigger: function(event, args){
7653
- var self = this, result = self._super(event, args), name, e;
7654
- if (self.tmpl != null){
7655
- if (result instanceof _utils.Event && !result.isDefaultPrevented()){
7656
- name = result.namespace != null ? [result.type, result.namespace].join(".") : result.type;
7657
- e = self.tmpl.raise(self.tmplEventPrefix + name, args);
7658
- if (!!e && e.isDefaultPrevented()) result.preventDefault();
7659
- } else if (_is.array(result)){
7660
- result.forEach(function (evt) {
7661
- if (!evt.isDefaultPrevented()){
7662
- name = evt.namespace != null ? [evt.type, evt.namespace].join(".") : evt.type;
7663
- e = self.tmpl.raise(self.tmplEventPrefix + name, args);
7664
- if (!!e && e.isDefaultPrevented()) evt.preventDefault();
7665
- }
7666
- });
7667
- }
7668
- }
7669
- return _is.empty(result) ? null : (result.length === 1 ? result[0] : result);
7670
  }
7671
  });
7672
 
@@ -7674,9 +7220,9 @@
7674
  * @summary A factory for registering and creating basic gallery components.
7675
  * @memberof FooGallery
7676
  * @name components
7677
- * @type {FooGallery.utils.Factory}
7678
  */
7679
- _.components = new _utils.Factory();
7680
 
7681
  })(
7682
  FooGallery,
@@ -7980,7 +7526,7 @@
7980
  if (_is.hash(state)){
7981
  var obj = _obj.extend({ filter: [], page: 1, item: null }, state);
7982
  tmpl.items.reset();
7983
- var e = tmpl.raise("before-state", [obj]);
7984
  if (!e.isDefaultPrevented()){
7985
  if (!!tmpl.filter){
7986
  tmpl.filter.setState(obj);
@@ -7988,10 +7534,14 @@
7988
  if (!!tmpl.pages){
7989
  tmpl.pages.setState(obj);
7990
  } else {
7991
- tmpl.items.detach(tmpl.items.all());
7992
- tmpl.items.create(tmpl.items.available(), true);
 
 
 
 
7993
  }
7994
- if (obj.item){
7995
  if (self.opt.scrollTo) {
7996
  obj.item.scrollTo();
7997
  }
@@ -8001,7 +7551,7 @@
8001
  }
8002
  }
8003
  self.current = obj;
8004
- tmpl.raise("after-state", [obj]);
8005
  }
8006
  }
8007
  },
@@ -8054,7 +7604,7 @@
8054
  );
8055
  (function ($, _, _utils, _is, _fn, _obj) {
8056
 
8057
- _.Items = _.Component.extend(/** @lends FooGallery.Items */{
8058
  /**
8059
  * @summary This class controls everything related to items and serves as the base class for the various paging types.
8060
  * @memberof FooGallery
@@ -8068,29 +7618,45 @@
8068
  var self = this;
8069
  self.ALLOW_CREATE = true;
8070
  self.ALLOW_APPEND = true;
8071
- self.ALLOW_LOAD = true;
8072
  /**
8073
  * @ignore
8074
  * @memberof FooGallery.Items#
8075
  * @function _super
8076
  */
8077
  self._super(template);
8078
- self.maps = {};
8079
  self._fetched = null;
8080
- self._arr = [];
8081
  self._available = [];
 
 
 
8082
  // add the .all caption selector
8083
  var cls = self.tmpl.cls.item.caption;
8084
  self.tmpl.sel.item.caption.all = _utils.selectify([cls.elem, cls.inner, cls.title, cls.description]);
 
 
 
 
 
 
 
 
 
 
 
 
 
8085
  },
8086
  fromHash: function(hash){
8087
- return this.get(hash);
8088
  },
8089
  toHash: function(value){
8090
  return value instanceof _.Item ? value.id : null;
8091
  },
8092
  destroy: function () {
8093
  var self = this, items = self.all(), destroyed = [];
 
8094
  if (items.length > 0) {
8095
  /**
8096
  * @summary Raised before the template destroys its' items.
@@ -8108,7 +7674,7 @@
8108
  * }
8109
  * });
8110
  */
8111
- self.tmpl.raise("destroy-items", [items]);
8112
  destroyed = $.map(items, function (item) {
8113
  return item.destroy() ? item : null;
8114
  });
@@ -8128,23 +7694,25 @@
8128
  * }
8129
  * });
8130
  */
8131
- if (destroyed.length > 0) self.tmpl.raise("destroyed-items", [destroyed]);
8132
  // should we handle a case where the destroyed.length != items.length??
8133
  }
8134
- self.maps = {};
8135
  self._fetched = null;
8136
- self._arr = [];
8137
  self._available = [];
 
 
8138
  self._super();
8139
  },
8140
  fetch: function (refresh) {
8141
  var self = this;
8142
  if (!refresh && _is.promise(self._fetched)) return self._fetched;
8143
- var fg = self.tmpl, selectors = fg.sel,
8144
- option = fg.opt.items,
8145
- def = $.Deferred();
 
8146
 
8147
- var items = self.make(fg.$el.find(selectors.item.elem));
8148
 
8149
  if (!_is.empty(option)) {
8150
  if (_is.array(option)) {
@@ -8162,7 +7730,9 @@
8162
  def.resolve(items);
8163
  }
8164
  } else {
8165
- items.push.apply(items, self.make(window[fg.id + "-items"]));
 
 
8166
  def.resolve(items);
8167
  }
8168
  def.then(function (items) {
@@ -8177,7 +7747,7 @@
8177
  });
8178
  },
8179
  all: function () {
8180
- return this._arr.slice();
8181
  },
8182
  count: function (all) {
8183
  return all ? this.all().length : this.available().length;
@@ -8188,18 +7758,31 @@
8188
  }
8189
  return this._available.slice();
8190
  },
8191
- get: function (idOrIndex) {
8192
- var map = _is.number(idOrIndex) ? 'index' : 'id';
8193
- return !!this.maps[map][idOrIndex] ? this.maps[map][idOrIndex] : null;
 
 
8194
  },
8195
  setAll: function (items) {
8196
- this._arr = _is.array(items) ? items : [];
8197
- this.maps = this.createMaps(this._arr);
 
 
 
8198
  this._available = this.all();
 
8199
  },
8200
  setAvailable: function (items) {
8201
- this.maps = this.createMaps(this._arr);
8202
- this._available = _is.array(items) ? items : [];
 
 
 
 
 
 
 
8203
  },
8204
  reset: function () {
8205
  this.setAvailable(this.all());
@@ -8215,6 +7798,21 @@
8215
  }
8216
  return null;
8217
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8218
  first: function(where){
8219
  return this.find(this._available, where);
8220
  },
@@ -8251,36 +7849,6 @@
8251
  }
8252
  return null;
8253
  },
8254
- createMaps: function(items){
8255
- items = _is.array(items) ? items : [];
8256
- var maps = {
8257
- id: {},
8258
- index: {}
8259
- };
8260
- $.each(items, function (i, item) {
8261
- if (_is.empty(item.id)) item.id = "" + (i + 1);
8262
- item.index = i;
8263
- maps.id[item.id] = item;
8264
- maps.index[item.index] = item;
8265
- });
8266
- return maps;
8267
- },
8268
- /**
8269
- * @summary Filter the supplied `items` and return only those that can be loaded.
8270
- * @memberof FooGallery.Items#
8271
- * @function loadable
8272
- * @param {FooGallery.Item[]} items - The items to filter.
8273
- * @returns {FooGallery.Item[]}
8274
- */
8275
- loadable: function (items) {
8276
- var self = this, opt = self.tmpl.opt, viewport;
8277
- if (opt.lazy) {
8278
- viewport = _utils.getViewportBounds(opt.viewport);
8279
- }
8280
- return self.ALLOW_LOAD && _is.array(items) ? $.map(items, function (item) {
8281
- return item.isCreated && item.isAttached && !item.isLoading && !item.isLoaded && !item.isError && (!opt.lazy || (opt.lazy && item.intersects(viewport))) ? item : null;
8282
- }) : [];
8283
- },
8284
  /**
8285
  * @summary Filter the supplied `items` and return only those that can be created.
8286
  * @memberof FooGallery.Items#
@@ -8372,7 +7940,7 @@
8372
  * }
8373
  * });
8374
  */
8375
- var e = self.tmpl.raise("make-items", [arr]);
8376
  if (!e.isDefaultPrevented()) {
8377
  made = $.map(arr, function (obj) {
8378
  var type = self.type(obj), opt = _obj.extend(_is.hash(obj) ? obj : {}, {type: type});
@@ -8405,7 +7973,7 @@
8405
  * }
8406
  * });
8407
  */
8408
- if (made.length > 0) self.tmpl.raise("made-items", [made]);
8409
 
8410
  /**
8411
  * @summary Raised after the template has parsed any elements into an array of {@link FooGallery.Item|item} objects.
@@ -8423,17 +7991,21 @@
8423
  * }
8424
  * });
8425
  */
8426
- if (parsed.length > 0) self.tmpl.raise("parsed-items", [parsed]);
8427
  }
8428
  return made;
8429
  },
8430
  type: function (objOrElement) {
8431
- var type;
8432
  if (_is.hash(objOrElement)) {
8433
  type = objOrElement.type;
8434
  } else if (_is.element(objOrElement)) {
8435
- var $el = $(objOrElement), item = this.tmpl.sel.item;
8436
- type = $el.find(item.anchor).data("type");
 
 
 
 
8437
  }
8438
  return _is.string(type) && _.components.contains(type) ? type : "image";
8439
  },
@@ -8481,7 +8053,7 @@
8481
  * }
8482
  * });
8483
  */
8484
- var e = self.tmpl.raise("create-items", [creatable]);
8485
  if (!e.isDefaultPrevented()) {
8486
  created = $.map(creatable, function (item) {
8487
  return item.create() ? item : null;
@@ -8503,7 +8075,7 @@
8503
  * }
8504
  * });
8505
  */
8506
- if (created.length > 0) self.tmpl.raise("created-items", [created]);
8507
  }
8508
  if (_is.boolean(append) ? append : false) return self.append(items);
8509
  return created;
@@ -8547,7 +8119,7 @@
8547
  * }
8548
  * });
8549
  */
8550
- var e = self.tmpl.raise("append-items", [appendable]);
8551
  if (!e.isDefaultPrevented()) {
8552
  appended = $.map(appendable, function (item) {
8553
  return item.append() ? item : null;
@@ -8569,7 +8141,7 @@
8569
  * }
8570
  * });
8571
  */
8572
- if (appended.length > 0) self.tmpl.raise("appended-items", [appended]);
8573
  }
8574
  return appended;
8575
  },
@@ -8612,7 +8184,7 @@
8612
  * }
8613
  * });
8614
  */
8615
- var e = self.tmpl.raise("detach-items", [detachable]);
8616
  if (!e.isDefaultPrevented()) {
8617
  detached = $.map(detachable, function (item) {
8618
  return item.detach() ? item : null;
@@ -8632,79 +8204,25 @@
8632
  * // do something
8633
  * }
8634
  * }
8635
- * });
8636
- */
8637
- if (detached.length > 0) self.tmpl.raise("detached-items", [detached]);
8638
- }
8639
- return detached;
8640
- },
8641
- /**
8642
- * @summary Load each of the supplied `items` images.
8643
- * @memberof FooGallery.Items#
8644
- * @function load
8645
- * @param {FooGallery.Item[]} items - The array of items to load.
8646
- * @returns {Promise<FooGallery.Item[]>} Resolved with an array of {@link FooGallery.Item|items} as the first argument. If no items are loaded this array is empty.
8647
- * @fires FooGallery.Template~"load-items.foogallery"
8648
- * @fires FooGallery.Template~"loaded-items.foogallery"
8649
- */
8650
- load: function (items) {
8651
- var self = this;
8652
- items = self.loadable(items);
8653
- if (items.length > 0) {
8654
- /**
8655
- * @summary Raised before the template loads any items.
8656
- * @event FooGallery.Template~"load-items.foogallery"
8657
- * @type {jQuery.Event}
8658
- * @param {jQuery.Event} event - The jQuery.Event object for the current event.
8659
- * @param {FooGallery.Template} template - The template raising the event.
8660
- * @param {FooGallery.Item[]} items - The array of items to load.
8661
- * @example {@caption To listen for this event and perform some action when it occurs you would bind to it as follows.}
8662
- * $(".foogallery").foogallery({
8663
- * on: {
8664
- * "load-items.foogallery": function(event, template, items){
8665
- * // do something
8666
- * }
8667
- * }
8668
- * });
8669
- * @example {@caption Calling the `preventDefault` method on the `event` object will prevent any `items` being loaded.}
8670
- * $(".foogallery").foogallery({
8671
- * on: {
8672
- * "load-items.foogallery": function(event, template, items){
8673
- * if ("some condition"){
8674
- * // stop any items being loaded
8675
- * event.preventDefault();
8676
- * }
8677
- * }
8678
- * }
8679
- * });
8680
  */
8681
- var e = self.tmpl.raise("load-items", [items]);
8682
- if (!e.isDefaultPrevented()) {
8683
- var loading = $.map(items, function (item) {
8684
- return item.load();
8685
- });
8686
- return _fn.when(loading).done(function (loaded) {
8687
- /**
8688
- * @summary Raised after the template has loaded items.
8689
- * @event FooGallery.Template~"loaded-items.foogallery"
8690
- * @type {jQuery.Event}
8691
- * @param {jQuery.Event} event - The jQuery.Event object for the current event.
8692
- * @param {FooGallery.Template} template - The template raising the event.
8693
- * @param {FooGallery.Item[]} items - The array of items that were loaded.
8694
- * @example {@caption To listen for this event and perform some action when it occurs you would bind to it as follows.}
8695
- * $(".foogallery").foogallery({
8696
- * on: {
8697
- * "loaded-items.foogallery": function(event, template, items){
8698
- * // do something
8699
- * }
8700
- * }
8701
- * });
8702
- */
8703
- self.tmpl.raise("loaded-items", [loaded]);
8704
- });
8705
- }
8706
  }
8707
- return _fn.resolveWith([]);
8708
  }
8709
  });
8710
 
@@ -8806,6 +8324,12 @@
8806
  * @type {?jQuery}
8807
  */
8808
  self.$el = null;
 
 
 
 
 
 
8809
  /**
8810
  * @memberof FooGallery.Item#
8811
  * @name $inner
@@ -8842,13 +8366,12 @@
8842
  * @type {?jQuery}
8843
  */
8844
  self.$caption = null;
8845
-
8846
  /**
8847
  * @memberof FooGallery.Item#
8848
- * @name fixLayout
8849
- * @type {boolean}
8850
  */
8851
- self.fixLayout = self.tmpl.opt.fixLayout;
8852
 
8853
  /**
8854
  * @memberof FooGallery.Item#
@@ -8881,6 +8404,12 @@
8881
  * @type {string}
8882
  */
8883
  self.href = self.opt.href;
 
 
 
 
 
 
8884
  /**
8885
  * @memberof FooGallery.Item#
8886
  * @name src
@@ -8941,12 +8470,6 @@
8941
  * @type {string[]}
8942
  */
8943
  self.tags = self.opt.tags;
8944
- /**
8945
- * @memberof FooGallery.Item#
8946
- * @name maxWidth
8947
- * @type {?FooGallery.Item~maxWidthCallback}
8948
- */
8949
- self.maxWidth = self.opt.maxWidth;
8950
  /**
8951
  * @memberof FooGallery.Item#
8952
  * @name maxCaptionLength
@@ -8995,14 +8518,6 @@
8995
  * @type {boolean}
8996
  */
8997
  self.hasExif = _is.exif(self.exif);
8998
- /**
8999
- * @summary The cached result of the last call to the {@link FooGallery.Item#getThumbUrl|getThumbUrl} method.
9000
- * @memberof FooGallery.Item#
9001
- * @name _thumbUrl
9002
- * @type {?string}
9003
- * @private
9004
- */
9005
- self._thumbUrl = null;
9006
  /**
9007
  * @summary This property is used to store the promise created when loading an item for the first time.
9008
  * @memberof FooGallery.Item#
@@ -9021,9 +8536,6 @@
9021
  self._undo = {
9022
  classes: "",
9023
  style: "",
9024
- loader: false,
9025
- wrap: false,
9026
- overlay: false,
9027
  placeholder: false
9028
  };
9029
  },
@@ -9077,7 +8589,7 @@
9077
  * }
9078
  * });
9079
  */
9080
- var e = self.tmpl.raise("destroy-item", [self]);
9081
  if (!e.isDefaultPrevented()) {
9082
  self.isDestroyed = self.doDestroyItem();
9083
  }
@@ -9098,7 +8610,7 @@
9098
  * }
9099
  * });
9100
  */
9101
- self.tmpl.raise("destroyed-item", [self]);
9102
  // call the original method that simply nulls the tmpl property
9103
  self._super();
9104
  }
@@ -9115,23 +8627,16 @@
9115
  if (self.isParsed) {
9116
  self.$anchor.add(self.$caption).off("click.foogallery");
9117
  self.append();
 
 
 
9118
  if (_is.empty(self._undo.classes)) self.$el.removeAttr("class");
9119
  else self.$el.attr("class", self._undo.classes);
9120
 
9121
  if (_is.empty(self._undo.style)) self.$el.removeAttr("style");
9122
  else self.$el.attr("style", self._undo.style);
9123
 
9124
- if (self._undo.overlay) {
9125
- self.$overlay.remove();
9126
- }
9127
- if (self._undo.wrap) {
9128
- self.$anchor.append(self.$image);
9129
- self.$wrap.remove();
9130
- }
9131
- if (self._undo.loader) {
9132
- self.$el.find(self.sel.loader).remove();
9133
- }
9134
- if (self._undo.placeholder && self.$image.prop("src") === _.EMPTY_IMAGE) {
9135
  self.$image.removeAttr("src");
9136
  }
9137
  } else if (self.isCreated) {
@@ -9193,13 +8698,13 @@
9193
  * }
9194
  * });
9195
  */
9196
- var e = self.tmpl.raise("parse-item", [self, $el]);
9197
  if (!e.isDefaultPrevented() && (self.isCreated = $el.is(self.sel.elem))) {
9198
  self.isParsed = self.doParseItem($el);
9199
- if (self.fixLayout) self.fix();
9200
  // We don't load the attributes when parsing as they are only ever used to create an item and if you're parsing it's already created.
9201
  }
9202
  if (self.isParsed) {
 
9203
  /**
9204
  * @summary Raised after an item has been parsed from an element.
9205
  * @event FooGallery.Template~"parsed-item.foogallery"
@@ -9217,7 +8722,7 @@
9217
  * }
9218
  * });
9219
  */
9220
- self.tmpl.raise("parsed-item", [self]);
9221
  }
9222
  return self.isParsed;
9223
  },
@@ -9229,39 +8734,46 @@
9229
  * @returns {boolean}
9230
  */
9231
  doParseItem: function ($el) {
9232
- var self = this, o = self.tmpl.opt, cls = self.cls, sel = self.sel;
 
 
 
9233
 
9234
  self._undo.classes = $el.attr("class") || "";
9235
  self._undo.style = $el.attr("style") || "";
9236
 
9237
  self.$el = $el.data(_.DATA_ITEM, self);
9238
- self.$inner = self.$el.children(sel.inner);
9239
- self.$anchor = self.$inner.children(sel.anchor).on("click.foogallery", {self: self}, self.onAnchorClick);
9240
- self.$image = self.$anchor.find(sel.image);
9241
- self.$caption = self.$inner.children(sel.caption.elem).on("click.foogallery", {self: self}, self.onCaptionClick);
 
 
 
 
9242
 
9243
  if ( !self.$el.length || !self.$inner.length || !self.$anchor.length || !self.$image.length ){
9244
  console.error("FooGallery Error: Invalid HTML markup. Check the item markup for additional elements or malformed HTML in the title or description.", self);
9245
  self.isError = true;
9246
- self.tmpl.raise("error-item", [self]);
9247
  if (self.$el.length !== 0){
9248
  self.$el.remove();
9249
  }
9250
  return false;
9251
  }
9252
 
9253
- self.isAttached = self.$el.parent().length > 0;
9254
- self.isLoading = self.$el.is(sel.loading);
9255
- self.isLoaded = self.$el.is(sel.loaded);
9256
- self.isError = self.$el.is(sel.error);
9257
 
9258
- var data = self.$anchor.attr("data-type", self.type).data();
9259
  self.id = data.id || self.id;
9260
  self.productId = data.productId || self.productId;
9261
  self.tags = data.tags || self.tags;
9262
  self.href = data.href || self.$anchor.attr('href') || self.href;
9263
- self.src = self.$image.attr(o.src) || self.src;
9264
- self.srcset = self.$image.attr(o.srcset) || self.srcset;
9265
  self.width = parseInt(self.$image.attr("width")) || self.width;
9266
  self.height = parseInt(self.$image.attr("height")) || self.height;
9267
  self.title = self.$image.attr("title") || self.title;
@@ -9274,48 +8786,44 @@
9274
  self.exif = _obj.extend(self.exif, data.exif);
9275
  self.hasExif = true;
9276
  }
9277
- // if the caption or description are not set yet try fetching it from the html
9278
- if (_is.empty(self.caption)) self.caption = $.trim(self.$caption.find(sel.caption.title).html());
9279
- if (_is.empty(self.description)) self.description = $.trim(self.$caption.find(sel.caption.description).html());
9280
  // enforce the max lengths for the caption and description
9281
- if (_is.number(self.maxCaptionLength) && self.maxCaptionLength > 0 && !_is.empty(self.caption) && _is.string(self.caption) && self.caption.length > self.maxCaptionLength) {
9282
- self.$caption.find(sel.caption.title).html(self.caption.substr(0, self.maxCaptionLength) + "&hellip;");
9283
- }
9284
- if (_is.number(self.maxDescriptionLength) && self.maxDescriptionLength > 0 && !_is.empty(self.description) && _is.string(self.description) && self.description.length > self.maxDescriptionLength) {
9285
- self.$caption.find(sel.caption.description).html(self.description.substr(0, self.maxDescriptionLength) + "&hellip;");
9286
- }
9287
- // check if the item has an overlay
9288
- self.$overlay = self.$anchor.children(sel.overlay);
9289
- if (self.$overlay.length === 0) {
9290
- self.$overlay = $("<span/>", {"class": cls.overlay});
9291
- self.$anchor.append(self.$overlay);
9292
- self._undo.overlay = true;
9293
- }
9294
- // check if the item has a wrap
9295
- self.$wrap = self.$anchor.children(sel.wrap);
9296
- if (self.$wrap.length === 0) {
9297
- self.$wrap = $("<span/>", {"class": cls.wrap});
9298
- self.$anchor.append(self.$wrap.append(self.$image));
9299
- self._undo.wrap = true;
9300
- }
9301
- // check if the item has a loader
9302
- if (self.$el.children(sel.loader).length === 0) {
9303
- self.$el.append($("<div/>", {"class": cls.loader}));
9304
- self._undo.loader = true;
9305
  }
 
 
 
 
 
 
 
9306
  // if the image has no src url then set the placeholder
9307
  var img = self.$image.get(0);
9308
- if (_is.empty(img.src)) {
9309
- img.src = _.EMPTY_IMAGE;
9310
- self._undo.placeholder = true;
 
 
 
 
 
 
 
 
 
9311
  }
9312
- self.$el.addClass(self.getTypeClass());
9313
- if (self.hasExif){
9314
  self.$el.addClass(cls.exif);
9315
  }
9316
- if (self.isCreated && self.isAttached && !self.isLoading && !self.isLoaded && !self.isError) {
9317
  self.$el.addClass(cls.idle);
9318
  }
 
 
 
9319
  return true;
9320
  },
9321
  /**
@@ -9370,7 +8878,7 @@
9370
  * }
9371
  * });
9372
  */
9373
- var e = self.tmpl.raise("create-item", [self]);
9374
  if (!e.isDefaultPrevented()) {
9375
  self.isCreated = self.doCreateItem();
9376
  }
@@ -9391,11 +8899,42 @@
9391
  * }
9392
  * });
9393
  */
9394
- self.tmpl.raise("created-item", [self]);
9395
  }
9396
  }
9397
  return self.isCreated;
9398
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9399
  /**
9400
  * @summary Performs the actual create logic for the item.
9401
  * @memberof FooGallery.Item#
@@ -9403,10 +8942,20 @@
9403
  * @returns {boolean}
9404
  */
9405
  doCreateItem: function () {
9406
- var self = this, o = self.tmpl.opt, cls = self.cls, attr = self.attr, type = self.getTypeClass(), exif = self.hasExif ? cls.exif : "";
9407
- attr.elem["class"] = [cls.elem, type, exif, cls.idle].join(" ");
 
 
 
 
9408
 
9409
- attr.inner["class"] = cls.inner;
 
 
 
 
 
 
9410
 
9411
  var anchorClasses = [cls.anchor];
9412
  if (self.noLightbox){
@@ -9415,68 +8964,92 @@
9415
  if (self.panelHide){
9416
  anchorClasses.push(cls.panelHide);
9417
  }
9418
- attr.anchor["class"] = anchorClasses.join(" ");
9419
- attr.anchor["href"] = self.href;
9420
- attr.anchor["data-type"] = self.type;
9421
- attr.anchor["data-id"] = self.id;
9422
- attr.anchor["data-title"] = self.caption;
9423
- attr.anchor["data-description"] = self.description;
9424
- if (!_is.empty(self.tags)) {
9425
- attr.anchor["data-tags"] = JSON.stringify(self.tags);
9426
- }
9427
- if (!_is.empty(self.productId)) {
9428
- attr.anchor["data-product-id"] = self.productId;
9429
- }
9430
-
9431
- attr.image["class"] = cls.image;
9432
- attr.image[o.src] = self.src;
9433
- attr.image[o.srcset] = self.srcset;
9434
- attr.image["width"] = self.width;
9435
- attr.image["height"] = self.height;
9436
- attr.image["title"] = self.title;
9437
- attr.image["alt"] = self.alt;
9438
-
9439
- self.$el = $("<div/>").attr(attr.elem).data(_.DATA_ITEM, self);
9440
- self.$inner = $("<figure/>").attr(attr.inner).appendTo(self.$el);
9441
- self.$anchor = $("<a/>").attr(attr.anchor).appendTo(self.$inner).on("click.foogallery", {self: self}, self.onAnchorClick);
9442
- self.$overlay = $("<span/>", {"class": cls.overlay}).appendTo(self.$anchor);
9443
- self.$wrap = $("<span/>", {"class": cls.wrap}).appendTo(self.$anchor);
9444
- self.$image = $("<img/>").attr(attr.image).appendTo(self.$wrap);
9445
-
9446
- cls = self.cls.caption;
9447
- attr = self.attr.caption;
9448
- attr.elem["class"] = cls.elem;
9449
- self.$caption = $("<figcaption/>").attr(attr.elem).on("click.foogallery", {self: self}, self.onCaptionClick);
9450
- attr.inner["class"] = cls.inner;
9451
- var $inner = $("<div/>").attr(attr.inner).appendTo(self.$caption);
9452
- var hasTitle = self.showCaptionTitle && !_is.empty(self.caption), hasDesc = self.showCaptionDescription && !_is.empty(self.description);
9453
- if (hasTitle || hasDesc) {
9454
- attr.title["class"] = cls.title;
9455
- attr.description["class"] = cls.description;
9456
- if (hasTitle) {
9457
- var $title = $("<div/>").attr(attr.title), titleHtml = self.caption;
9458
- // enforce the max length for the caption
9459
- if (_is.number(self.maxCaptionLength) && self.maxCaptionLength > 0 && _is.string(self.caption) && self.caption.length > self.maxCaptionLength) {
9460
- titleHtml = self.caption.substr(0, self.maxCaptionLength) + "&hellip;";
9461
- }
9462
- $title.get(0).innerHTML = titleHtml;
9463
- $inner.append($title);
9464
- }
9465
- if (hasDesc) {
9466
- var $desc = $("<div/>").attr(attr.description), descHtml = self.description;
9467
- // enforce the max length for the description
9468
- if (_is.number(self.maxDescriptionLength) && self.maxDescriptionLength > 0 && _is.string(self.description) && self.description.length > self.maxDescriptionLength) {
9469
- descHtml = self.description.substr(0, self.maxDescriptionLength) + "&hellip;";
9470
- }
9471
- $desc.get(0).innerHTML = descHtml;
9472
- $inner.append($desc);
9473
- }
9474
- }
9475
- self.$caption.appendTo(self.$inner);
9476
- // check if the item has a loader
9477
- if (self.$el.find(self.sel.loader).length === 0) {
9478
- self.$el.append($("<div/>", {"class": self.cls.loader}));
9479
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9480
  return true;
9481
  },
9482
  /**
@@ -9531,13 +9104,13 @@
9531
  * }
9532
  * });
9533
  */
9534
- var e = self.tmpl.raise("append-item", [self]);
9535
  if (!e.isDefaultPrevented()) {
9536
- self.tmpl.$el.append(self.$el);
9537
- if (self.fixLayout || !self.isParsed) self.fix();
9538
  self.isAttached = true;
9539
  }
9540
  if (self.isAttached) {
 
9541
  /**
9542
  * @summary Raised after an item has appended its' elements to the template.
9543
  * @event FooGallery.Template~"appended-item.foogallery"
@@ -9554,7 +9127,7 @@
9554
  * }
9555
  * });
9556
  */
9557
- self.tmpl.raise("appended-item", [self]);
9558
  }
9559
  }
9560
  return self.isAttached;
@@ -9568,6 +9141,7 @@
9568
  detach: function () {
9569
  var self = this;
9570
  if (self.isCreated && self.isAttached) {
 
9571
  /**
9572
  * @summary Raised when an item needs to detach its' elements from the template.
9573
  * @event FooGallery.Template~"detach-item.foogallery"
@@ -9609,10 +9183,9 @@
9609
  * }
9610
  * });
9611
  */
9612
- var e = self.tmpl.raise("detach-item", [self]);
9613
  if (!e.isDefaultPrevented()) {
9614
- self.$el.detach();
9615
- if (self.fixLayout || !self.isParsed) self.unfix();
9616
  self.isAttached = false;
9617
  }
9618
  if (!self.isAttached) {
@@ -9632,7 +9205,7 @@
9632
  * }
9633
  * });
9634
  */
9635
- self.tmpl.raise("detached-item", [self]);
9636
  }
9637
  }
9638
  return !self.isAttached;
@@ -9646,20 +9219,20 @@
9646
  load: function () {
9647
  var self = this;
9648
  if (_is.promise(self._load)) return self._load;
9649
- if (!self.isCreated || !self.isAttached) return _fn.rejectWith("not created or attached");
9650
- var e = self.tmpl.raise("load-item", [self]);
9651
- if (e.isDefaultPrevented()) return _fn.rejectWith("default prevented");
9652
  var cls = self.cls, img = self.$image.get(0), placeholder = img.src;
9653
  self.isLoading = true;
9654
- self.$el.removeClass(cls.idle).removeClass(cls.loaded).removeClass(cls.error).addClass(cls.loading);
 
9655
  return self._load = $.Deferred(function (def) {
9656
  img.onload = function () {
9657
  img.onload = img.onerror = null;
9658
  self.isLoading = false;
9659
  self.isLoaded = true;
9660
  self.$el.removeClass(cls.loading).addClass(cls.loaded);
9661
- if (self.fixLayout || !self.isParsed) self.unfix();
9662
- self.tmpl.raise("loaded-item", [self]);
9663
  def.resolve(self);
9664
  };
9665
  img.onerror = function () {
@@ -9670,74 +9243,30 @@
9670
  if (_is.string(placeholder)) {
9671
  self.$image.prop("src", placeholder);
9672
  }
9673
- self.tmpl.raise("error-item", [self]);
9674
  def.reject(self);
9675
  };
9676
  // set everything in motion by setting the src
9677
- img.src = self.getThumbUrl();
 
9678
  if (img.complete){
9679
  img.onload();
9680
  }
9681
  }).promise();
9682
  },
9683
  /**
9684
- * @summary Attempts to set a inline width and height on the {@link FooGallery.Item#$image|$image} to prevent layout jumps.
9685
- * @memberof FooGallery.Item#
9686
- * @function fix
9687
- * @returns {FooGallery.Item}
9688
- */
9689
- fix: function () {
9690
- var self = this;
9691
- if (self.tmpl == null) return self;
9692
- if (self.isCreated && !self.isLoading && !self.isLoaded && !self.isError) {
9693
- var w = self.width, h = self.height, img = self.$image.get(0);
9694
- // if we have a base width and height to work with
9695
- if (!isNaN(w) && !isNaN(h) && !!img) {
9696
- // figure out the max image width and calculate the height the image should be displayed as
9697
- var width = _is.fn(self.maxWidth) ? self.maxWidth(self) : self.$image.width();
9698
- if (width <= 0) width = w;
9699
- var ratio = width / w, height = h * ratio;
9700
- // actually set the inline css on the image
9701
- self.$image.css({width: width, height: height});
9702
- }
9703
- }
9704
- return self;
9705
- },
9706
- /**
9707
- * @summary Removes any inline width and height values set on the {@link FooGallery.Item#$image|$image}.
9708
  * @memberof FooGallery.Item#
9709
- * @function unfix
9710
- * @returns {FooGallery.Item}
9711
- */
9712
- unfix: function () {
9713
- var self = this;
9714
- if (self.tmpl == null) return self;
9715
- if (self.isCreated) self.$image.css({width: '', height: ''});
9716
- return self;
9717
- },
9718
- /**
9719
- * @summary Inspect the `src` and `srcset` properties to determine which url to load for the thumb.
9720
- * @memberof FooGallery.Item#
9721
- * @function getThumbSrc
9722
- * @param {number} renderWidth - The rendered width of the image to fetch the url for.
9723
- * @param {number} renderHeight - The rendered height of the image to fetch the url for.
9724
- * @returns {string}
9725
- */
9726
- getThumbSrc: function(renderWidth, renderHeight){
9727
- return _utils.src(this.src, this.srcset, this.width, this.height, renderWidth, renderHeight);
9728
- },
9729
- /**
9730
- * @summary Inspect the `src` and `srcset` properties to determine which url to load for the thumb.
9731
- * @memberof FooGallery.Item#
9732
- * @function getThumbUrl
9733
- * @param {boolean} [refresh=false] - Whether or not to force refreshing of the cached value.
9734
  * @returns {string}
9735
  */
9736
- getThumbUrl: function (refresh) {
9737
- refresh = _is.boolean(refresh) ? refresh : false;
9738
- var self = this;
9739
- if (!refresh && _is.string(self._thumbUrl)) return self._thumbUrl;
9740
- return self._thumbUrl = self.getThumbSrc(self.$anchor.innerWidth(), self.$anchor.innerHeight());
9741
  },
9742
  /**
9743
  * @summary Gets the type specific CSS class for the item.
@@ -9746,7 +9275,7 @@
9746
  * @returns {string}
9747
  */
9748
  getTypeClass: function(){
9749
- return this.cls.types.hasOwnProperty(this.type) ? this.cls.types[this.type] : "";
9750
  },
9751
  /**
9752
  * @summary Scroll the item into the center of the viewport.
@@ -9756,40 +9285,15 @@
9756
  scrollTo: function (align) {
9757
  var self = this;
9758
  if (self.isAttached) {
9759
- var ib = self.bounds(), vb = _utils.getViewportBounds();
9760
- switch (align) {
9761
- case "top": // attempts to center the item horizontally but aligns the top with the middle of the viewport
9762
- ib.left += (ib.width / 2) - (vb.width / 2);
9763
- ib.top -= (vb.height / 5);
9764
- break;
9765
- default: // attempts to center the item in the viewport
9766
- ib.left += (ib.width / 2) - (vb.width / 2);
9767
- ib.top += (ib.height / 2) - (vb.height / 2);
9768
- break;
9769
  }
9770
- window.scrollTo(ib.left, ib.top);
9771
  }
9772
  return self;
9773
  },
9774
- /**
9775
- * @summary Get the bounds for the item.
9776
- * @memberof FooGallery.Item#
9777
- * @function bounds
9778
- * @returns {?FooGallery.utils.Bounds}
9779
- */
9780
- bounds: function () {
9781
- return this.isAttached ? _utils.getElementBounds(this.$el) : null;
9782
- },
9783
- /**
9784
- * @summary Checks if the item bounds intersects the supplied bounds.
9785
- * @memberof FooGallery.Item#
9786
- * @function intersects
9787
- * @param {FooGallery.utils.Bounds} bounds - The bounds to check.
9788
- * @returns {boolean}
9789
- */
9790
- intersects: function (bounds) {
9791
- return this.isAttached ? this.bounds().intersects(bounds) : false;
9792
- },
9793
  /**
9794
  * @summary Updates the current state to this item.
9795
  * @memberof FooGallery.Item#
@@ -9836,7 +9340,7 @@
9836
  * @private
9837
  */
9838
  onAnchorClick: function (e) {
9839
- var self = e.data.self, evt = self.tmpl.raise("anchor-click-item", [self]);
9840
  if (evt.isDefaultPrevented()) {
9841
  e.preventDefault();
9842
  } else {
@@ -9851,26 +9355,13 @@
9851
  * @private
9852
  */
9853
  onCaptionClick: function (e) {
9854
- var self = e.data.self, evt = self.tmpl.raise("caption-click-item", [self]);
9855
  if (!evt.isDefaultPrevented() && self.$anchor.length > 0 && !$(e.target).is("a,:input")) {
9856
  self.$anchor.get(0).click();
9857
  }
9858
  }
9859
  });
9860
 
9861
- /**
9862
- * @summary Called when setting an items' image size to prevent layout jumps.
9863
- * @callback FooGallery.Item~maxWidthCallback
9864
- * @param {FooGallery.Item} item - The item to determine the maxWidth for.
9865
- * @returns {number} Returns the maximum width allowed for the {@link FooGallery.Item#$image|$image} element.
9866
- * @example {@caption An example of the default behavior this callback replaces would look like the below.}
9867
- * {
9868
- * "maxWidth": function(item){
9869
- * return item.$image.outerWidth();
9870
- * }
9871
- * }
9872
- */
9873
-
9874
  /**
9875
  * @summary A simple object containing an items' default values.
9876
  * @typedef {object} FooGallery.Item~Options
@@ -9886,7 +9377,6 @@
9886
  * @property {?string} [caption=null] - The caption for the image. This can contain HTML content.
9887
  * @property {?string} [description=null] - The description for the image. This can contain HTML content.
9888
  * @property {string[]} [tags=[]] - The `data-tags` attribute for the outer element.
9889
- * @property {?FooGallery.Item~maxWidthCallback} [maxWidth=null] - Called when setting an items' image size. If not supplied the images outer width is used.
9890
  * @property {number} [maxCaptionLength=0] - The max length of the title for the caption.
9891
  * @property {number} [maxDescriptionLength=0] - The max length of the description for the caption.
9892
  * @property {boolean} [showCaptionTitle=true] - Whether or not the caption title should be displayed.
@@ -9898,6 +9388,7 @@
9898
  type: "item",
9899
  id: "",
9900
  href: "",
 
9901
  src: "",
9902
  srcset: "",
9903
  width: 0,
@@ -9907,7 +9398,6 @@
9907
  caption: "",
9908
  description: "",
9909
  tags: [],
9910
- maxWidth: null,
9911
  maxCaptionLength: 0,
9912
  maxDescriptionLength: 0,
9913
  showCaptionTitle: true,
@@ -9950,6 +9440,7 @@
9950
  loading: "fg-loading",
9951
  loaded: "fg-loaded",
9952
  error: "fg-error",
 
9953
  noLightbox: "fg-no-lightbox",
9954
  panelHide: "fg-panel-hide",
9955
  types: {
@@ -10042,6 +9533,149 @@
10042
  FooGallery.utils,
10043
  FooGallery.utils.is
10044
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10045
  (function ($, _, _utils, _is) {
10046
 
10047
  _.Paging = _.Component.extend({
@@ -10066,8 +9700,9 @@
10066
  self.current = 0;
10067
  self.total = 0;
10068
  self.ctrls = [];
10069
- self._arr = [];
10070
  },
 
10071
  fromHash: function(hash){
10072
  var parsed = parseInt(hash);
10073
  return isNaN(parsed) ? null : parsed;
@@ -10080,15 +9715,17 @@
10080
  },
10081
  setState: function(state){
10082
  this.rebuild();
 
10083
  if (!!state.item && !this.contains(state.page, state.item)){
10084
  state.page = this.find(state.item);
10085
  state.page = state.page !== 0 ? state.page : 1;
 
10086
  }
10087
- this.set(state.page, false, false, true);
10088
  },
10089
  destroy: function () {
10090
  var self = this;
10091
- self._arr.splice(0, self._arr.length);
10092
  $.each(self.ctrls.splice(0, self.ctrls.length), function (i, control) {
10093
  control.destroy();
10094
  });
@@ -10098,7 +9735,7 @@
10098
  var self = this, items = self.tmpl.items.available();
10099
  self.total = self.size > 0 && items.length > 0 ? Math.ceil(items.length / self.size) : 1;
10100
  for (var i = 0; i < self.total; i++) {
10101
- self._arr.push(items.splice(0, self.size));
10102
  }
10103
  if (self.total > 1 && _.paging.hasCtrl(self.type)) {
10104
  var pos = self.position, top, bottom;
@@ -10122,21 +9759,18 @@
10122
  var self = this;
10123
  self.current = 0;
10124
  self.total = 0;
10125
- self._arr.splice(0, self._arr.length);
10126
  $.each(self.ctrls.splice(0, self.ctrls.length), function (i, control) {
10127
  control.destroy();
10128
  });
10129
  self.build();
10130
  },
10131
  all: function () {
10132
- return this._arr.slice();
10133
  },
10134
  available: function () {
10135
  return this.get(this.current);
10136
  },
10137
- items: function(){
10138
- return this.get(this.current);
10139
- },
10140
  controls: function (pageNumber) {
10141
  var self = this;
10142
  if (self.isValid(pageNumber)) {
@@ -10154,22 +9788,32 @@
10154
  create: function (pageNumber, isFilter) {
10155
  var self = this;
10156
  pageNumber = self.number(pageNumber);
10157
- var index = pageNumber - 1;
10158
- self.tmpl.items.detach(self.tmpl.items.all());
 
 
 
 
 
 
 
 
10159
  self.current = pageNumber;
10160
- self.tmpl.items.create(self._arr[index], true);
 
10161
  },
10162
  get: function (pageNumber) {
10163
  var self = this;
10164
  if (self.isValid(pageNumber)) {
10165
  pageNumber = self.number(pageNumber);
10166
- return self._arr[pageNumber - 1];
10167
  }
10168
  return [];
10169
  },
10170
  set: function (pageNumber, scroll, updateState, isFilter) {
10171
  var self = this;
10172
  if (self.isValid(pageNumber)) {
 
10173
  var num = self.number(pageNumber), state;
10174
  if (num !== self.current) {
10175
  var prev = self.current, setPage = function () {
@@ -10179,21 +9823,21 @@
10179
  state = self.tmpl.state.get();
10180
  self.tmpl.state.update(state, self.pushOrReplace);
10181
  }
10182
- self.controls(pageNumber);
10183
  self.create(num, isFilter);
10184
  if (updateState) {
10185
  state = self.tmpl.state.get();
10186
  self.tmpl.state.update(state, self.pushOrReplace);
10187
  }
 
10188
  if (self.scrollToTop && _is.boolean(scroll) ? scroll : false) {
10189
  var page = self.get(self.current);
10190
  if (page.length > 0) {
10191
  page[0].scrollTo("top");
10192
  }
10193
  }
10194
- self.tmpl.raise("after-page-change", [self.current, prev, isFilter]);
10195
  };
10196
- var e = self.tmpl.raise("before-page-change", [self.current, num, setPage, isFilter]);
10197
  if (e.isDefaultPrevented()) return false;
10198
  setPage();
10199
  return true;
@@ -10203,8 +9847,8 @@
10203
  },
10204
  find: function (item) {
10205
  var self = this;
10206
- for (var i = 0, l = self._arr.length; i < l; i++) {
10207
- if (_utils.inArray(item, self._arr[i]) !== -1) {
10208
  return i + 1;
10209
  }
10210
  }
@@ -10218,7 +9862,7 @@
10218
  this.goto(1);
10219
  },
10220
  last: function () {
10221
- this.goto(this._arr.length);
10222
  },
10223
  prev: function () {
10224
  this.goto(this.current - 1);
@@ -10227,10 +9871,7 @@
10227
  this.goto(this.current + 1);
10228
  },
10229
  goto: function (pageNumber) {
10230
- var self = this;
10231
- if (self.set(pageNumber, true)) {
10232
- self.tmpl.loadAvailable();
10233
- }
10234
  }
10235
  });
10236
 
@@ -10241,19 +9882,37 @@
10241
  self.pages = parent;
10242
  self.position = position;
10243
  self.$container = null;
 
 
10244
  },
10245
  create: function () {
10246
  var self = this;
10247
- self.$container = $("<nav/>", {"class": self.pages.cls.container}).addClass(self.pages.theme);
 
 
 
 
 
 
 
 
 
10248
  return true;
10249
  },
10250
  destroy: function () {
10251
  var self = this;
10252
- self.$container.remove();
 
 
 
 
 
 
10253
  self.$container = null;
10254
  },
10255
  append: function () {
10256
  var self = this;
 
10257
  if (self.position === "top") {
10258
  self.$container.insertBefore(self.tmpl.$el);
10259
  } else {
@@ -10288,38 +9947,32 @@
10288
  _.DotsControl = _.PagingControl.extend({
10289
  construct: function(template, parent, position){
10290
  this._super(template, parent, position);
10291
- this.$container = $();
10292
- this.$list = $();
10293
- this.$items = $();
10294
  },
10295
  create: function(){
10296
- var self = this, cls = self.pages.cls, il8n = self.pages.il8n,
10297
- items = [], $list = $("<ul/>", {"class": cls.list});
10298
-
10299
- for (var i = 0, l = self.pages.total, $item; i < l; i++){
10300
- items.push($item = self.createItem(i + 1, il8n.page));
10301
- $list.append($item);
10302
- }
10303
- self.$list = $list;
10304
- self.$container = $("<nav/>", {"class": cls.container}).addClass(self.pages.theme).append($list);
10305
- self.$items = $($.map(items, function($item){ return $item.get(); }));
10306
- return true;
10307
- },
10308
- append: function(){
10309
  var self = this;
10310
- if (self.position === "top"){
10311
- self.$container.insertBefore(self.tmpl.$el);
10312
- } else {
10313
- self.$container.insertAfter(self.tmpl.$el);
 
 
 
 
 
 
 
 
10314
  }
 
10315
  },
10316
  destroy: function(){
10317
  var self = this, sel = self.pages.sel;
10318
  self.$list.find(sel.link).off("click.foogallery", self.onLinkClick);
10319
- self.$container.remove();
10320
- self.$container = $();
10321
  self.$list = $();
10322
  self.$items = $();
 
10323
  },
10324
  update: function(pageNumber){
10325
  this.setSelected(pageNumber - 1);
@@ -10390,7 +10043,6 @@
10390
  // this check should not be required as we use the CSS pointer-events: none; property on disabled links but just in case test for the class here
10391
  if (!$(this).closest(sel.item).is(sel.disabled)){
10392
  self.pages.set(page, true);
10393
- self.tmpl.loadAvailable();
10394
  }
10395
  }
10396
  });
@@ -10435,384 +10087,84 @@
10435
 
10436
  /**
10437
  * @summary The Masonry template for FooGallery.
10438
- * @memberof FooGallery
10439
  * @constructs MasonryTemplate
10440
- * @param {FooGallery.MasonryTemplate~Options} [options] - The options for the template.
10441
  * @param {(jQuery|HTMLElement)} [element] - The jQuery object or HTMLElement of the template. If not supplied one will be created within the `parent` element supplied to the {@link FooGallery.Template#initialize|initialize} method.
10442
  * @augments FooGallery.Template
10443
  * @borrows FooGallery.utils.Class.extend as extend
10444
  * @borrows FooGallery.utils.Class.override as override
10445
  * @description This template makes use of the popular [Masonry library](http://masonry.desandro.com/) to perform its layout. It supports two basic layout types, fixed and column based.
10446
- * @example {@caption The below shows the simplest way to create a Masonry gallery using this template, by simply initializing it on pre-existing elements.}{@lang html}
10447
- * <!-- The container element for the template -->
10448
- * <div id="gallery-1" class="foogallery fg-masonry">
10449
- * <!-- Used by the masonry to handle responsive sizing -->
10450
- * <div class="fg-column-width"></div>
10451
- * <div class="fg-gutter-width"></div>
10452
- * <!-- A single item -->
10453
- * <div class="fg-item" data-id="[item.id]">
10454
- * <div class="fg-item-inner">
10455
- * <a class="fg-thumb" href="[item.href]">
10456
- * <img class="fg-image" width="[item.width]" height="[item.height]"
10457
- * title="[item.title]" alt="[item.description]"
10458
- * data-src="[item.src]"
10459
- * data-srcset="[item.srcset]" />
10460
- * <!-- Optional caption markup -->
10461
- * <div class="fg-caption">
10462
- * <div class="fg-caption-inner">
10463
- * <div class="fg-caption-title">[item.title]</div>
10464
- * <div class="fg-caption-desc">[item.description]</div>
10465
- * </div>
10466
- * </div>
10467
- * </a>
10468
- * </div>
10469
- * </div>
10470
- * <!-- Any number of additional items -->
10471
- * </div>
10472
- * <script>
10473
- * jQuery(function($){
10474
- * $("#gallery-1").foogallery();
10475
- * });
10476
- * </script>
10477
- * @example {@caption Options can be supplied directly to the `.foogallery()` method or by supplying them using the `data-foogallery` attribute. If supplied using the attribute the value must follow [valid JSON syntax](http://en.wikipedia.org/wiki/JSON#Data_types.2C_syntax_and_example) including quoted property names.}{@lang html}
10478
- * <!-- Supplying the options using the attribute -->
10479
- * <div id="gallery-1" class="foogallery fg-masonry" data-foogallery='{"lazy": true, "template": {"layout": "col4"}}'>
10480
- * <!-- Snip -->
10481
- * </div>
10482
- * <script>
10483
- * jQuery(function($){
10484
- * // Supply the options directly to the method
10485
- * $("#gallery-1").foogallery({
10486
- * lazy: true,
10487
- * template: {
10488
- * layout: "col4"
10489
- * }
10490
- * });
10491
- * });
10492
- * </script>
10493
- * @example {@caption If required the templates container element can be created from just options however a parent element must be supplied to the `initialize` method. The created gallery container is appended to the supplied parent. When creating galleries this way all items must be supplied using the `items` option.}{@lang html}
10494
- * <div id="gallery-parent"></div>
10495
- * <script>
10496
- * jQuery(function($){
10497
- * // Create the template using just options
10498
- * var tmpl = FooGallery.template.make({
10499
- * type: "masonry", // required when creating from options
10500
- * lazy: true,
10501
- * template: {
10502
- * layout: "col4"
10503
- * },
10504
- * items: [{
10505
- * id: "item-1",
10506
- * href: "https://url-to-your/full-image.jpg",
10507
- * src: "https://url-to-your/thumb-image.jpg",
10508
- * width: 250,
10509
- * height: 300,
10510
- * srcset: "https://url-to-your/thumb-image@2x.jpg 500w,https://url-to-your/thumb-image@3x.jpg 750w",
10511
- * title: "Short Item Title",
10512
- * description: "Longer item description but still fairly brief."
10513
- * },{
10514
- * // Any number of additional items
10515
- * }]
10516
- * });
10517
- * // Supply the parent element to the initialize method
10518
- * tmpl.initialize("#gallery-parent");
10519
- * });
10520
- * </script>
10521
  */
10522
  _.MasonryTemplate = _.Template.extend(/** @lends FooGallery.MasonryTemplate */{
10523
  construct: function(options, element){
10524
- this._super(options, element);
10525
- /**
10526
- * @summary The current Masonry instance for the template.
10527
- * @memberof FooGallery.MasonryTemplate#
10528
- * @name masonry
10529
- * @type {?Masonry}
10530
- * @description This value is `null` until after the {@link FooGallery.Template~event:"pre-init.foogallery"|`pre-init.foogallery`} event has been raised.
10531
- */
10532
- this.masonry = null;
10533
- /**
10534
- *
10535
- * @type {?HTMLStyleElement}
10536
- */
10537
- this.style = null;
10538
- this.$columnWidth = null;
10539
- /**
10540
- * @summary The CSS classes for the Masonry template.
10541
- * @memberof FooGallery.MasonryTemplate#
10542
- * @name cls
10543
- * @type {FooGallery.MasonryTemplate~CSSClasses}
10544
- */
10545
- /**
10546
- * @summary The CSS selectors for the Masonry template.
10547
- * @memberof FooGallery.MasonryTemplate#
10548
- * @name sel
10549
- * @type {FooGallery.MasonryTemplate~CSSSelectors}
10550
- */
10551
- },
10552
- /**
10553
- * @summary Creates or gets the CSS stylesheet element for this template instance.
10554
- * @memberof FooGallery.MasonryTemplate#
10555
- * @function getStylesheet
10556
- * @returns {CSSStyleSheet}
10557
- */
10558
- getStylesheet: function(){
10559
- var self = this;
10560
- if (self.style === null){
10561
- self.style = document.createElement("style");
10562
- self.style.appendChild(document.createTextNode(""));
10563
- document.head.appendChild(self.style);
10564
- }
10565
- return self.style.sheet;
10566
- },
10567
- delayedLayout: function(){
10568
  var self = this;
10569
- if (self._delayedLayout) clearTimeout(self._delayedLayout);
10570
- self._delayedLayout = setTimeout(function () {
10571
- self._delayedLayout = null;
10572
- self.masonry.layout();
10573
- }, 20);
10574
- },
10575
- /**
10576
- * @summary Listens for the {@link FooGallery.Template~event:"pre-init.foogallery"|`pre-init.foogallery`} event.
10577
- * @memberof FooGallery.MasonryTemplate#
10578
- * @function onPreInit
10579
- * @param {jQuery.Event} event - The jQuery.Event object for the event.
10580
- * @param {FooGallery.MasonryTemplate} self - The current instance of the template.
10581
- * @this {HTMLElement} The templates container element that the event was raised on.
10582
- * @description Performs all pre-initialization work required by the Masonry template, specifically handling the `layout` option and building up the required Masonry options.
10583
- * @protected
10584
- */
10585
- onPreInit: function(event, self){
10586
- var sel = self.sel, cls = self.cls;
10587
- // first update the templates classes to include one property containing all layouts
10588
- cls.layouts = $.map(cls.layout, function(value){
10589
- return value;
10590
- }).join(" ");
10591
- // check if the layout is supplied as a CSS class
10592
- var layouts = $.map(cls.layout, function(value, key){
10593
- return {key: key, value: value};
10594
- });
10595
- for (var i =0, l = layouts.length; i < l; i++){
10596
- if (self.$el.hasClass(layouts[i].value)){
10597
- self.template.layout = layouts[i].key;
10598
- break;
10599
- }
10600
- }
10601
- // check if the supplied layout is supported
10602
- if (!_is.string(cls.layout[self.template.layout])){
10603
- // if not set the default
10604
- self.template.layout = "col4";
10605
- }
10606
- // configure the base masonry options depending on the layout
10607
- var fixed = self.template.layout === "fixed", sheet, rule;
10608
  self.template.isFitWidth = fixed;
10609
  self.template.percentPosition = !fixed;
10610
  self.template.transitionDuration = 0;
10611
  self.template.itemSelector = sel.item.elem;
10612
- // remove any layout classes and then apply only the current to the container
10613
- self.$el.removeClass(cls.layouts).addClass(cls.layout[self.template.layout]);
10614
-
10615
  if (!fixed){
10616
- // if the gutterWidth element does not exist create it
10617
- if (self.$el.find(sel.gutterWidth).length === 0){
10618
- self.$el.prepend($("<div/>").addClass(cls.gutterWidth));
10619
- }
10620
  self.template.gutter = sel.gutterWidth;
 
10621
  }
10622
-
10623
- // if the columnWidth element does not exist create it
10624
- if (self.$el.find(sel.columnWidth).length === 0){
10625
- self.$el.prepend($("<div/>").addClass(cls.columnWidth));
10626
- }
10627
- if (fixed && _is.number(self.template.columnWidth)){
10628
- var $columnWidth = self.$el.find(sel.columnWidth).width(self.template.columnWidth);
10629
- sheet = self.getStylesheet();
10630
- rule = '#' + self.id + sel.container + ' ' + sel.item.elem + ' { width: ' + $columnWidth.outerWidth() + 'px; }';
10631
- sheet.insertRule(rule , 0);
10632
- }
10633
- self.template.columnWidth = sel.columnWidth;
10634
-
10635
- // if this is a fixed layout and a number value is supplied as the gutter option then
10636
- // make sure to vertically space the items using a CSS class and the same value
10637
- if (fixed && _is.number(self.template.gutter)){
10638
- sheet = self.getStylesheet();
10639
- rule = '#' + self.id + sel.container + ' ' + sel.item.elem + ' { margin-bottom: ' + self.template.gutter + 'px; }';
10640
- sheet.insertRule(rule , 0);
10641
- }
10642
- self.masonry = new Masonry( self.$el.get(0), self.template );
10643
- },
10644
- onPostInit: function(event, self){
10645
- self.masonry.layout();
10646
- },
10647
- onFirstLoad: function(event, self){
10648
- self.masonry.layout();
10649
- },
10650
- onReady: function(event, self){
10651
- self.delayedLayout();
10652
- },
10653
- onDestroy: function(event, self){
10654
- if (self._delayedLayout) clearTimeout(self._delayedLayout);
10655
- self.$el.find(self.sel.columnWidth).remove();
10656
- self.$el.find(self.sel.gutterWidth).remove();
10657
- if (self.style && self.style.parentNode){
10658
- self.style.parentNode.removeChild(self.style);
10659
- }
10660
  },
10661
- onDestroyed: function(event, self){
 
10662
  if (self.masonry instanceof Masonry){
10663
  self.masonry.destroy();
10664
  }
10665
  },
10666
- onLayout: function(event, self){
10667
- self.masonry.layout();
10668
  },
10669
- /**
10670
- * @summary Listens for the {@link FooGallery.Template~event:"parsed-items.foogallery"|`parsed-items.foogallery`} event.
10671
- * @memberof FooGallery.MasonryTemplate#
10672
- * @function onParsedItems
10673
- * @param {jQuery.Event} event - The jQuery.Event object for the event.
10674
- * @param {FooGallery.MasonryTemplate} self - The current instance of the template.
10675
- * @param {FooGallery.Item[]} items - The array of items that were parsed.
10676
- * @this {HTMLElement} The templates container element that the event was raised on.
10677
- * @description Instructs Masonry to perform a layout operation whenever items are parsed.
10678
- * @protected
10679
- */
10680
- onParsedItems: function(event, self, items){
10681
- self.masonry.layout();
10682
  },
10683
- /**
10684
- * @summary Listens for the {@link FooGallery.Template~event:"appended-items.foogallery"|`appended-items.foogallery`} event.
10685
- * @memberof FooGallery.MasonryTemplate#
10686
- * @function onAppendedItems
10687
- * @param {jQuery.Event} event - The jQuery.Event object for the event.
10688
- * @param {FooGallery.MasonryTemplate} self - The current instance of the template.
10689
- * @param {FooGallery.Item[]} items - The array of items that were appended.
10690
- * @this {HTMLElement} The templates container element that the event was raised on.
10691
- * @description Instructs Masonry to perform a layout operation whenever items are appended.
10692
- * @protected
10693
- */
10694
- onAppendedItems: function(event, self, items){
10695
- items = self.items.jquerify(items);
10696
- items = self.masonry.addItems(items);
10697
  // add and layout the new items with no transitions
10698
- self.masonry.layoutItems(items, true);
10699
  },
10700
- /**
10701
- * @summary Listens for the {@link FooGallery.Template~event:"detach-item.foogallery"|`detach-item.foogallery`} event.
10702
- * @memberof FooGallery.MasonryTemplate#
10703
- * @function onDetachItem
10704
- * @param {jQuery.Event} event - The jQuery.Event object for the event.
10705
- * @param {FooGallery.MasonryTemplate} self - The current instance of the template.
10706
- * @param {FooGallery.Item} item - The item to detach.
10707
- * @this {HTMLElement} The templates container element that the event was raised on.
10708
- * @description If not already overridden this method will override the default logic to detach an item and replace it with Masonry specific logic.
10709
- * @protected
10710
- */
10711
- onDetachItem: function(event, self, item){
10712
  if (!event.isDefaultPrevented()){
10713
  event.preventDefault();
10714
- self.masonry.remove(item.$el);
 
10715
  item.isAttached = false;
10716
- item.unfix();
10717
  }
10718
- },
10719
- /**
10720
- * @summary Listens for the {@link FooGallery.Template~event:"detached-items.foogallery"|`detached-items.foogallery`} event.
10721
- * @memberof FooGallery.MasonryTemplate#
10722
- * @function onDetachedItems
10723
- * @param {jQuery.Event} event - The jQuery.Event object for the event.
10724
- * @param {FooGallery.MasonryTemplate} self - The current instance of the template.
10725
- * @param {FooGallery.Item[]} items - The array of items that were detached.
10726
- * @this {HTMLElement} The templates container element that the event was raised on.
10727
- * @description Instructs Masonry to perform a layout operation whenever items are detached.
10728
- * @protected
10729
- */
10730
- onDetachedItems: function(event, self, items){
10731
- self.masonry.layout();
10732
- },
10733
- onLoadedItems: function(event, self, items){
10734
- self.masonry.layout();
10735
  }
10736
  });
10737
 
10738
  _.template.register("masonry", _.MasonryTemplate, {
10739
- fixLayout: true,
10740
- template: {
10741
- initLayout: false,
10742
- isInitLayout: false,
10743
- layout: "col4"
10744
- }
10745
  }, {
10746
  container: "foogallery fg-masonry",
10747
  columnWidth: "fg-column-width",
10748
- gutterWidth: "fg-gutter-width",
10749
- layout: {
10750
- fixed: "fg-masonry-fixed",
10751
- col2: "fg-masonry-2col",
10752
- col3: "fg-masonry-3col",
10753
- col4: "fg-masonry-4col",
10754
- col5: "fg-masonry-5col"
10755
- }
10756
  });
10757
 
10758
- /**
10759
- * @summary An object containing the default options for the Masonry template.
10760
- * @typedef {FooGallery.Template~Options} FooGallery.MasonryTemplate~Options
10761
- * @property {object} [template] - An object containing the custom options for the Masonry template.
10762
- * @property {string} [template.layout="col4"] - The layout to use for the template; "fixed", "col2", "col3", "col4" or "col5".
10763
- * @property {FooGallery.MasonryTemplate~CSSClasses} [cls] - An object containing all CSS classes for the Masonry template.
10764
- * @description Apart from the `layout` option the template object is identical to the standard {@link https://masonry.desandro.com/options.html|Masonry options}.
10765
- * Note that the template overrides and sets its' own values for the following options based primarily on the `layout` value; `itemSelector`, `columnWidth`, `gutter`, `isFitWidth`, `percentPosition` and `transitionDuration`.
10766
- * The `layout` value can be classed into two categories, fixed width and column type layouts. You can see in the examples below the options the template sets for each of these types of layouts.
10767
- * @example {@caption For both fixed and column layouts the template sets the below option values.}
10768
- * {
10769
- * "itemSelector": ".fg-item", // this selector is generated from the classes.item.elem value.
10770
- * "columnWidth": ".fg-column-width", // this selector is generated from the classes.masonry.columnWidth value.
10771
- * "gutter": ".fg-gutter-width", // this selector is generated from the classes.masonry.gutterWidth value.
10772
- * "transitionDuration": 0 // disables masonry's inline transitions to prevent them overriding our CSS class transitions
10773
- * }
10774
- * @example {@caption For fixed layouts (`"fixed"`) the template sets the below options. If a number was supplied for the `columnWidth` or `gutter` options it is applied to the relevant elements before they are replaced by the selector seen above.}
10775
- * {
10776
- * "isFitWidth": true,
10777
- * "percentPosition": false
10778
- * }
10779
- * @example {@caption For column layouts (`"col2","col3","col4","col5"`) the template sets the below options.}
10780
- * {
10781
- * "isFitWidth": false,
10782
- * "percentPosition": true
10783
- * }
10784
- */
10785
-
10786
- /**
10787
- * @summary An object containing the default CSS classes for the Masonry template.
10788
- * @typedef {FooGallery.Template~CSSClasses} FooGallery.MasonryTemplate~CSSClasses
10789
- * @property {string} [container="foogallery fg-masonry"] - The base CSS class names to apply to the container element.
10790
- * @property {string} [columnWidth="fg-column-width"] - The CSS class name to apply to the Masonry column sizer element.
10791
- * @property {string} [gutterWidth="fg-gutter-width"] - The CSS class name to apply to the Masonry gutter sizer element.
10792
- * @property {object} [layout] - An object containing all layout classes.
10793
- * @property {string} [layout.fixed="fg-masonry-fixed"] - The CSS class name for a fixed width layout.
10794
- * @property {string} [layout.col2="fg-masonry-2col"] - The CSS class name for a two column layout.
10795
- * @property {string} [layout.col3="fg-masonry-3col"] - The CSS class name for a three column layout.
10796
- * @property {string} [layout.col4="fg-masonry-4col"] - The CSS class name for a four column layout.
10797
- * @property {string} [layout.col5="fg-masonry-5col"] - The CSS class name for a five column layout.
10798
- * @property {string} [layouts="fg-masonry-fixed fg-masonry-2col fg-masonry-3col fg-masonry-4col fg-masonry-5col"] - A space delimited string of all CSS class names from the `layout` object.
10799
- */
10800
-
10801
- /**
10802
- * @summary An object containing all CSS selectors for the Masonry template.
10803
- * @typedef {FooGallery.Template~CSSSelectors} FooGallery.MasonryTemplate~CSSSelectors
10804
- * @property {string} [container=".foogallery.fg-masonry"] - The CSS selector for the container element.
10805
- * @property {string} [columnWidth=".fg-column-width"] - The CSS selector for the Masonry column sizer element.
10806
- * @property {string} [gutterWidth=".fg-gutter-width"] - The CSS selector for the Masonry gutter sizer element.
10807
- * @property {object} [layout] - An object containing all layout CSS selectors.
10808
- * @property {string} [layout.fixed=".fg-masonry-fixed"] - The CSS selector for a fixed width layout.
10809
- * @property {string} [layout.col2=".fg-masonry-2col"] - The CSS selector for a two column layout.
10810
- * @property {string} [layout.col3=".fg-masonry-3col"] - The CSS selector for a three column layout.
10811
- * @property {string} [layout.col4=".fg-masonry-4col"] - The CSS selector for a four column layout.
10812
- * @property {string} [layout.col5=".fg-masonry-5col"] - The CSS selector for a five column layout.
10813
- * @description This object is automatically generated from a {@link FooGallery.MasonryTemplate~CSSClasses|classes} object and its properties mirror those except the class name values are converted into CSS selectors.
10814
- */
10815
-
10816
  })(
10817
  FooGallery.$,
10818
  FooGallery,
@@ -10823,262 +10175,221 @@
10823
 
10824
  _.Justified = _utils.Class.extend({
10825
  construct: function(template, options){
10826
- this.tmpl = template;
10827
- this.$el = template.$el;
10828
- this.options = $.extend(true, {}, _.Justified.defaults, options);
10829
- this._items = [];
 
 
 
 
10830
  },
10831
  init: function(){
10832
  var self = this;
10833
- if (_is.string(self.options.maxRowHeight)){
10834
- if (self.options.maxRowHeight.indexOf('%')){
10835
- self.options.maxRowHeight = self.options.rowHeight * (parseInt(self.options.maxRowHeight) / 100);
10836
- } else {
10837
- self.options.maxRowHeight = parseInt(self.options.maxRowHeight);
10838
- }
10839
- }
10840
  },
10841
  destroy: function(){
10842
  this.$el.removeAttr("style");
10843
  },
10844
- parse: function(){
10845
- var self = this;
10846
- return self._items = $.map(self.tmpl.getItems(), function(item, i){
10847
- return {
10848
- index: i,
10849
- width: item.width,
10850
- height: item.height,
10851
- top: 0,
10852
- left: 0,
10853
- $item: item.$el
10854
- };
10855
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
10856
  },
10857
- getMaxRowHeight: function() {
10858
  var self = this;
10859
- if (_is.string(self.options.maxRowHeight)){
10860
- if (self.options.maxRowHeight.indexOf('%')){
10861
- self.options.maxRowHeight = self.options.rowHeight * (parseInt(self.options.maxRowHeight) / 100);
10862
- } else {
10863
- self.options.maxRowHeight = parseInt(self.options.maxRowHeight);
 
 
 
 
 
10864
  }
10865
  }
10866
- return _is.number(self.options.maxRowHeight) ? self.options.maxRowHeight : self.options.rowHeight;
10867
- },
10868
- getContainerWidth: function(){
10869
- var self = this, visible = self.$el.is(':visible');
10870
- if (!visible){
10871
- return self.$el.parents(':visible:first').innerWidth();
10872
- }
10873
- return self.$el.width();
10874
- },
10875
- layout: function(){
10876
- this.parse();
10877
-
10878
- var self = this,
10879
- height = 0,
10880
- maxWidth = self.getContainerWidth(),
10881
- maxHeight = self.getMaxRowHeight(),
10882
- rows = self.rows(maxWidth, maxHeight);
10883
-
10884
- $.each(rows, function(ri, row){
10885
- if (row.visible){
10886
- if (ri > 0) height += self.options.margins;
10887
- height += row.height;
10888
- }
10889
- self.render(row);
10890
- });
10891
- self.$el.height(height);
10892
  },
10893
  render: function(row){
10894
- for (var j = 0, jl = row.items.length, item; j < jl; j++){
10895
- item = row.items[j];
10896
- if (row.visible){
10897
- item.$item.css({
10898
- width: item.width,
10899
- height: item.height,
10900
- top: item.top,
10901
- left: item.left,
10902
- display: "",
10903
- maxHeight: this.options.maxRowHeight > 0 ? this.options.maxRowHeight : ""
10904
- }).addClass("fg-positioned");
10905
- } else {
10906
- item.$item.css("display", "none");
 
 
 
 
 
 
 
 
 
10907
  }
10908
- }
10909
  },
10910
  justify: function(row, top, maxWidth, maxHeight){
10911
  var self = this,
10912
- margins = self.options.margins * (row.items.length - 1),
10913
- max = maxWidth - margins;
 
 
10914
 
10915
- var w_ratio = max / row.width;
10916
- row.width = row.width * w_ratio;
10917
  row.height = row.height * w_ratio;
10918
- row.top = top;
10919
-
10920
- if (row.height > maxHeight){
10921
- row.height = maxHeight;
10922
- }
10923
-
10924
- row.left = 0;
10925
- if (row.width < max){
10926
- // here I'm not sure if I should center, left or right align a row that cannot be displayed at 100% width
10927
- row.left = (max - row.width) / 2;
10928
- }
10929
- row.width += margins;
10930
 
10931
- var left = row.left;
10932
- for (var i = 0, l = row.items.length, item; i < l; i++){
10933
- if (i > 0) left += self.options.margins;
10934
- item = row.items[i];
10935
- item.left = left;
10936
- item.top = top;
10937
- item.width = item.width * w_ratio;
10938
- item.height = item.height * w_ratio;
10939
- if (item.height > maxHeight){
10940
- item.height = maxHeight;
10941
- }
10942
- left += item.width;
10943
  }
10944
 
10945
- return row.height;
10946
- },
10947
- position: function(row, top, maxWidth, align){
10948
- var self = this,
10949
- margins = self.options.margins * (row.items.length - 1),
10950
- max = maxWidth - margins;
10951
-
10952
  row.top = top;
 
10953
  row.left = 0;
10954
- if (row.width < max){
10955
- switch (align){
10956
- case "center":
10957
- row.left = (max - row.width) / 2;
10958
- break;
10959
- case "right":
10960
- row.left = max - row.width;
10961
- break;
10962
  }
10963
  }
 
10964
  row.width += margins;
10965
 
10966
  var left = row.left;
10967
- for (var i = 0, l = row.items.length, item; i < l; i++){
10968
- if (i > 0) left += self.options.margins;
10969
- item = row.items[i];
10970
  item.left = left;
10971
  item.top = top;
 
 
 
10972
  left += item.width;
10973
- }
10974
 
10975
  return row.height;
10976
  },
10977
- lastRow: function(row, top, maxWidth, maxHeight){
10978
- var self = this,
10979
- margins = self.options.margins * (row.items.length - 1),
10980
- max = maxWidth - margins,
10981
- threshold = row.width / max > self.options.justifyThreshold;
10982
-
10983
- switch (self.options.lastRow){
10984
- case "hide":
10985
- if (threshold){
10986
- self.justify(row, top, maxWidth, maxHeight);
10987
- } else {
10988
- row.visible = false;
10989
- }
10990
- break;
10991
- case "justify":
10992
- self.justify(row, top, maxWidth, maxHeight);
10993
- break;
10994
- case "nojustify":
10995
- if (threshold){
10996
- self.justify(row, top, maxWidth, maxHeight);
10997
- } else {
10998
- self.position(row, top, maxWidth, "left");
10999
- }
11000
- break;
11001
- case "left":
11002
- case "center":
11003
- case "right":
11004
- if (threshold){
11005
- self.justify(row, top, maxWidth, maxHeight);
11006
- } else {
11007
- self.position(row, top, maxWidth, self.options.lastRow);
11008
- }
11009
- break;
11010
- }
11011
- },
11012
- items: function(){
11013
- return $.map(this._items, function(item){
11014
- return {
11015
- index: item.index,
11016
- width: item.width,
11017
- height: item.height,
11018
- $item: item.$item,
11019
- top: item.top,
11020
- left: item.left,
11021
- };
11022
- });
11023
- },
11024
- rows: function(maxWidth, maxHeight){
11025
  var self = this,
11026
- items = self.items(),
11027
- rows = [],
11028
- index = -1;
 
11029
 
11030
- function create(){
11031
- var row = {
11032
  index: ++index,
11033
  visible: true,
11034
  width: 0,
11035
- height: self.options.rowHeight,
11036
  top: 0,
11037
  left: 0,
11038
  items: []
11039
  };
11040
- // push the row into the result collection now
11041
- rows.push(row);
11042
- return row;
11043
  }
11044
 
11045
- var row = create(), top = 0, tmp = 0;
11046
- for (var i = 0, il = items.length, item; i < il; i++){
11047
- item = items[i];
11048
- // first make all the items match the row height
11049
- if (item.height != self.options.rowHeight){
11050
- var ratio = self.options.rowHeight / item.height;
11051
- item.height = item.height * ratio;
11052
- item.width = item.width * ratio;
11053
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11054
 
11055
- if (tmp + item.width > maxWidth && i > 0){
11056
- // adding this item to the row would exceed the max width
11057
- if (rows.length > 1) top += self.options.margins;
11058
- top += self.justify(row, top, maxWidth, maxHeight); // first justify the current row
11059
- row = create(); // then make the new one
11060
- tmp = 0;
 
 
 
 
 
11061
  }
11062
 
11063
- if (row.items.length > 0) tmp += self.options.margins;
11064
- tmp += item.width;
11065
  row.width += item.width;
11066
  row.items.push(item);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11067
  }
11068
- if (rows.length > 1) top += self.options.margins;
11069
- self.lastRow(row, top, maxWidth, maxHeight);
11070
- return rows;
 
 
11071
  }
11072
  });
11073
 
11074
  _.Justified.defaults = {
11075
- itemSelector: ".fg-item",
11076
  rowHeight: 150,
11077
  maxRowHeight: "200%",
11078
  margins: 0,
11079
- lastRow: "center",
11080
- justifyThreshold: 1,
11081
- refreshInterval: 250
11082
  };
11083
 
11084
  })(
@@ -11087,34 +10398,41 @@
11087
  FooGallery.utils,
11088
  FooGallery.utils.is
11089
  );
11090
- (function($, _, _is){
11091
 
11092
  _.JustifiedTemplate = _.Template.extend({
11093
- onPreInit: function(event, self){
 
 
 
 
 
 
 
 
 
 
 
 
 
11094
  self.justified = new _.Justified( self, self.template );
11095
  },
11096
- onInit: function(event, self){
11097
- self.justified.init();
11098
- },
11099
- onFirstLoad: function(event, self){
11100
- self.justified.layout();
11101
  },
11102
- onReady: function(event, self){
11103
- self.justified.layout();
11104
- },
11105
- onDestroy: function(event, self){
11106
- self.justified.destroy();
11107
  },
11108
- onLayout: function(event, self){
11109
- self.justified.layout();
11110
  },
11111
- onAfterPageChange: function(event, self, current, prev, isFilter){
11112
  if (!isFilter){
11113
- self.justified.layout();
11114
  }
11115
- },
11116
- onAfterFilterChange: function(event, self){
11117
- self.justified.layout();
11118
  }
11119
  });
11120
 
@@ -11123,108 +10441,26 @@
11123
  });
11124
 
11125
  })(
11126
- FooGallery.$,
11127
- FooGallery,
11128
- FooGallery.utils.is
11129
  );
11130
- (function($, _, _utils, _is, _fn){
11131
 
11132
- _.PortfolioTemplate = _.Template.extend({
11133
- construct: function(element, options){
11134
- this._super(element, options);
11135
- /**
11136
- *
11137
- * @type {?HTMLStyleElement}
11138
- */
11139
- this.style = null;
11140
 
11141
- this.fullWidth = false;
11142
- },
11143
- /**
11144
- * @summary Creates or gets the CSS stylesheet element for this template instance.
11145
- * @memberof FooGallery.MasonryTemplate#
11146
- * @function getStylesheet
11147
- * @returns {StyleSheet}
11148
- */
11149
- getStylesheet: function(){
11150
- var self = this;
11151
- if (self.style === null){
11152
- self.style = document.createElement("style");
11153
- self.style.appendChild(document.createTextNode(""));
11154
- document.head.appendChild(self.style);
11155
- }
11156
- return self.style.sheet;
11157
- },
11158
- onPreInit: function(event, self){
11159
- self.appendCSS();
11160
- },
11161
- onPostInit: function(event, self){
11162
- self.checkCSS();
11163
- },
11164
- onDestroy: function(event, self){
11165
- self.removeCSS();
11166
- },
11167
- onLayout: function(event, self){
11168
- self.checkCSS();
11169
- },
11170
- checkCSS: function(){
11171
- var self = this, maxWidth = self.getContainerWidth(), current = maxWidth < self.template.columnWidth;
11172
- if (current !== self.fullWidth){
11173
- self.appendCSS(maxWidth);
11174
- }
11175
- },
11176
- appendCSS: function(maxWidth){
11177
- var self = this;
11178
- maxWidth = _is.number(maxWidth) ? maxWidth : self.getContainerWidth();
11179
-
11180
- self.removeCSS();
11181
-
11182
- var sheet = self.getStylesheet(), rule,
11183
- container = '#' + self.id + self.sel.container,
11184
- item = container + ' ' + self.sel.item.elem,
11185
- width = self.template.columnWidth,
11186
- gutter = Math.ceil(self.template.gutter / 2);
11187
-
11188
- switch (self.template.align) {
11189
- case "center":
11190
- rule = container + ' { justify-content: center; }';
11191
- sheet.insertRule(rule , 0);
11192
- break;
11193
- case "left":
11194
- rule = container + ' { justify-content: flex-start; }';
11195
- sheet.insertRule(rule , 0);
11196
- break;
11197
- case "right":
11198
- rule = container + ' { justify-content: flex-end; }';
11199
- sheet.insertRule(rule , 0);
11200
- break;
11201
- }
11202
- self.fullWidth = maxWidth < width;
11203
- if (self.fullWidth){
11204
- rule = item + ' { max-width: 100%; min-width: 100%; margin: ' + gutter + 'px; }';
11205
- sheet.insertRule(rule , 0);
11206
- } else {
11207
- rule = item + ' { max-width: ' + width + 'px; min-width: ' + width + 'px; margin: ' + gutter + 'px; }';
11208
- sheet.insertRule(rule , 0);
11209
- }
11210
- },
11211
- removeCSS: function(){
11212
- var self = this;
11213
- if (self.style && self.style.parentNode){
11214
- self.style.parentNode.removeChild(self.style);
11215
- self.style = null;
11216
- self.fullWidth = false;
11217
- }
11218
- }
11219
  });
11220
 
11221
- _.template.register("simple_portfolio", _.PortfolioTemplate, {
11222
- template: {
11223
- gutter: 40,
11224
- align: "center",
11225
- columnWidth: 250
11226
- }
11227
- }, {
 
 
11228
  container: "foogallery fg-simple_portfolio"
11229
  });
11230
 
@@ -11239,7 +10475,8 @@
11239
 
11240
  _.ImageViewerTemplate = _.Template.extend({
11241
  construct: function (options, element) {
11242
- this._super(_obj.extend({}, options, {
 
11243
  paging: {
11244
  pushOrReplace: "replace",
11245
  theme: "fg-light",
@@ -11255,35 +10492,35 @@
11255
  * @name $inner
11256
  * @type {jQuery}
11257
  */
11258
- this.$inner = $();
11259
  /**
11260
  * @summary The jQuery object that displays the current image count.
11261
  * @memberof FooGallery.ImageViewerTemplate#
11262
  * @name $current
11263
  * @type {jQuery}
11264
  */
11265
- this.$current = $();
11266
  /**
11267
  * @summary The jQuery object that displays the current image count.
11268
  * @memberof FooGallery.ImageViewerTemplate#
11269
  * @name $current
11270
  * @type {jQuery}
11271
  */
11272
- this.$total = $();
11273
  /**
11274
  * @summary The jQuery object for the previous button.
11275
  * @memberof FooGallery.ImageViewerTemplate#
11276
  * @name $prev
11277
  * @type {jQuery}
11278
  */
11279
- this.$prev = $();
11280
  /**
11281
  * @summary The jQuery object for the next button.
11282
  * @memberof FooGallery.ImageViewerTemplate#
11283
  * @name $next
11284
  * @type {jQuery}
11285
  */
11286
- this.$next = $();
11287
  /**
11288
  * @summary The CSS classes for the Image Viewer template.
11289
  * @memberof FooGallery.ImageViewerTemplate#
@@ -11296,6 +10533,14 @@
11296
  * @name sel
11297
  * @type {FooGallery.ImageViewerTemplate~CSSSelectors}
11298
  */
 
 
 
 
 
 
 
 
11299
  },
11300
  createChildren: function(){
11301
  var self = this;
@@ -11316,14 +10561,17 @@
11316
  var self = this;
11317
  self.$el.find(self.sel.inner).remove();
11318
  },
11319
- onPreInit: function(event, self){
 
 
11320
  self.$inner = self.$el.find(self.sel.innerContainer);
11321
  self.$current = self.$el.find(self.sel.countCurrent);
11322
  self.$total = self.$el.find(self.sel.countTotal);
11323
  self.$prev = self.$el.find(self.sel.prev);
11324
  self.$next = self.$el.find(self.sel.next);
11325
  },
11326
- onInit: function (event, self) {
 
11327
  if (self.template.attachFooBox) {
11328
  self.$el.on('foobox.previous', {self: self}, self.onFooBoxPrev)
11329
  .on('foobox.next', {self: self}, self.onFooBoxNext);
@@ -11331,15 +10579,13 @@
11331
  self.$prev.on('click', {self: self}, self.onPrevClick);
11332
  self.$next.on('click', {self: self}, self.onNextClick);
11333
  },
11334
- onFirstLoad: function(event, self){
11335
- self.update();
11336
- },
11337
  /**
11338
  * @summary Destroy the plugin cleaning up any bound events.
11339
  * @memberof FooGallery.ImageViewerTemplate#
11340
  * @function onDestroy
11341
  */
11342
- onDestroy: function (event, self) {
 
11343
  if (self.template.attachFooBox) {
11344
  self.$el.off({
11345
  'foobox.previous': self.onFooBoxPrev,
@@ -11349,20 +10595,20 @@
11349
  self.$prev.off('click', self.onPrevClick);
11350
  self.$next.off('click', self.onNextClick);
11351
  },
11352
- onAppendItem: function (event, self, item) {
11353
  event.preventDefault();
11354
- self.$inner.append(item.$el);
11355
- item.fix();
11356
  item.isAttached = true;
11357
  },
11358
- onAfterPageChange: function(event, self, current, prev, isFilter){
11359
  if (!isFilter){
11360
- self.update();
11361
  }
11362
  },
11363
- onAfterFilterChange: function(event, self){
11364
- self.update();
11365
  },
 
11366
  update: function(){
11367
  if (this.pages){
11368
  this.$current.text(this.pages.current);
@@ -11629,7 +10875,7 @@
11629
  }
11630
  _t.start(self.$piles, function($el){
11631
  $el.css({width: size.width + 'px', height: size.height + 'px'});
11632
- }, false, 350).then(function(){
11633
  self.ignoreResize = false;
11634
  });
11635
  },
@@ -11875,14 +11121,16 @@
11875
  def.reject();
11876
  }
11877
  });
11878
- self.$image.prop('src', self.$image.attr(self.opt.src));
 
11879
  }).promise();
11880
  }
11881
  });
11882
 
11883
  _.StackAlbum.Item.defaults = {
11884
  index: -1,
11885
- src: 'data-src-fg'
 
11886
  };
11887
 
11888
  })(
@@ -11924,25 +11172,28 @@
11924
  );
11925
  (function ($, _, _utils, _obj, _is) {
11926
 
11927
- _.triggerPostLoad = function (e, tmpl, current, prev, isFilter) {
11928
- if (e.type === "first-load" || (tmpl.initialized && ((e.type === "after-page-change" && !isFilter) || e.type === "after-filter-change"))) {
11929
- try {
11930
- // if the gallery is displayed within a FooBox do not trigger the post-load which would cause the lightbox to re-init
11931
- if (tmpl.$el.parents(".fbx-item").length > 0) return;
11932
- if (tmpl.$el.hasClass("fbx-instance") && !!window.FOOBOX && !!$.fn.foobox){
11933
- tmpl.$el.foobox(window.FOOBOX.o);
11934
- } else {
11935
- $("body").trigger("post-load");
 
 
 
 
 
11936
  }
11937
- } catch(err) {
11938
- console.error(err);
11939
  }
11940
  }
11941
  };
11942
 
11943
  _.autoDefaults = {
11944
  on: {
11945
- "first-load.foogallery after-page-change.foogallery after-filter-change.foogallery": _.triggerPostLoad
11946
  }
11947
  };
11948
 
@@ -11959,7 +11210,7 @@
11959
  if (window.FooGallery_il8n && _is.object(window.FooGallery_il8n)){
11960
  var il8n = window.FooGallery_il8n;
11961
  for (var factory in il8n){
11962
- if (!il8n.hasOwnProperty(factory) || !(_[factory] instanceof _utils.Factory) || !_is.object(il8n[factory])) continue;
11963
  for (var component in il8n[factory]){
11964
  if (il8n[factory].hasOwnProperty(component)){
11965
  _[factory].configure(component, null, null, il8n[factory][component]);
1735
  */
1736
  window.FooGallery = window.FooGallery || {}
1737
  );
1738
+ "use strict";
1739
+
1740
+ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
1741
+
1742
  /*!
1743
  * FooGallery.utils - Contains common utility methods and classes used in our plugins.
1744
+ * @version 1.0.0
1745
  * @link https://github.com/steveush/foo-utils#readme
1746
+ * @copyright Steve Usher 2021
1747
  * @license Released under the GPL-3.0 license.
1748
  */
1749
+
1750
  /**
1751
  * @file This creates the global FooGallery.utils namespace
1752
  */
1753
  (function ($) {
1754
+ if (!$) {
1755
+ console.warn('jQuery must be included in the page prior to the FooGallery.utils library.');
1756
+ return;
1757
+ }
1758
+
1759
+ function __exists() {
1760
+ try {
1761
+ return !!window.FooGallery.utils; // does the namespace already exist?
1762
+ } catch (err) {
1763
+ return false;
1764
+ }
1765
+ }
1766
 
1767
+ if (!__exists()) {
1768
+ /**
1769
+ * @summary This namespace contains common utility methods and code shared between our plugins.
1770
+ * @global
1771
+ * @namespace FooGallery.utils
1772
+ * @description This namespace relies on jQuery being included in the page prior to it being loaded.
1773
+ */
1774
+ window.FooGallery.utils = {
1775
+ /**
1776
+ * @summary A reference to the jQuery object the library is registered with.
1777
+ * @memberof FooGallery.utils.
1778
+ * @name $
1779
+ * @type {jQuery}
1780
+ * @description This is used internally for all jQuery operations to help work around issues where multiple jQuery libraries have been included in a single page.
1781
+ * @example {@caption The following shows the issue when multiple jQuery's are included in a single page.}{@lang html}
1782
+ * <script src="jquery-1.12.4.js"></script>
1783
+ * <script src="my-plugin.js"></script>
1784
+ * <script src="jquery-2.2.4.js"></script>
1785
+ * <script>
1786
+ * jQuery(function($){
1787
+ * $(".selector").myPlugin(); // => This would throw a TypeError: $(...).myPlugin is not a function
1788
+ * });
1789
+ * </script>
1790
+ * @example {@caption The reason the above throws an error is that the `$.fn.myPlugin` function is registered to the first instance of jQuery in the page however the instance used to create the ready callback and actually try to execute `$(...).myPlugin()` is the second. To resolve this issue ideally you would remove the second instance of jQuery however you can use the `FooGallery.utils.$` member to ensure you are always working with the instance of jQuery the library was registered with.}{@lang html}
1791
+ * <script src="jquery-1.12.4.js"></script>
1792
+ * <script src="my-plugin.js"></script>
1793
+ * <script src="jquery-2.2.4.js"></script>
1794
+ * <script>
1795
+ * FooGallery.utils.$(function($){
1796
+ * $(".selector").myPlugin(); // => It works!
1797
+ * });
1798
+ * </script>
1799
+ */
1800
+ $: $,
1801
+
1802
+ /**
1803
+ * @summary The version of this library.
1804
+ * @memberof FooGallery.utils.
1805
+ * @name version
1806
+ * @type {string}
1807
+ */
1808
+ version: '1.0.0'
1809
+ };
1810
+ } // at this point there will always be a FooGallery.utils namespace registered to the global scope.
1811
 
1812
+ })(jQuery);
 
 
 
 
 
 
1813
 
1814
+ (function ($, _) {
1815
+ // only register methods if this version is the current version
1816
+ if (_.version !== '1.0.0') return;
1817
+ /**
1818
+ * @summary Contains common type checking utility methods.
1819
+ * @memberof FooGallery.utils.
1820
+ * @namespace is
1821
+ */
1822
+
1823
+ _.is = {};
1824
+ /**
1825
+ * @summary Checks if the `value` is an array.
1826
+ * @memberof FooGallery.utils.is.
1827
+ * @function array
1828
+ * @param {*} value - The value to check.
1829
+ * @returns {boolean} `true` if the supplied `value` is an array.
1830
+ * @example {@run true}
1831
+ * // alias the FooGallery.utils.is namespace
1832
+ * var _is = FooGallery.utils.is;
1833
+ *
1834
+ * console.log( _is.array( [] ) ); // => true
1835
+ * console.log( _is.array( null ) ); // => false
1836
+ * console.log( _is.array( 123 ) ); // => false
1837
+ * console.log( _is.array( "" ) ); // => false
1838
+ */
1839
+
1840
+ _.is.array = function (value) {
1841
+ return '[object Array]' === Object.prototype.toString.call(value);
1842
+ };
1843
+ /**
1844
+ * @summary Checks if the `value` is a boolean.
1845
+ * @memberof FooGallery.utils.is.
1846
+ * @function boolean
1847
+ * @param {*} value - The value to check.
1848
+ * @returns {boolean} `true` if the supplied `value` is a boolean.
1849
+ * @example {@run true}
1850
+ * // alias the FooGallery.utils.is namespace
1851
+ * var _is = FooGallery.utils.is;
1852
+ *
1853
+ * console.log( _is.boolean( true ) ); // => true
1854
+ * console.log( _is.boolean( false ) ); // => true
1855
+ * console.log( _is.boolean( "true" ) ); // => false
1856
+ * console.log( _is.boolean( "false" ) ); // => false
1857
+ * console.log( _is.boolean( 1 ) ); // => false
1858
+ * console.log( _is.boolean( 0 ) ); // => false
1859
+ */
1860
+
1861
+
1862
+ _.is.boolean = function (value) {
1863
+ return '[object Boolean]' === Object.prototype.toString.call(value);
1864
+ };
1865
+ /**
1866
+ * @summary Checks if the `value` is an element.
1867
+ * @memberof FooGallery.utils.is.
1868
+ * @function element
1869
+ * @param {*} value - The value to check.
1870
+ * @returns {boolean} `true` if the supplied `value` is an element.
1871
+ * @example {@run true}
1872
+ * // alias the FooGallery.utils.is namespace
1873
+ * var _is = FooGallery.utils.is,
1874
+ * // create an element to test
1875
+ * el = document.createElement("span");
1876
+ *
1877
+ * console.log( _is.element( el ) ); // => true
1878
+ * console.log( _is.element( $(el) ) ); // => false
1879
+ * console.log( _is.element( null ) ); // => false
1880
+ * console.log( _is.element( {} ) ); // => false
1881
+ */
1882
+
1883
+
1884
+ _.is.element = function (value) {
1885
+ return (typeof HTMLElement === "undefined" ? "undefined" : _typeof(HTMLElement)) === 'object' ? value instanceof HTMLElement : !!value && _typeof(value) === 'object' && value.nodeType === 1 && typeof value.nodeName === 'string';
1886
+ };
1887
+ /**
1888
+ * @summary Checks if the `value` is empty.
1889
+ * @memberof FooGallery.utils.is.
1890
+ * @function empty
1891
+ * @param {*} value - The value to check.
1892
+ * @returns {boolean} `true` if the supplied `value` is empty.
1893
+ * @description The following values are considered to be empty by this method:
1894
+ *
1895
+ * <ul><!--
1896
+ * --><li>`""` - An empty string</li><!--
1897
+ * --><li>`0` - 0 as an integer</li><!--
1898
+ * --><li>`0.0` - 0 as a float</li><!--
1899
+ * --><li>`[]` - An empty array</li><!--
1900
+ * --><li>`{}` - An empty object</li><!--
1901
+ * --><li>`$()` - An empty jQuery object</li><!--
1902
+ * --><li>`false`</li><!--
1903
+ * --><li>`null`</li><!--
1904
+ * --><li>`undefined`</li><!--
1905
+ * --></ul>
1906
+ * @example {@run true}
1907
+ * // alias the FooGallery.utils.is namespace
1908
+ * var _is = FooGallery.utils.is;
1909
+ *
1910
+ * console.log( _is.empty( undefined ) ); // => true
1911
+ * console.log( _is.empty( null ) ); // => true
1912
+ * console.log( _is.empty( 0 ) ); // => true
1913
+ * console.log( _is.empty( 0.0 ) ); // => true
1914
+ * console.log( _is.empty( "" ) ); // => true
1915
+ * console.log( _is.empty( [] ) ); // => true
1916
+ * console.log( _is.empty( {} ) ); // => true
1917
+ * console.log( _is.empty( 1 ) ); // => false
1918
+ * console.log( _is.empty( 0.1 ) ); // => false
1919
+ * console.log( _is.empty( "one" ) ); // => false
1920
+ * console.log( _is.empty( ["one"] ) ); // => false
1921
+ * console.log( _is.empty( { "name": "My Object" } ) ); // => false
1922
+ */
1923
+
1924
+
1925
+ _.is.empty = function (value) {
1926
+ if (_.is.undef(value) || value === null) return true;
1927
+ if (_.is.number(value) && value === 0) return true;
1928
+ if (_.is.boolean(value) && value === false) return true;
1929
+ if (_.is.string(value) && value.length === 0) return true;
1930
+ if (_.is.array(value) && value.length === 0) return true;
1931
+ if (_.is.jq(value) && value.length === 0) return true;
1932
+
1933
+ if (_.is.hash(value)) {
1934
+ for (var prop in value) {
1935
+ if (value.hasOwnProperty(prop)) return false;
1936
+ }
1937
+
1938
+ return true;
1939
+ }
1940
 
1941
+ return false;
1942
+ };
1943
+ /**
1944
+ * @summary Checks if the `value` is an error.
1945
+ * @memberof FooGallery.utils.is.
1946
+ * @function error
1947
+ * @param {*} value - The value to check.
1948
+ * @returns {boolean} `true` if the supplied `value` is an error.
1949
+ * @example {@run true}
1950
+ * // alias the FooGallery.utils.is namespace
1951
+ * var _is = FooGallery.utils.is,
1952
+ * // create some errors to test
1953
+ * err1 = new Error("err1"),
1954
+ * err2 = new SyntaxError("err2");
1955
+ *
1956
+ * console.log( _is.error( err1 ) ); // => true
1957
+ * console.log( _is.error( err2 ) ); // => true
1958
+ * console.log( _is.error( null ) ); // => false
1959
+ * console.log( _is.error( 123 ) ); // => false
1960
+ * console.log( _is.error( "" ) ); // => false
1961
+ * console.log( _is.error( {} ) ); // => false
1962
+ * console.log( _is.error( [] ) ); // => false
1963
+ */
1964
+
1965
+
1966
+ _.is.error = function (value) {
1967
+ return '[object Error]' === Object.prototype.toString.call(value);
1968
+ };
1969
+ /**
1970
+ * @summary Checks if the `value` is a function.
1971
+ * @memberof FooGallery.utils.is.
1972
+ * @function fn
1973
+ * @param {*} value - The value to check.
1974
+ * @returns {boolean} `true` if the supplied `value` is a function.
1975
+ * @example {@run true}
1976
+ * // alias the FooGallery.utils.is namespace
1977
+ * var _is = FooGallery.utils.is,
1978
+ * // create a function to test
1979
+ * func = function(){};
1980
+ *
1981
+ * console.log( _is.fn( func ) ); // => true
1982
+ * console.log( _is.fn( null ) ); // => false
1983
+ * console.log( _is.fn( 123 ) ); // => false
1984
+ * console.log( _is.fn( "" ) ); // => false
1985
+ */
1986
+
1987
+
1988
+ _.is.fn = function (value) {
1989
+ return value === window.alert || '[object Function]' === Object.prototype.toString.call(value);
1990
+ };
1991
+ /**
1992
+ * @summary Checks if the `value` is a hash.
1993
+ * @memberof FooGallery.utils.is.
1994
+ * @function hash
1995
+ * @param {*} value - The value to check.
1996
+ * @returns {boolean} `true` if the supplied `value` is a hash.
1997
+ * @example {@run true}
1998
+ * // alias the FooGallery.utils.is namespace
1999
+ * var _is = FooGallery.utils.is;
2000
+ *
2001
+ * console.log( _is.hash( {"some": "prop"} ) ); // => true
2002
+ * console.log( _is.hash( {} ) ); // => true
2003
+ * console.log( _is.hash( window ) ); // => false
2004
+ * console.log( _is.hash( document ) ); // => false
2005
+ * console.log( _is.hash( "" ) ); // => false
2006
+ * console.log( _is.hash( 123 ) ); // => false
2007
+ */
2008
+
2009
+
2010
+ _.is.hash = function (value) {
2011
+ return _.is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval;
2012
+ };
2013
+ /**
2014
+ * @summary Checks if the `value` is a jQuery object.
2015
+ * @memberof FooGallery.utils.is.
2016
+ * @function jq
2017
+ * @param {*} value - The value to check.
2018
+ * @returns {boolean} `true` if the supplied `value` is a jQuery object.
2019
+ * @example {@run true}
2020
+ * // alias the FooGallery.utils.is namespace
2021
+ * var _is = FooGallery.utils.is,
2022
+ * // create an element to test
2023
+ * el = document.createElement("span");
2024
+ *
2025
+ * console.log( _is.jq( $(el) ) ); // => true
2026
+ * console.log( _is.jq( $() ) ); // => true
2027
+ * console.log( _is.jq( el ) ); // => false
2028
+ * console.log( _is.jq( {} ) ); // => false
2029
+ * console.log( _is.jq( null ) ); // => false
2030
+ * console.log( _is.jq( 123 ) ); // => false
2031
+ * console.log( _is.jq( "" ) ); // => false
2032
+ */
2033
+
2034
+
2035
+ _.is.jq = function (value) {
2036
+ return !_.is.undef($) && value instanceof $;
2037
+ };
2038
+ /**
2039
+ * @summary Checks if the `value` is a number.
2040
+ * @memberof FooGallery.utils.is.
2041
+ * @function number
2042
+ * @param {*} value - The value to check.
2043
+ * @returns {boolean}
2044
+ * @example {@run true}
2045
+ * // alias the FooGallery.utils.is namespace
2046
+ * var _is = FooGallery.utils.is;
2047
+ *
2048
+ * console.log( _is.number( 123 ) ); // => true
2049
+ * console.log( _is.number( undefined ) ); // => false
2050
+ * console.log( _is.number( null ) ); // => false
2051
+ * console.log( _is.number( "" ) ); // => false
2052
+ */
2053
+
2054
+
2055
+ _.is.number = function (value) {
2056
+ return '[object Number]' === Object.prototype.toString.call(value) && !isNaN(value);
2057
+ };
2058
+ /**
2059
+ * @summary Checks if the `value` is an object.
2060
+ * @memberof FooGallery.utils.is.
2061
+ * @function object
2062
+ * @param {*} value - The value to check.
2063
+ * @returns {boolean} `true` if the supplied `value` is an object.
2064
+ * @example {@run true}
2065
+ * // alias the FooGallery.utils.is namespace
2066
+ * var _is = FooGallery.utils.is;
2067
+ *
2068
+ * console.log( _is.object( {"some": "prop"} ) ); // => true
2069
+ * console.log( _is.object( {} ) ); // => true
2070
+ * console.log( _is.object( window ) ); // => true
2071
+ * console.log( _is.object( document ) ); // => true
2072
+ * console.log( _is.object( undefined ) ); // => false
2073
+ * console.log( _is.object( null ) ); // => false
2074
+ * console.log( _is.object( "" ) ); // => false
2075
+ * console.log( _is.object( 123 ) ); // => false
2076
+ */
2077
+
2078
+
2079
+ _.is.object = function (value) {
2080
+ return '[object Object]' === Object.prototype.toString.call(value) && !_.is.undef(value) && value !== null;
2081
+ };
2082
+ /**
2083
+ * @summary Checks if the `value` is a promise.
2084
+ * @memberof FooGallery.utils.is.
2085
+ * @function promise
2086
+ * @param {*} value - The object to check.
2087
+ * @returns {boolean} `true` if the supplied `value` is an object.
2088
+ * @description This is a simple check to determine if an object is a jQuery promise object. It simply checks the object has a `then` and `promise` function defined.
2089
+ *
2090
+ * The promise object is created as an object literal inside of `jQuery.Deferred`, it has no prototype, nor any other truly unique properties that could be used to distinguish it.
2091
+ *
2092
+ * This method should be a little more accurate than the internal jQuery one that simply checks for a `promise` function.
2093
+ * @example {@run true}
2094
+ * // alias the FooGallery.utils.is namespace
2095
+ * var _is = FooGallery.utils.is;
2096
+ *
2097
+ * console.log( _is.promise( $.Deferred() ) ); // => true
2098
+ * console.log( _is.promise( {} ) ); // => false
2099
+ * console.log( _is.promise( undefined ) ); // => false
2100
+ * console.log( _is.promise( null ) ); // => false
2101
+ * console.log( _is.promise( "" ) ); // => false
2102
+ * console.log( _is.promise( 123 ) ); // => false
2103
+ */
2104
+
2105
+
2106
+ _.is.promise = function (value) {
2107
+ return _.is.object(value) && _.is.fn(value.then) && _.is.fn(value.promise);
2108
+ };
2109
+ /**
2110
+ * @summary Checks if the `value` is a valid CSS length.
2111
+ * @memberof FooGallery.utils.is.
2112
+ * @function size
2113
+ * @param {*} value - The value to check.
2114
+ * @returns {boolean} `true` if the `value` is a number or CSS length.
2115
+ * @example {@run true}
2116
+ * // alias the FooGallery.utils.is namespace
2117
+ * var _is = FooGallery.utils.is;
2118
+ *
2119
+ * console.log( _is.size( 80 ) ); // => true
2120
+ * console.log( _is.size( "80px" ) ); // => true
2121
+ * console.log( _is.size( "80em" ) ); // => true
2122
+ * console.log( _is.size( "80%" ) ); // => true
2123
+ * console.log( _is.size( {} ) ); // => false
2124
+ * console.log( _is.size( undefined ) ); // => false
2125
+ * console.log( _is.size( null ) ); // => false
2126
+ * console.log( _is.size( "" ) ); // => false
2127
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/length|&lt;length&gt; - CSS | MDN} for more information on CSS length values.
2128
+ */
2129
+
2130
+
2131
+ _.is.size = function (value) {
2132
+ if (!(_.is.string(value) && !_.is.empty(value)) && !_.is.number(value)) return false;
2133
+ return /^(auto|none|(?:[\d.]*)+?(?:%|px|mm|q|cm|in|pt|pc|em|ex|ch|rem|vh|vw|vmin|vmax)?)$/.test(value);
2134
+ };
2135
+ /**
2136
+ * @summary Checks if the `value` is a string.
2137
+ * @memberof FooGallery.utils.is.
2138
+ * @function string
2139
+ * @param {*} value - The value to check.
2140
+ * @returns {boolean} `true` if the `value` is a string.
2141
+ * @example {@run true}
2142
+ * // alias the FooGallery.utils.is namespace
2143
+ * var _is = FooGallery.utils.is;
2144
+ *
2145
+ * console.log( _is.string( "" ) ); // => true
2146
+ * console.log( _is.string( undefined ) ); // => false
2147
+ * console.log( _is.string( null ) ); // => false
2148
+ * console.log( _is.string( 123 ) ); // => false
2149
+ */
2150
+
2151
+
2152
+ _.is.string = function (value) {
2153
+ return '[object String]' === Object.prototype.toString.call(value);
2154
+ };
2155
+ /**
2156
+ * @summary Checks if the `value` is `undefined`.
2157
+ * @memberof FooGallery.utils.is.
2158
+ * @function undef
2159
+ * @param {*} value - The value to check is undefined.
2160
+ * @returns {boolean} `true` if the supplied `value` is `undefined`.
2161
+ * @example {@run true}
2162
+ * // alias the FooGallery.utils.is namespace
2163
+ * var _is = FooGallery.utils.is;
2164
+ *
2165
+ * console.log( _is.undef( undefined ) ); // => true
2166
+ * console.log( _is.undef( null ) ); // => false
2167
+ * console.log( _is.undef( 123 ) ); // => false
2168
+ * console.log( _is.undef( "" ) ); // => false
2169
+ */
2170
+
2171
+
2172
+ _.is.undef = function (value) {
2173
+ return typeof value === 'undefined';
2174
+ };
2175
+ })( // dependencies
2176
+ FooGallery.utils.$, FooGallery.utils);
2177
+
2178
+ (function ($, _, _is) {
2179
+ // only register methods if this version is the current version
2180
+ if (_.version !== '1.0.0') return;
2181
+ /**
2182
+ * @memberof FooGallery.utils.
2183
+ * @namespace fn
2184
+ * @summary Contains common function utility methods.
2185
+ */
2186
+
2187
+ _.fn = {};
2188
+ var fnStr = Function.prototype.toString;
2189
+ /**
2190
+ * @summary The regular expression to test if a function uses the `this._super` method applied by the {@link FooGallery.utils.fn.add} method.
2191
+ * @memberof FooGallery.utils.fn.
2192
+ * @name CONTAINS_SUPER
2193
+ * @type {RegExp}
2194
+ * @default /\b_super\b/
2195
+ * @readonly
2196
+ * @description When the script is first loaded into the page this performs a quick check to see if the browser supports function decompilation. If it does the regular expression is set to match the expected `_super`, however if function decompilation is not supported, the regular expression is set to match anything effectively making the test always return `true`.
2197
+ * @example {@run true}
2198
+ * // alias the FooGallery.utils.fn namespace
2199
+ * var _fn = FooGallery.utils.fn;
2200
+ *
2201
+ * // create some functions to test
2202
+ * function testFn1(){}
2203
+ * function testFn2(){
2204
+ * this._super();
2205
+ * }
2206
+ *
2207
+ * console.log( _fn.CONTAINS_SUPER.test( testFn1 ) ); // => false
2208
+ * console.log( _fn.CONTAINS_SUPER.test( testFn2 ) ); // => true
2209
+ *
2210
+ * // NOTE: in browsers that don't support functional decompilation both tests will return `true`
2211
+ */
2212
+
2213
+ _.fn.CONTAINS_SUPER = /xyz/.test(fnStr.call(function () {
2214
+ //noinspection JSUnresolvedVariable,BadExpressionStatementJS
2215
+ xyz;
2216
+ })) ? /\b_super\b/ : /.*/;
2217
+ /**
2218
+ * @summary An empty function that does nothing. Useful for setting a default value and checking if it has changed.
2219
+ * @memberof FooGallery.utils.fn.
2220
+ * @function noop
2221
+ */
2222
+
2223
+ _.fn.noop = function () {};
2224
+ /**
2225
+ * @summary Adds or overrides the given method `name` on the `proto` using the supplied `fn`.
2226
+ * @memberof FooGallery.utils.fn.
2227
+ * @function addOrOverride
2228
+ * @param {Object} proto - The prototype to add the method to.
2229
+ * @param {string} name - The name of the method to add, if this already exists the original will be exposed within the scope of the supplied `fn` as `this._super`.
2230
+ * @param {function} fn - The function to add to the prototype, if this is overriding an existing method you can use `this._super` to access the original within its' scope.
2231
+ * @description If the new method overrides a pre-existing one, this function will expose the overridden method as `this._super` within the new methods scope.
2232
+ *
2233
+ * This replaces having to write out the following to override a method and call its original:
2234
+ *
2235
+ * ```javascript
2236
+ * var original = MyClass.prototype.someMethod;
2237
+ * MyClass.prototype.someMethod = function(arg1, arg2){
2238
+ * // execute the original
2239
+ * original.call(this, arg1, arg2);
2240
+ * };
2241
+ * ```
2242
+ *
2243
+ * With the following:
2244
+ *
2245
+ * ```javascript
2246
+ * FooGallery.utils.fn.addOrOverride( MyClass.prototype, "someMethod", function(arg1, arg2){
2247
+ * // execute the original
2248
+ * this._super(arg1, arg2);
2249
+ * });
2250
+ * ```
2251
+ *
2252
+ * This method is used by the {@link FooGallery.utils.Class} to implement the inheritance of individual methods.
2253
+ * @example {@run true}
2254
+ * // alias the FooGallery.utils.fn namespace
2255
+ * var _fn = FooGallery.utils.fn;
2256
+ *
2257
+ * var proto = {
2258
+ * write: function( message ){
2259
+ * console.log( "Original#write: " + message );
2260
+ * }
2261
+ * };
2262
+ *
2263
+ * proto.write( "My message" ); // => "Original#write: My message"
2264
+ *
2265
+ * _fn.addOrOverride( proto, "write", function( message ){
2266
+ * message = "Override#write: " + message;
2267
+ * this._super( message );
2268
+ * } );
2269
+ *
2270
+ * proto.write( "My message" ); // => "Original#write: Override#write: My message"
2271
+ */
2272
+
2273
+
2274
+ _.fn.addOrOverride = function (proto, name, fn) {
2275
+ if (!_is.object(proto) || !_is.string(name) || _is.empty(name) || !_is.fn(fn)) return;
2276
+
2277
+ var _super = proto[name],
2278
+ wrap = _is.fn(_super) && _.fn.CONTAINS_SUPER.test(fnStr.call(fn)); // only wrap the function if it overrides a method and makes use of `_super` within it's body.
2279
+
2280
+
2281
+ proto[name] = wrap ? function (_super, fn) {
2282
+ // create a new wrapped that exposes the original method as `_super`
2283
+ return function () {
2284
+ var tmp = this._super;
2285
+ this._super = _super;
2286
+ var ret = fn.apply(this, arguments);
2287
+ this._super = tmp;
2288
+ return ret;
2289
+ };
2290
+ }(_super, fn) : fn;
2291
+ };
2292
+ /**
2293
+ * @summary Exposes the `methods` from the `source` on the `target`.
2294
+ * @memberof FooGallery.utils.fn.
2295
+ * @function expose
2296
+ * @param {Object} source - The object to expose methods from.
2297
+ * @param {Object} target - The object to expose methods on.
2298
+ * @param {String[]} methods - An array of method names to expose.
2299
+ * @param {*} [thisArg] - The value of `this` within the exposed `methods`. Defaults to the `source` object.
2300
+ */
2301
+
2302
+
2303
+ _.fn.expose = function (source, target, methods, thisArg) {
2304
+ if (_is.object(source) && _is.object(target) && _is.array(methods)) {
2305
+ thisArg = _is.undef(thisArg) ? source : thisArg;
2306
+ methods.forEach(function (method) {
2307
+ if (_is.string(method) && _is.fn(source[method])) {
2308
+ target[method] = source[method].bind(thisArg);
2309
+ }
2310
+ });
2311
+ }
2312
+ };
2313
+ /**
2314
+ * @summary Use the `Function.prototype.apply` method on a class constructor using the `new` keyword.
2315
+ * @memberof FooGallery.utils.fn.
2316
+ * @function apply
2317
+ * @param {Object} klass - The class to create.
2318
+ * @param {Array} [args=[]] - The arguments to pass to the constructor.
2319
+ * @returns {Object} The new instance of the `klass` created with the supplied `args`.
2320
+ * @description When using the default `Function.prototype.apply` you can't use it on class constructors requiring the `new` keyword, this method allows us to do that.
2321
+ * @example {@run true}
2322
+ * // alias the FooGallery.utils.fn namespace
2323
+ * var _fn = FooGallery.utils.fn;
2324
+ *
2325
+ * // create a class to test with
2326
+ * function Test( name, value ){
2327
+ * if ( !( this instanceof Test )){
2328
+ * console.log( "Test instantiated without the `new` keyword." );
2329
+ * return;
2330
+ * }
2331
+ * console.log( "Test: name = " + name + ", value = " + value );
2332
+ * }
2333
+ *
2334
+ * Test.apply( Test, ["My name", "My value"] ); // => "Test instantiated without the `new` keyword."
2335
+ * _fn.apply( Test, ["My name", "My value"] ); // => "Test: name = My name, value = My value"
2336
+ */
2337
+
2338
+
2339
+ _.fn.apply = function (klass, args) {
2340
+ args.unshift(klass);
2341
+ return new (Function.prototype.bind.apply(klass, args))();
2342
+ };
2343
+ /**
2344
+ * @summary Converts the default `arguments` object into a proper array.
2345
+ * @memberof FooGallery.utils.fn.
2346
+ * @function arg2arr
2347
+ * @param {IArguments} args - The arguments object to create an array from.
2348
+ * @returns {Array}
2349
+ * @description This method is simply a replacement for calling `Array.prototype.slice.call()` to create an array from an `arguments` object.
2350
+ * @example {@run true}
2351
+ * // alias the FooGallery.utils.fn namespace
2352
+ * var _fn = FooGallery.utils.fn;
2353
+ *
2354
+ * function callMe(){
2355
+ * var args = _fn.arg2arr(arguments);
2356
+ * console.log( arguments instanceof Array ); // => false
2357
+ * console.log( args instanceof Array ); // => true
2358
+ * console.log( args ); // => [ "arg1", "arg2" ]
2359
+ * }
2360
+ *
2361
+ * callMe("arg1", "arg2");
2362
+ */
2363
+
2364
+
2365
+ _.fn.arg2arr = function (args) {
2366
+ return Array.prototype.slice.call(args);
2367
+ };
2368
+ /**
2369
+ * @summary Debounce the `fn` by the supplied `time`.
2370
+ * @memberof FooGallery.utils.fn.
2371
+ * @function debounce
2372
+ * @param {function} fn - The function to debounce.
2373
+ * @param {number} time - The time in milliseconds to delay execution.
2374
+ * @returns {function}
2375
+ * @description This returns a wrapped version of the `fn` which delays its' execution by the supplied `time`. Additional calls to the function will extend the delay until the `time` expires.
2376
+ */
2377
+
2378
+
2379
+ _.fn.debounce = function (fn, time) {
2380
+ var timeout;
2381
+ return function () {
2382
+ var ctx = this,
2383
+ args = _.fn.arg2arr(arguments);
2384
+
2385
+ clearTimeout(timeout);
2386
+ timeout = setTimeout(function () {
2387
+ fn.apply(ctx, args);
2388
+ }, time);
2389
+ };
2390
+ };
2391
+ /**
2392
+ * @summary Throttles the `fn` by the supplied `time`.
2393
+ * @memberof FooGallery.utils.fn.
2394
+ * @function throttle
2395
+ * @param {function} fn - The function to throttle.
2396
+ * @param {number} time - The time in milliseconds to delay execution.
2397
+ * @returns {function}
2398
+ * @description This returns a wrapped version of the `fn` which ensures it's executed only once every `time` milliseconds. The first call to the function will be executed, after that only the last of any additional calls will be executed once the `time` expires.
2399
+ */
2400
+
2401
+
2402
+ _.fn.throttle = function (fn, time) {
2403
+ var last, timeout;
2404
+ return function () {
2405
+ var ctx = this,
2406
+ args = _.fn.arg2arr(arguments);
2407
+
2408
+ if (!last) {
2409
+ fn.apply(ctx, args);
2410
+ last = Date.now();
2411
+ } else {
2412
+ clearTimeout(timeout);
2413
+ timeout = setTimeout(function () {
2414
+ if (Date.now() - last >= time) {
2415
+ fn.apply(ctx, args);
2416
+ last = Date.now();
2417
+ }
2418
+ }, time - (Date.now() - last));
2419
+ }
2420
+ };
2421
+ };
2422
+ /**
2423
+ * @summary A resolved promise object.
2424
+ * @memberof FooGallery.utils.fn.
2425
+ * @name resolved
2426
+ * @type {Promise}
2427
+ */
2428
+
2429
+
2430
+ _.fn.resolved = $.Deferred().resolve().promise();
2431
+ /**
2432
+ * @summary A rejected promise object.
2433
+ * @memberof FooGallery.utils.fn.
2434
+ * @name rejected
2435
+ * @type {Promise}
2436
+ */
2437
+
2438
+ _.fn.rejected = $.Deferred().reject().promise();
2439
+ /**
2440
+ * @summary Return a promise rejected using the supplied args.
2441
+ * @memberof FooGallery.utils.fn.
2442
+ * @function reject
2443
+ * @param {*} [arg1] - The first argument to reject the promise with.
2444
+ * @param {...*} [argN] - Any additional arguments to reject the promise with.
2445
+ * @returns {Promise}
2446
+ */
2447
+
2448
+ _.fn.reject = function (arg1, argN) {
2449
+ var def = $.Deferred(),
2450
+ args = _.fn.arg2arr(arguments);
2451
+
2452
+ return def.reject.apply(def, args).promise();
2453
+ };
2454
+ /**
2455
+ * @summary Return a promise resolved using the supplied args.
2456
+ * @memberof FooGallery.utils.fn.
2457
+ * @function resolve
2458
+ * @param {*} [arg1] - The first argument to resolve the promise with.
2459
+ * @param {...*} [argN] - Any additional arguments to resolve the promise with.
2460
+ * @returns {Promise}
2461
+ */
2462
+
2463
+
2464
+ _.fn.resolve = function (arg1, argN) {
2465
+ var def = $.Deferred(),
2466
+ args = _.fn.arg2arr(arguments);
2467
+
2468
+ return def.resolve.apply(def, args).promise();
2469
+ };
2470
+ /**
2471
+ * @summary Return a promise rejected using the supplied args.
2472
+ * @memberof FooGallery.utils.fn.
2473
+ * @function rejectWith
2474
+ * @param {*} thisArg - The value of `this` within the promises callbacks.
2475
+ * @param {*} [arg1] - The first argument to reject the promise with.
2476
+ * @param {...*} [argN] - Any additional arguments to reject the promise with.
2477
+ * @returns {Promise}
2478
+ */
2479
+
2480
+
2481
+ _.fn.rejectWith = function (thisArg, arg1, argN) {
2482
+ var def = $.Deferred(),
2483
+ args = _.fn.arg2arr(arguments);
2484
+
2485
+ args.shift(); // remove the thisArg
2486
+
2487
+ return def.rejectWith(thisArg, args).promise();
2488
+ };
2489
+ /**
2490
+ * @summary Return a promise resolved using the supplied args.
2491
+ * @memberof FooGallery.utils.fn.
2492
+ * @function resolveWith
2493
+ * @param {*} thisArg - The value of `this` within the promises callbacks.
2494
+ * @param {*} [arg1] - The first argument to resolve the promise with.
2495
+ * @param {...*} [argN] - Any additional arguments to resolve the promise with.
2496
+ * @returns {Promise}
2497
+ */
2498
+
2499
+
2500
+ _.fn.resolveWith = function (thisArg, arg1, argN) {
2501
+ var def = $.Deferred(),
2502
+ args = _.fn.arg2arr(arguments);
2503
+
2504
+ args.shift(); // remove the thisArg
2505
+
2506
+ return def.resolveWith(thisArg, args).promise();
2507
+ };
2508
+ /**
2509
+ * @summary Waits for all promises to complete before resolving with an array containing the return value of each. This method will reject immediately with the first rejection message or error.
2510
+ * @memberof FooGallery.utils.fn.
2511
+ * @function all
2512
+ * @param {Promise[]} promises - The array of promises to wait for.
2513
+ * @returns {Promise}
2514
+ */
2515
+
2516
+
2517
+ _.fn.all = function (promises) {
2518
+ var d = $.Deferred(),
2519
+ results = [];
2520
+
2521
+ if (_is.array(promises) && promises.length > 0) {
2522
+ (function () {
2523
+ /**
2524
+ * Pushes the arguments into the results array at the supplied index.
2525
+ * @ignore
2526
+ * @param {number} index
2527
+ * @param {Array} args
2528
+ */
2529
+ var pushResult = function pushResult(index, args) {
2530
+ if (rejected) return;
2531
+ results[index] = args.length === 0 ? undefined : args.length === 1 ? args[0] : args;
2532
+ remaining--;
2533
+ if (!remaining) d.resolve(results);
2534
+ };
2535
 
2536
+ var remaining = promises.length,
2537
+ rejected = false;
2538
+ var i = 0,
2539
+ l = promises.length;
2540
+
2541
+ var _loop = function _loop() {
2542
+ if (rejected) return "break";
2543
+ var j = i; // hold a scoped reference that can be used in the async callbacks
2544
+
2545
+ if (_is.promise(promises[j])) {
2546
+ promises[j].then(function () {
2547
+ pushResult(j, _.fn.arg2arr(arguments));
2548
+ }, function () {
2549
+ if (rejected) return;
2550
+ rejected = true;
2551
+ d.reject.apply(d, _.fn.arg2arr(arguments));
2552
+ });
2553
+ } else {
2554
+ // if we were supplied something that was not a promise then just add it as a fulfilled result
2555
+ pushResult(j, [promises[j]]);
2556
+ }
2557
+ };
2558
 
2559
+ for (; i < l; i++) {
2560
+ var _ret = _loop();
 
 
 
 
2561
 
2562
+ if (_ret === "break") break;
2563
+ }
2564
+ })();
2565
+ } else {
2566
+ d.resolve(results);
2567
+ }
 
 
 
 
 
 
 
 
 
 
 
 
2568
 
2569
+ return d.promise();
2570
+ };
2571
+ /**
2572
+ * @summary Waits for all promises to complete before resolving with an array containing the outcome of each.
2573
+ * @memberof FooGallery.utils.fn.
2574
+ * @function allSettled
2575
+ * @param {Promise[]} promises - The array of promises to wait for.
2576
+ * @returns {Promise}
2577
+ */
 
 
 
 
 
 
 
 
 
 
 
2578
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2579
 
2580
+ _.fn.allSettled = function (promises) {
2581
+ var d = $.Deferred(),
2582
+ results = [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2583
 
2584
+ if (_is.array(promises) && promises.length > 0) {
2585
+ (function () {
2586
+ /**
2587
+ * Sets the value in the results array using the status and args.
2588
+ * @ignore
2589
+ * @param {number} index
2590
+ * @param {string} status
2591
+ * @param {Array} args
2592
+ */
2593
+ var setResult = function setResult(index, status, args) {
2594
+ results[index] = {
2595
+ status: status
2596
+ };
2597
+
2598
+ if (args.length > 0) {
2599
+ var prop = status === "rejected" ? "reason" : "value";
2600
+ results[index][prop] = args.length === 1 ? args[0] : args;
2601
+ }
2602
+
2603
+ remaining--;
2604
+ if (!remaining) d.resolve(results);
2605
+ };
 
 
2606
 
2607
+ var remaining = promises.length;
2608
+ var i = 0,
2609
+ l = promises.length;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2610
 
2611
+ var _loop2 = function _loop2() {
2612
+ var j = i; // hold a scoped reference that can be used in the async callbacks
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2613
 
2614
+ if (_is.promise(promises[j])) {
2615
+ promises[j].then(function () {
2616
+ setResult(j, "fulfilled", _.fn.arg2arr(arguments));
2617
+ }, function () {
2618
+ setResult(j, "rejected", _.fn.arg2arr(arguments));
2619
+ });
2620
+ } else {
2621
+ // if we were supplied something that was not a promise then just add it as a fulfilled result
2622
+ setResult(j, "fulfilled", [promises[j]]);
2623
+ }
2624
+ };
 
 
 
 
 
 
 
 
 
 
 
 
2625
 
2626
+ for (; i < l; i++) {
2627
+ _loop2();
2628
+ }
2629
+ })();
2630
+ } else {
2631
+ d.resolve(results);
2632
+ }
 
 
 
 
 
 
 
 
 
 
 
2633
 
2634
+ return d.promise();
2635
+ };
2636
+ })( // dependencies
2637
+ FooGallery.utils.$, FooGallery.utils, FooGallery.utils.is);
2638
+
2639
+ (function (_, _is) {
2640
+ // only register methods if this version is the current version
2641
+ if (_.version !== '1.0.0') return;
2642
+ /**
2643
+ * @summary Contains common url utility methods.
2644
+ * @memberof FooGallery.utils.
2645
+ * @namespace url
2646
+ */
2647
+
2648
+ _.url = {}; // used for parsing a url into it's parts.
2649
+
2650
+ var _a = document.createElement('a');
2651
+ /**
2652
+ * @summary Parses the supplied url into an object containing it's component parts.
2653
+ * @memberof FooGallery.utils.url.
2654
+ * @function parts
2655
+ * @param {string} url - The url to parse.
2656
+ * @returns {FooGallery.utils.url~Parts}
2657
+ * @example {@run true}
2658
+ * // alias the FooGallery.utils.url namespace
2659
+ * var _url = FooGallery.utils.url;
2660
+ *
2661
+ * console.log( _url.parts( "http://example.com/path/?param=true#something" ) ); // => {"hash":"#something", ...}
2662
+ */
2663
+
2664
+
2665
+ _.url.parts = function (url) {
2666
+ _a.href = url;
2667
+ var port = _a.port ? _a.port : ["http:", "https:"].indexOf(_a.protocol) !== -1 ? _a.protocol === "https:" ? "443" : "80" : "",
2668
+ host = _a.hostname + (port ? ":" + port : ""),
2669
+ origin = _a.origin ? _a.origin : _a.protocol + "//" + host,
2670
+ pathname = _a.pathname.slice(0, 1) === "/" ? _a.pathname : "/" + _a.pathname;
2671
+ return {
2672
+ hash: _a.hash,
2673
+ host: host,
2674
+ hostname: _a.hostname,
2675
+ href: _a.href,
2676
+ origin: origin,
2677
+ pathname: pathname,
2678
+ port: port,
2679
+ protocol: _a.protocol,
2680
+ search: _a.search
2681
+ };
2682
+ };
2683
+ /**
2684
+ * @summary Given a <code>url</code> that could be relative or full this ensures a full url is returned.
2685
+ * @memberof FooGallery.utils.url.
2686
+ * @function full
2687
+ * @param {string} url - The url to ensure is full.
2688
+ * @returns {?string} `null` if the given `path` is not a string or empty.
2689
+ * @description Given a full url this will simply return it however if given a relative url this will create a full url using the current location to fill in the blanks.
2690
+ * @example {@run true}
2691
+ * // alias the FooGallery.utils.url namespace
2692
+ * var _url = FooGallery.utils.url;
2693
+ *
2694
+ * console.log( _url.full( "http://example.com/path/" ) ); // => "http://example.com/path/"
2695
+ * console.log( _url.full( "/path/" ) ); // => "{protocol}//{host}/path/"
2696
+ * console.log( _url.full( "path/" ) ); // => "{protocol}//{host}/{pathname}/path/"
2697
+ * console.log( _url.full( "../path/" ) ); // => "{protocol}//{host}/{calculated pathname}/path/"
2698
+ * console.log( _url.full() ); // => null
2699
+ * console.log( _url.full( 123 ) ); // => null
2700
+ */
2701
+
2702
+
2703
+ _.url.full = function (url) {
2704
+ if (!_is.string(url) || _is.empty(url)) return null;
2705
+ _a.href = url;
2706
+ return _a.href;
2707
+ };
2708
+ /**
2709
+ * @summary Gets or sets a parameter in the given <code>search</code> string.
2710
+ * @memberof FooGallery.utils.url.
2711
+ * @function param
2712
+ * @param {string} search - The search string to use (usually `location.search`).
2713
+ * @param {string} key - The key of the parameter.
2714
+ * @param {?string} [value] - The value to set for the parameter. If not provided the current value for the `key` is returned.
2715
+ * @returns {?string} The value of the `key` in the given `search` string if no `value` is supplied or `null` if the `key` does not exist.
2716
+ * @returns {string} A modified `search` string if a `value` is supplied.
2717
+ * @example <caption>Shows how to retrieve a parameter value from a search string.</caption>{@run true}
2718
+ * // alias the FooGallery.utils.url namespace
2719
+ * var _url = FooGallery.utils.url,
2720
+ * // create a search string to test
2721
+ * search = "?wmode=opaque&autoplay=1";
2722
+ *
2723
+ * console.log( _url.param( search, "wmode" ) ); // => "opaque"
2724
+ * console.log( _url.param( search, "autoplay" ) ); // => "1"
2725
+ * console.log( _url.param( search, "nonexistent" ) ); // => null
2726
+ * @example <caption>Shows how to set a parameter value in the given search string.</caption>{@run true}
2727
+ * // alias the FooGallery.utils.url namespace
2728
+ * var _url = FooGallery.utils.url,
2729
+ * // create a search string to test
2730
+ * search = "?wmode=opaque&autoplay=1";
2731
+ *
2732
+ * console.log( _url.param( search, "wmode", "window" ) ); // => "?wmode=window&autoplay=1"
2733
+ * console.log( _url.param( search, "autoplay", "0" ) ); // => "?wmode=opaque&autoplay=0"
2734
+ * console.log( _url.param( search, "v", "2" ) ); // => "?wmode=opaque&autoplay=1&v=2"
2735
+ */
2736
+
2737
+
2738
+ _.url.param = function (search, key, value) {
2739
+ if (!_is.string(search) || !_is.string(key) || _is.empty(key)) return search;
2740
+ var regex, match, result, param;
2741
+
2742
+ if (_is.undef(value)) {
2743
+ regex = new RegExp('[?|&]' + key + '=([^&;]+?)(&|#|;|$)'); // regex to match the key and it's value but only capture the value
2744
+
2745
+ match = regex.exec(search) || ["", ""]; // match the param otherwise return an empty string match
2746
+
2747
+ result = match[1].replace(/\+/g, '%20'); // replace any + character's with spaces
2748
+
2749
+ return _is.string(result) && !_is.empty(result) ? decodeURIComponent(result) : null; // decode the result otherwise return null
2750
+ }
2751
 
2752
+ if (_is.empty(value)) {
2753
+ regex = new RegExp('^([^#]*\?)(([^#]*)&)?' + key + '(\=[^&#]*)?(&|#|$)');
2754
+ result = search.replace(regex, '$1$3$5').replace(/^([^#]*)((\?)&|\?(#|$))/, '$1$3$4');
2755
+ } else {
2756
+ regex = new RegExp('([?&])' + key + '[^&]*'); // regex to match the key and it's current value but only capture the preceding ? or & char
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2757
 
2758
+ param = key + '=' + encodeURIComponent(value);
2759
+ result = search.replace(regex, '$1' + param); // replace any existing instance of the key with the new value
2760
+ // If nothing was replaced, then add the new param to the end
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2761
 
2762
+ if (result === search && !regex.test(result)) {
2763
+ // if no replacement occurred and the parameter is not currently in the result then add it
2764
+ result += (result.indexOf("?") !== -1 ? '&' : '?') + param;
2765
+ }
2766
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
2767
 
2768
+ return result;
2769
+ }; //######################
2770
+ //## Type Definitions ##
2771
+ //######################
2772
+
2773
+ /**
2774
+ * @summary A plain JavaScript object returned by the {@link FooGallery.utils.url.parts} method.
2775
+ * @typedef {Object} FooGallery.utils.url~Parts
2776
+ * @property {string} hash - A string containing a `#` followed by the fragment identifier of the URL.
2777
+ * @property {string} host - A string containing the host, that is the hostname, a `:`, and the port of the URL.
2778
+ * @property {string} hostname - A string containing the domain of the URL.
2779
+ * @property {string} href - A string containing the entire URL.
2780
+ * @property {string} origin - A string containing the canonical form of the origin of the specific location.
2781
+ * @property {string} pathname - A string containing an initial `/` followed by the path of the URL.
2782
+ * @property {string} port - A string containing the port number of the URL.
2783
+ * @property {string} protocol - A string containing the protocol scheme of the URL, including the final `:`.
2784
+ * @property {string} search - A string containing a `?` followed by the parameters of the URL. Also known as "querystring".
2785
+ * @see {@link FooGallery.utils.url.parts} for example usage.
2786
+ */
2787
+
2788
+ })( // dependencies
2789
+ FooGallery.utils, FooGallery.utils.is);
2790
 
2791
+ (function (_, _is, _fn) {
2792
+ // only register methods if this version is the current version
2793
+ if (_.version !== '1.0.0') return;
2794
+ /**
2795
+ * @summary Contains common string utility methods.
2796
+ * @memberof FooGallery.utils.
2797
+ * @namespace str
2798
+ */
2799
+
2800
+ _.str = {};
2801
+ /**
2802
+ * @summary Removes whitespace from both ends of the target string.
2803
+ * @memberof FooGallery.utils.str.
2804
+ * @function trim
2805
+ * @param {string} target - The string to trim.
2806
+ * @returns {string|null} Returns `null` if the supplied target is not a string.
2807
+ */
2808
+
2809
+ _.str.trim = function (target) {
2810
+ return _is.string(target) ? target.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '') : null;
2811
+ };
2812
+ /**
2813
+ * @summary Converts the given `target` to camel case.
2814
+ * @memberof FooGallery.utils.str.
2815
+ * @function camel
2816
+ * @param {string} target - The string to camel case.
2817
+ * @returns {string}
2818
+ * @example {@run true}
2819
+ * // alias the FooGallery.utils.str namespace
2820
+ * var _str = FooGallery.utils.str;
2821
+ *
2822
+ * console.log( _str.camel( "max-width" ) ); // => "maxWidth"
2823
+ * console.log( _str.camel( "max--width" ) ); // => "maxWidth"
2824
+ * console.log( _str.camel( "max Width" ) ); // => "maxWidth"
2825
+ * console.log( _str.camel( "Max_width" ) ); // => "maxWidth"
2826
+ * console.log( _str.camel( "MaxWidth" ) ); // => "maxWidth"
2827
+ * console.log( _str.camel( "Abbreviations like CSS are left intact" ) ); // => "abbreviationsLikeCSSAreLeftIntact"
2828
+ */
2829
+
2830
+
2831
+ _.str.camel = function (target) {
2832
+ if (!_is.string(target)) return target;
2833
+ if (target.toUpperCase() === target) return target.toLowerCase();
2834
+ return target.replace(/^([A-Z])|[-\s_]+(\w)/g, function (match, p1, p2) {
2835
+ if (_is.string(p2)) return p2.toUpperCase();
2836
+ return p1.toLowerCase();
2837
+ });
2838
+ };
2839
+ /**
2840
+ * @summary Converts the given `target` to kebab case. Non-alphanumeric characters are converted to `-`.
2841
+ * @memberof FooGallery.utils.str.
2842
+ * @function kebab
2843
+ * @param {string} target - The string to kebab case.
2844
+ * @returns {string}
2845
+ * @example {@run true}
2846
+ * // alias the FooGallery.utils.str namespace
2847
+ * var _str = FooGallery.utils.str;
2848
+ *
2849
+ * console.log( _str.kebab( "max-width" ) ); // => "max-width"
2850
+ * console.log( _str.kebab( "max--width" ) ); // => "max-width"
2851
+ * console.log( _str.kebab( "max Width" ) ); // => "max-width"
2852
+ * console.log( _str.kebab( "Max_width" ) ); // => "max-width"
2853
+ * console.log( _str.kebab( "MaxWidth" ) ); // => "max-width"
2854
+ * console.log( _str.kebab( "Non-alphanumeric ch@racters are converted to dashes!" ) ); // => "non-alphanumeric-ch-racters-are-converted-to-dashes"
2855
+ */
2856
+
2857
+
2858
+ _.str.kebab = function (target) {
2859
+ if (!_is.string(target)) return target;
2860
+ return target.match(/[A-Z]{2,}(?=[A-Z][a-z0-9]*|\b)|[A-Z]?[a-z0-9]*|[A-Z]|[0-9]+/g).filter(Boolean).map(function (x) {
2861
+ return x.toLowerCase();
2862
+ }).join('-');
2863
+ };
2864
+ /**
2865
+ * @summary Checks if the `target` contains the given `substr`.
2866
+ * @memberof FooGallery.utils.str.
2867
+ * @function contains
2868
+ * @param {string} target - The string to check.
2869
+ * @param {string} substr - The string to check for.
2870
+ * @param {boolean} [ignoreCase=false] - Whether or not to ignore casing when performing the check.
2871
+ * @returns {boolean} `true` if the `target` contains the given `substr`.
2872
+ * @example {@run true}
2873
+ * // alias the FooGallery.utils.str namespace
2874
+ * var _str = FooGallery.utils.str,
2875
+ * // create a string to test
2876
+ * target = "To be, or not to be, that is the question.";
2877
+ *
2878
+ * console.log( _str.contains( target, "To be" ) ); // => true
2879
+ * console.log( _str.contains( target, "question" ) ); // => true
2880
+ * console.log( _str.contains( target, "no" ) ); // => true
2881
+ * console.log( _str.contains( target, "nonexistent" ) ); // => false
2882
+ * console.log( _str.contains( target, "TO BE" ) ); // => false
2883
+ * console.log( _str.contains( target, "TO BE", true ) ); // => true
2884
+ */
2885
+
2886
+
2887
+ _.str.contains = function (target, substr, ignoreCase) {
2888
+ if (!_is.string(target) || _is.empty(target) || !_is.string(substr) || _is.empty(substr)) return false;
2889
+ return substr.length <= target.length && (!!ignoreCase ? target.toUpperCase().indexOf(substr.toUpperCase()) : target.indexOf(substr)) !== -1;
2890
+ };
2891
+ /**
2892
+ * @summary Checks if the `target` contains the given `word`.
2893
+ * @memberof FooGallery.utils.str.
2894
+ * @function containsWord
2895
+ * @param {string} target - The string to check.
2896
+ * @param {string} word - The word to check for.
2897
+ * @param {boolean} [ignoreCase=false] - Whether or not to ignore casing when performing the check.
2898
+ * @returns {boolean} `true` if the `target` contains the given `word`.
2899
+ * @description This method differs from {@link FooGallery.utils.str.contains} in that it searches for whole words by splitting the `target` string on word boundaries (`\b`) and then comparing the individual parts.
2900
+ * @example {@run true}
2901
+ * // alias the FooGallery.utils.str namespace
2902
+ * var _str = FooGallery.utils.str,
2903
+ * // create a string to test
2904
+ * target = "To be, or not to be, that is the question.";
2905
+ *
2906
+ * console.log( _str.containsWord( target, "question" ) ); // => true
2907
+ * console.log( _str.containsWord( target, "no" ) ); // => false
2908
+ * console.log( _str.containsWord( target, "NOT" ) ); // => false
2909
+ * console.log( _str.containsWord( target, "NOT", true ) ); // => true
2910
+ * console.log( _str.containsWord( target, "nonexistent" ) ); // => false
2911
+ */
2912
+
2913
+
2914
+ _.str.containsWord = function (target, word, ignoreCase) {
2915
+ if (!_is.string(target) || _is.empty(target) || !_is.string(word) || _is.empty(word) || target.length < word.length) return false;
2916
+ var parts = target.split(/\W/);
2917
+ var i = 0,
2918
+ len = parts.length;
2919
+
2920
+ for (; i < len; i++) {
2921
+ if (ignoreCase ? parts[i].toUpperCase() === word.toUpperCase() : parts[i] === word) return true;
2922
+ }
2923
 
2924
+ return false;
2925
+ };
2926
+ /**
2927
+ * @summary Checks if the `target` ends with the given `substr`.
2928
+ * @memberof FooGallery.utils.str.
2929
+ * @function endsWith
2930
+ * @param {string} target - The string to check.
2931
+ * @param {string} substr - The substr to check for.
2932
+ * @returns {boolean} `true` if the `target` ends with the given `substr`.
2933
+ * @example {@run true}
2934
+ * // alias the FooGallery.utils.str namespace
2935
+ * var _str = FooGallery.utils.str;
2936
+ *
2937
+ * console.log( _str.endsWith( "something", "g" ) ); // => true
2938
+ * console.log( _str.endsWith( "something", "ing" ) ); // => true
2939
+ * console.log( _str.endsWith( "something", "no" ) ); // => false
2940
+ */
2941
+
2942
+
2943
+ _.str.endsWith = function (target, substr) {
2944
+ if (!_is.string(target) || !_is.string(substr) || substr.length > target.length) return false;
2945
+ return target.slice(target.length - substr.length) === substr;
2946
+ };
2947
+ /**
2948
+ * @summary Checks if the `target` starts with the given `substr`.
2949
+ * @memberof FooGallery.utils.str.
2950
+ * @function startsWith
2951
+ * @param {string} target - The string to check.
2952
+ * @param {string} substr - The substr to check for.
2953
+ * @returns {boolean} `true` if the `target` starts with the given `substr`.
2954
+ * @example {@run true}
2955
+ * // alias the FooGallery.utils.str namespace
2956
+ * var _str = FooGallery.utils.str;
2957
+ *
2958
+ * console.log( _str.startsWith( "something", "s" ) ); // => true
2959
+ * console.log( _str.startsWith( "something", "some" ) ); // => true
2960
+ * console.log( _str.startsWith( "something", "no" ) ); // => false
2961
+ */
2962
+
2963
+
2964
+ _.str.startsWith = function (target, substr) {
2965
+ if (_is.empty(target) || _is.empty(substr)) return false;
2966
+ return target.slice(0, substr.length) === substr;
2967
+ };
2968
+ /**
2969
+ * @summary Escapes the `target` for use in a regular expression.
2970
+ * @memberof FooGallery.utils.str.
2971
+ * @function escapeRegExp
2972
+ * @param {string} target - The string to escape.
2973
+ * @returns {string}
2974
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
2975
+ */
2976
+
2977
+
2978
+ _.str.escapeRegExp = function (target) {
2979
+ if (!_is.string(target)) return target;
2980
+ return target.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2981
+ };
2982
+ /**
2983
+ * @summary Generates a 32 bit FNV-1a hash from the given `target`.
2984
+ * @memberof FooGallery.utils.str.
2985
+ * @function fnv1a
2986
+ * @param {string} target - The string to generate a hash from.
2987
+ * @returns {?number} `null` if the `target` is not a string or empty otherwise a 32 bit FNV-1a hash.
2988
+ * @example {@run true}
2989
+ * // alias the FooGallery.utils.str namespace
2990
+ * var _str = FooGallery.utils.str;
2991
+ *
2992
+ * console.log( _str.fnv1a( "Some string to generate a hash for." ) ); // => 207568994
2993
+ * console.log( _str.fnv1a( "Some string to generate a hash for" ) ); // => 1350435704
2994
+ * @see {@link https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function|Fowler–Noll–Vo hash function}
2995
+ */
2996
+
2997
+
2998
+ _.str.fnv1a = function (target) {
2999
+ if (!_is.string(target) || _is.empty(target)) return null;
3000
+ var i,
3001
+ l,
3002
+ hval = 0x811c9dc5;
3003
+
3004
+ for (i = 0, l = target.length; i < l; i++) {
3005
+ hval ^= target.charCodeAt(i);
3006
+ hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
3007
+ }
3008
 
3009
+ return hval >>> 0;
3010
+ };
3011
+ /**
3012
+ * @summary Returns the remainder of the `target` split on the first index of the given `substr`.
3013
+ * @memberof FooGallery.utils.str.
3014
+ * @function from
3015
+ * @param {string} target - The string to split.
3016
+ * @param {string} substr - The substring to split on.
3017
+ * @returns {?string} `null` if the given `substr` does not exist within the `target`.
3018
+ * @example {@run true}
3019
+ * // alias the FooGallery.utils.str namespace
3020
+ * var _str = FooGallery.utils.str,
3021
+ * // create a string to test
3022
+ * target = "To be, or not to be, that is the question.";
3023
+ *
3024
+ * console.log( _str.from( target, "no" ) ); // => "t to be, that is the question."
3025
+ * console.log( _str.from( target, "that" ) ); // => " is the question."
3026
+ * console.log( _str.from( target, "question" ) ); // => "."
3027
+ * console.log( _str.from( target, "nonexistent" ) ); // => null
3028
+ */
3029
+
3030
+
3031
+ _.str.from = function (target, substr) {
3032
+ return _.str.contains(target, substr) ? target.substring(target.indexOf(substr) + substr.length) : null;
3033
+ };
3034
+ /**
3035
+ * @summary Joins any number of strings using the given `separator`.
3036
+ * @memberof FooGallery.utils.str.
3037
+ * @function join
3038
+ * @param {string} separator - The separator to use to join the strings.
3039
+ * @param {string} part - The first string to join.
3040
+ * @param {...string} [partN] - Any number of additional strings to join.
3041
+ * @returns {?string}
3042
+ * @description This method differs from using the standard `Array.prototype.join` function to join strings in that it ignores empty parts and checks to see if each starts with the supplied `separator`. If the part starts with the `separator` it is removed before appending it to the final result.
3043
+ * @example {@run true}
3044
+ * // alias the FooGallery.utils.str namespace
3045
+ * var _str = FooGallery.utils.str;
3046
+ *
3047
+ * console.log( _str.join( "_", "all", "in", "one" ) ); // => "all_in_one"
3048
+ * console.log( _str.join( "_", "all", "_in", "one" ) ); // => "all_in_one"
3049
+ * console.log( _str.join( "/", "http://", "/example.com/", "/path/to/image.png" ) ); // => "http://example.com/path/to/image.png"
3050
+ * console.log( _str.join( "/", "http://", "/example.com", "/path/to/image.png" ) ); // => "http://example.com/path/to/image.png"
3051
+ * console.log( _str.join( "/", "http://", "example.com", "path/to/image.png" ) ); // => "http://example.com/path/to/image.png"
3052
+ */
3053
+
3054
+
3055
+ _.str.join = function (separator, part, partN) {
3056
+ if (!_is.string(separator) || !_is.string(part)) return null;
3057
+
3058
+ var parts = _fn.arg2arr(arguments);
3059
+
3060
+ separator = parts.shift();
3061
+ var i,
3062
+ l,
3063
+ result = parts.shift();
3064
+
3065
+ for (i = 0, l = parts.length; i < l; i++) {
3066
+ part = parts[i];
3067
+ if (_is.empty(part)) continue;
3068
+
3069
+ if (_.str.endsWith(result, separator)) {
3070
+ result = result.slice(0, result.length - separator.length);
3071
+ }
3072
+
3073
+ if (_.str.startsWith(part, separator)) {
3074
+ part = part.slice(separator.length);
3075
+ }
3076
+
3077
+ result += separator + part;
3078
+ }
3079
 
3080
+ return result;
3081
+ };
3082
+ /**
3083
+ * @summary Returns the first part of the `target` split on the first index of the given `substr`.
3084
+ * @memberof FooGallery.utils.str.
3085
+ * @function until
3086
+ * @param {string} target - The string to split.
3087
+ * @param {string} substr - The substring to split on.
3088
+ * @returns {string} The `target` if the `substr` does not exist.
3089
+ * @example {@run true}
3090
+ * // alias the FooGallery.utils.str namespace
3091
+ * var _str = FooGallery.utils.str,
3092
+ * // create a string to test
3093
+ * target = "To be, or not to be, that is the question.";
3094
+ *
3095
+ * console.log( _str.until( target, "no" ) ); // => "To be, or "
3096
+ * console.log( _str.until( target, "that" ) ); // => "To be, or not to be, "
3097
+ * console.log( _str.until( target, "question" ) ); // => "To be, or not to be, that is the "
3098
+ * console.log( _str.until( target, "nonexistent" ) ); // => "To be, or not to be, that is the question."
3099
+ */
3100
+
3101
+
3102
+ _.str.until = function (target, substr) {
3103
+ return _.str.contains(target, substr) ? target.substring(0, target.indexOf(substr)) : target;
3104
+ };
3105
+ /**
3106
+ * @summary A basic string formatter that can use both index and name based placeholders but handles only string or number replacements.
3107
+ * @memberof FooGallery.utils.str.
3108
+ * @function format
3109
+ * @param {string} target - The format string containing any placeholders to replace.
3110
+ * @param {string|number|Object|Array} arg1 - The first value to format the target with. If an object is supplied it's properties are used to match named placeholders. If an array, string or number is supplied it's values are used to match any index placeholders.
3111
+ * @param {...(string|number)} [argN] - Any number of additional strings or numbers to format the target with.
3112
+ * @returns {string} The string formatted with the supplied arguments.
3113
+ * @description This method allows you to supply the replacements as an object when using named placeholders or as an array or additional arguments when using index placeholders.
3114
+ *
3115
+ * This does not perform a simultaneous replacement of placeholders, which is why it's referred to as a basic formatter. This means replacements that contain placeholders within there value could end up being replaced themselves as seen in the last example.
3116
+ * @example {@caption The following shows how to use index placeholders.}{@run true}
3117
+ * // alias the FooGallery.utils.str namespace
3118
+ * var _str = FooGallery.utils.str,
3119
+ * // create a format string using index placeholders
3120
+ * format = "Hello, {0}, are you feeling {1}?";
3121
+ *
3122
+ * console.log( _str.format( format, "Steve", "OK" ) ); // => "Hello, Steve, are you feeling OK?"
3123
+ * // or
3124
+ * console.log( _str.format( format, [ "Steve", "OK" ] ) ); // => "Hello, Steve, are you feeling OK?"
3125
+ * @example {@caption While the above works perfectly fine the downside is that the placeholders provide no clues as to what should be supplied as a replacement value, this is were supplying an object and using named placeholders steps in.}{@run true}
3126
+ * // alias the FooGallery.utils.str namespace
3127
+ * var _str = FooGallery.utils.str,
3128
+ * // create a format string using named placeholders
3129
+ * format = "Hello, {name}, are you feeling {adjective}?";
3130
+ *
3131
+ * console.log( _str.format( format, {name: "Steve", adjective: "OK"} ) ); // => "Hello, Steve, are you feeling OK?"
3132
+ * @example {@caption The following demonstrates the issue with not performing a simultaneous replacement of placeholders.}{@run true}
3133
+ * // alias the FooGallery.utils.str namespace
3134
+ * var _str = FooGallery.utils.str;
3135
+ *
3136
+ * console.log( _str.format("{0}{1}", "{1}", "{0}") ); // => "{0}{0}"
3137
+ *
3138
+ * // If the replacement happened simultaneously the result would be "{1}{0}" but this method executes
3139
+ * // replacements synchronously as seen below:
3140
+ *
3141
+ * // "{0}{1}".replace( "{0}", "{1}" )
3142
+ * // => "{1}{1}".replace( "{1}", "{0}" )
3143
+ * // => "{0}{0}"
3144
+ */
3145
+
3146
+
3147
+ _.str.format = function (target, arg1, argN) {
3148
+ var args = _fn.arg2arr(arguments);
3149
+
3150
+ target = args.shift(); // remove the target from the args
3151
+
3152
+ if (_is.string(target) && args.length > 0) {
3153
+ if (args.length === 1 && (_is.array(args[0]) || _is.object(args[0]))) {
3154
+ args = args[0];
3155
+ }
3156
+
3157
+ _.each(args, function (value, placeholder) {
3158
+ target = target.replace(new RegExp("\\{" + placeholder + "\\}", "gi"), value + "");
3159
+ });
3160
+ }
3161
 
3162
+ return target;
3163
+ };
3164
+ })( // dependencies
3165
+ FooGallery.utils, FooGallery.utils.is, FooGallery.utils.fn);
3166
+
3167
+ (function ($, _, _is, _fn, _str) {
3168
+ // only register methods if this version is the current version
3169
+ if (_.version !== '1.0.0') return;
3170
+ /**
3171
+ * @summary Contains common object utility methods.
3172
+ * @memberof FooGallery.utils.
3173
+ * @namespace obj
3174
+ */
3175
+
3176
+ _.obj = {};
3177
+ /**
3178
+ * @summary Creates a new object with the specified prototype.
3179
+ * @memberof FooGallery.utils.obj.
3180
+ * @function create
3181
+ * @param {Object} proto - The object which should be the prototype of the newly-created object.
3182
+ * @returns {Object} A new object with the specified prototype.
3183
+ * @description This is a basic implementation of the {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create|Object.create} method.
3184
+ */
3185
+
3186
+ _.obj.create = function (proto) {
3187
+ if (!_is.object(proto)) throw TypeError('Argument must be an object');
3188
+
3189
+ function Obj() {}
3190
+
3191
+ Obj.prototype = proto;
3192
+ return new Obj();
3193
+ };
3194
+ /**
3195
+ * @summary Merge the contents of two or more objects together into the first `target` object.
3196
+ * @memberof FooGallery.utils.obj.
3197
+ * @function extend
3198
+ * @param {Object} target - The object to merge properties into.
3199
+ * @param {Object} object - An object containing properties to merge.
3200
+ * @param {...Object} [objectN] - Additional objects containing properties to merge.
3201
+ * @returns {Object} The `target` merged with the contents from any additional objects.
3202
+ * @description This does not merge arrays by index as jQuery does, it treats them as a single property and replaces the array with a shallow copy of the new one.
3203
+ *
3204
+ * This method makes use of the {@link FooGallery.utils.obj.merge} method internally.
3205
+ * @example {@run true}
3206
+ * // alias the FooGallery.utils.obj namespace
3207
+ * var _obj = FooGallery.utils.obj,
3208
+ * // create some objects to merge
3209
+ * defaults = {"name": "My Object", "enabled": false, "arr": [1,2,3]},
3210
+ * options = {"enabled": true, "something": 123, "arr": [4,5,6]};
3211
+ *
3212
+ * // merge the two objects into a new third one without modifying either of the originals
3213
+ * var settings = _obj.extend( {}, defaults, options );
3214
+ *
3215
+ * console.log( settings ); // => {"name": "My Object", "enabled": true, "arr": [4,5,6], "something": 123}
3216
+ * console.log( defaults ); // => {"name": "My Object", "enabled": true, "arr": [1,2,3]}
3217
+ * console.log( options ); // => {"enabled": true, "arr": [4,5,6], "something": 123}
3218
+ */
3219
+
3220
+
3221
+ _.obj.extend = function (target, object, objectN) {
3222
+ target = _is.object(target) ? target : {};
3223
+
3224
+ var objects = _fn.arg2arr(arguments);
3225
+
3226
+ objects.shift();
3227
+
3228
+ _.each(objects, function (object) {
3229
+ _.obj.merge(target, object);
3230
+ });
3231
 
3232
+ return target;
3233
+ };
3234
+ /**
3235
+ * @summary Merge the contents of two objects together into the first `target` object.
3236
+ * @memberof FooGallery.utils.obj.
3237
+ * @function merge
3238
+ * @param {Object} target - The object to merge properties into.
3239
+ * @param {Object} object - The object containing properties to merge.
3240
+ * @returns {Object} The `target` merged with the contents from the `object`.
3241
+ * @description This does not merge arrays by index as jQuery does, it treats them as a single property and replaces the array with a shallow copy of the new one.
3242
+ *
3243
+ * This method is used internally by the {@link FooGallery.utils.obj.extend} method.
3244
+ * @example {@run true}
3245
+ * // alias the FooGallery.utils.obj namespace
3246
+ * var _obj = FooGallery.utils.obj,
3247
+ * // create some objects to merge
3248
+ * target = {"name": "My Object", "enabled": false, "arr": [1,2,3]},
3249
+ * object = {"enabled": true, "something": 123, "arr": [4,5,6]};
3250
+ *
3251
+ * console.log( _obj.merge( target, object ) ); // => {"name": "My Object", "enabled": true, "arr": [4,5,6], "something": 123}
3252
+ */
3253
+
3254
+
3255
+ _.obj.merge = function (target, object) {
3256
+ target = _is.hash(target) ? target : {};
3257
+ object = _is.hash(object) ? object : {};
3258
+
3259
+ for (var prop in object) {
3260
+ if (object.hasOwnProperty(prop)) {
3261
+ if (_is.hash(object[prop])) {
3262
+ target[prop] = _is.hash(target[prop]) ? target[prop] : {};
3263
+
3264
+ _.obj.merge(target[prop], object[prop]);
3265
+ } else if (_is.array(object[prop])) {
3266
+ target[prop] = object[prop].slice();
3267
+ } else {
3268
+ target[prop] = object[prop];
3269
+ }
3270
+ }
3271
+ }
3272
 
3273
+ return target;
3274
+ };
3275
+ /**
3276
+ * @summary Merge the validated properties of the `object` into the `target` using the optional `mappings`.
3277
+ * @memberof FooGallery.utils.obj.
3278
+ * @function mergeValid
3279
+ * @param {Object} target - The object to merge properties into.
3280
+ * @param {FooGallery.utils.obj~Validators} validators - An object containing validators for the `target` object properties.
3281
+ * @param {Object} object - The object containing properties to merge.
3282
+ * @param {FooGallery.utils.obj~Mappings} [mappings] - An object containing property name mappings.
3283
+ * @returns {Object} The modified `target` object containing any valid properties from the supplied `object`.
3284
+ * @example {@caption Shows the basic usage for this method and shows how invalid properties or those with no corresponding validator are ignored.}{@run true}
3285
+ * // alias the FooGallery.utils.obj and FooGallery.utils.is namespaces
3286
+ * var _obj = FooGallery.utils.obj,
3287
+ * _is = FooGallery.utils.is;
3288
+ *
3289
+ * //create the target object and it's validators
3290
+ * var target = {"name":"John","location":"unknown"},
3291
+ * validators = {"name":_is.string,"location":_is.string};
3292
+ *
3293
+ * // create the object to merge into the target
3294
+ * var object = {
3295
+ * "name": 1234, // invalid
3296
+ * "location": "Liverpool", // updated
3297
+ * "notMerged": true // ignored
3298
+ * };
3299
+ *
3300
+ * // merge the object into the target, invalid properties or those with no corresponding validator are ignored.
3301
+ * console.log( _obj.mergeValid( target, validators, object ) ); // => { "name": "John", "location": "Liverpool" }
3302
+ * @example {@caption Shows how to supply a mappings object for this method.}{@run true}
3303
+ * // alias the FooGallery.utils.obj and FooGallery.utils.is namespaces
3304
+ * var _obj = FooGallery.utils.obj,
3305
+ * _is = FooGallery.utils.is;
3306
+ *
3307
+ * //create the target object and it's validators
3308
+ * var target = {"name":"John","location":"unknown"},
3309
+ * validators = {"name":_is.string,"location":_is.string};
3310
+ *
3311
+ * // create the object to merge into the target
3312
+ * var object = {
3313
+ * "name": { // ignored
3314
+ * "proper": "Christopher", // mapped to name if short is invalid
3315
+ * "short": "Chris" // map to name
3316
+ * },
3317
+ * "city": "London" // map to location
3318
+ * };
3319
+ *
3320
+ * // create the mapping object
3321
+ * var mappings = {
3322
+ * "name": [ "name.short", "name.proper" ], // try use the short name and fallback to the proper
3323
+ * "location": "city"
3324
+ * };
3325
+ *
3326
+ * // merge the object into the target using the mappings, invalid properties or those with no corresponding validator are ignored.
3327
+ * console.log( _obj.mergeValid( target, validators, object, mappings ) ); // => { "name": "Chris", "location": "London" }
3328
+ */
3329
+
3330
+
3331
+ _.obj.mergeValid = function (target, validators, object, mappings) {
3332
+ if (!_is.hash(object) || !_is.hash(validators)) return target;
3333
+ validators = _is.hash(validators) ? validators : {};
3334
+ mappings = _is.hash(mappings) ? mappings : {};
3335
+ var prop, maps, value;
3336
+
3337
+ for (prop in validators) {
3338
+ if (!validators.hasOwnProperty(prop) || !_is.fn(validators[prop])) continue;
3339
+ maps = _is.array(mappings[prop]) ? mappings[prop] : _is.string(mappings[prop]) ? [mappings[prop]] : [prop];
3340
+
3341
+ _.each(maps, function (map) {
3342
+ value = _.obj.prop(object, map);
3343
+ if (_is.undef(value)) return; // continue
3344
+
3345
+ if (validators[prop](value)) {
3346
+ _.obj.prop(target, prop, value);
3347
+
3348
+ return false; // break
3349
+ }
3350
+ });
3351
+ }
3352
 
3353
+ return target;
3354
+ };
3355
+ /**
3356
+ * @summary Get or set a property value given its `name`.
3357
+ * @memberof FooGallery.utils.obj.
3358
+ * @function prop
3359
+ * @param {Object} object - The object to inspect for the property.
3360
+ * @param {string} name - The name of the property to fetch. This can be a `.` notated name.
3361
+ * @param {*} [value] - If supplied this is the value to set for the property.
3362
+ * @returns {*} The value for the `name` property, if it does not exist then `undefined`.
3363
+ * @returns {undefined} If a `value` is supplied this method returns nothing.
3364
+ * @example {@caption Shows how to get a property value from an object.}{@run true}
3365
+ * // alias the FooGallery.utils.obj namespace
3366
+ * var _obj = FooGallery.utils.obj,
3367
+ * // create an object to test
3368
+ * object = {
3369
+ * "name": "My Object",
3370
+ * "some": {
3371
+ * "thing": 123
3372
+ * }
3373
+ * };
3374
+ *
3375
+ * console.log( _obj.prop( object, "name" ) ); // => "My Object"
3376
+ * console.log( _obj.prop( object, "some.thing" ) ); // => 123
3377
+ * @example {@caption Shows how to set a property value for an object.}{@run true}
3378
+ * // alias the FooGallery.utils.obj namespace
3379
+ * var _obj = FooGallery.utils.obj,
3380
+ * // create an object to test
3381
+ * object = {
3382
+ * "name": "My Object",
3383
+ * "some": {
3384
+ * "thing": 123
3385
+ * }
3386
+ * };
3387
+ *
3388
+ * _obj.prop( object, "name", "My Updated Object" );
3389
+ * _obj.prop( object, "some.thing", 987 );
3390
+ *
3391
+ * console.log( object ); // => { "name": "My Updated Object", "some": { "thing": 987 } }
3392
+ */
3393
+
3394
+
3395
+ _.obj.prop = function (object, name, value) {
3396
+ if (!_is.object(object) || _is.empty(name)) return;
3397
+ var parts, last;
3398
+
3399
+ if (_is.undef(value)) {
3400
+ if (_str.contains(name, '.')) {
3401
+ parts = name.split('.');
3402
+ last = parts.length - 1;
3403
+
3404
+ _.each(parts, function (part, i) {
3405
+ if (i === last) {
3406
+ value = object[part];
3407
+ } else if (_is.hash(object[part])) {
3408
+ object = object[part];
3409
+ } else {
3410
+ // exit early
3411
+ return false;
3412
+ }
3413
+ });
3414
+ } else if (!_is.undef(object[name])) {
3415
+ value = object[name];
3416
+ }
3417
 
3418
+ return value;
3419
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3420
 
3421
+ if (_str.contains(name, '.')) {
3422
+ parts = name.split('.');
3423
+ last = parts.length - 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3424
 
3425
+ _.each(parts, function (part, i) {
3426
+ if (i === last) {
3427
+ object[part] = value;
3428
+ } else {
3429
+ object = _is.hash(object[part]) ? object[part] : object[part] = {};
3430
+ }
3431
+ });
3432
+ } else if (!_is.undef(object[name])) {
3433
+ object[name] = value;
3434
+ }
3435
+ }; //######################
3436
+ //## Type Definitions ##
3437
+ //######################
3438
+
3439
+ /**
3440
+ * @summary An object used by the {@link FooGallery.utils.obj.mergeValid|mergeValid} method to map new values onto the `target` object.
3441
+ * @typedef {Object.<string,(string|Array.<string>)>} FooGallery.utils.obj~Mappings
3442
+ * @description The mappings object is a single level object. If you want to map a property from/to a child object on either the source or target objects you must supply the name using `.` notation as seen in the below example with the `"name.first"` to `"Name.Short"` mapping.
3443
+ * @example {@caption The basic structure of a mappings object is the below.}
3444
+ * {
3445
+ * "TargetName": "SourceName", // for top level properties
3446
+ * "Child.TargetName": "Child.SourceName" // for child properties
3447
+ * }
3448
+ * @example {@caption Given the following target object.}
3449
+ * var target = {
3450
+ * "name": {
3451
+ * "first": "",
3452
+ * "last": null
3453
+ * },
3454
+ * "age": 0
3455
+ * };
3456
+ * @example {@caption And the following object to merge.}
3457
+ * var object = {
3458
+ * "Name": {
3459
+ * "Full": "Christopher",
3460
+ * "Short": "Chris"
3461
+ * },
3462
+ * "Age": 32
3463
+ * };
3464
+ * @example {@caption The mappings object would look like the below.}
3465
+ * var mappings = {
3466
+ * "name.first": "Name.Short",
3467
+ * "age": "Age"
3468
+ * };
3469
+ * @example {@caption If you want the `"name.first"` property to try to use the `"Name.Short"` value but fallback to `"Name.Proper"` you can specify the mapping value as an array.}
3470
+ * var mappings = {
3471
+ * "name.first": [ "Name.Short", "Name.Proper" ],
3472
+ * "age": "Age"
3473
+ * };
3474
+ */
3475
+
3476
+ /**
3477
+ * @summary An object used by the {@link FooGallery.utils.obj.mergeValid|mergeValid} method to validate properties.
3478
+ * @typedef {Object.<string,function(*):boolean>} FooGallery.utils.obj~Validators
3479
+ * @description The validators object is a single level object. If you want to validate a property of a child object you must supply the name using `.` notation as seen in the below example with the `"name.first"` and `"name.last"` properties.
3480
+ *
3481
+ * Any function that accepts a value to test as the first argument and returns a boolean can be used as a validator. This means the majority of the {@link FooGallery.utils.is} methods can be used directly. If the property supports multiple types just provide your own function as seen with `"name.last"` in the below example.
3482
+ * @example {@caption The basic structure of a validators object is the below.}
3483
+ * {
3484
+ * "PropName": function(*):boolean, // for top level properties
3485
+ * "Child.PropName": function(*):boolean // for child properties
3486
+ * }
3487
+ * @example {@caption Given the following target object.}
3488
+ * var target = {
3489
+ * "name": {
3490
+ * "first": "", // must be a string
3491
+ * "last": null // must be a string or null
3492
+ * },
3493
+ * "age": 0 // must be a number
3494
+ * };
3495
+ * @example {@caption The validators object could be created as seen below.}
3496
+ * // alias the FooGallery.utils.is namespace
3497
+ * var _is = FooGallery.utils.is;
3498
+ *
3499
+ * var validators = {
3500
+ * "name.first": _is.string,
3501
+ * "name.last": function(value){
3502
+ * return _is.string(value) || value === null;
3503
+ * },
3504
+ * "age": _is.number
3505
+ * };
3506
+ */
3507
+
3508
+ })( // dependencies
3509
+ FooGallery.utils.$, FooGallery.utils, FooGallery.utils.is, FooGallery.utils.fn, FooGallery.utils.str);
3510
+
3511
+ (function ($, _, _is) {
3512
+ // only register methods if this version is the current version
3513
+ if (_.version !== '1.0.0') return; // any methods that have dependencies but don't fall into a specific subset or namespace can be added here
3514
+
3515
+ /**
3516
+ * @summary The callback for the {@link FooGallery.utils.ready} method.
3517
+ * @callback FooGallery.utils~readyCallback
3518
+ * @param {jQuery} $ - The instance of jQuery the plugin was registered with.
3519
+ * @this window
3520
+ * @see Take a look at the {@link FooGallery.utils.ready} method for example usage.
3521
+ */
3522
+
3523
+ /**
3524
+ * @summary Waits for the DOM to be accessible and then executes the supplied callback.
3525
+ * @memberof FooGallery.utils.
3526
+ * @function ready
3527
+ * @param {FooGallery.utils~readyCallback} callback - The function to execute once the DOM is accessible.
3528
+ * @example {@caption This method can be used as a replacement for the jQuery ready callback to avoid an error in another script stopping our scripts from running.}
3529
+ * FooGallery.utils.ready(function($){
3530
+ * // do something
3531
+ * });
3532
+ */
3533
+
3534
+ _.ready = function (callback) {
3535
+ function onready() {
3536
+ try {
3537
+ callback.call(window, _.$);
3538
+ } catch (err) {
3539
+ console.error(err);
3540
+ }
3541
+ }
3542
 
3543
+ if (Function('/*@cc_on return true@*/')() ? document.readyState === "complete" : document.readyState !== "loading") onready();else document.addEventListener('DOMContentLoaded', onready, false);
3544
+ };
3545
+ /**
3546
+ * @summary Executed once for each array index or object property until it returns a truthy value.
3547
+ * @callback FooGallery.utils~findCallback
3548
+ * @param {*} value - The current value being iterated over. This could be either an element in an array or the value of an object property.
3549
+ * @param {(number|string)} [key] - The array index or property name of the `value`.
3550
+ * @param {(Object|Array)} [object] - The array or object currently being searched.
3551
+ * @returns {boolean} A truthy value.
3552
+ */
3553
+
3554
+ /**
3555
+ * @summary Returns the value of the first element or property in the provided target that satisfies the provided test function.
3556
+ * @memberof FooGallery.utils.
3557
+ * @function find
3558
+ * @param {(Object|Array)} target - The object or array to search.
3559
+ * @param {FooGallery.utils~findCallback} callback - A function to execute for each value in the target.
3560
+ * @param {*} [thisArg] - The `this` value within the `callback`.
3561
+ * @returns {*} The value of the first element or property in the provided target that satisfies the provided test function. Otherwise, `undefined` is returned.
3562
+ */
3563
+
3564
+
3565
+ _.find = function (target, callback, thisArg) {
3566
+ if (!_is.fn(callback)) return;
3567
+ thisArg = _is.undef(thisArg) ? callback : thisArg;
3568
+ var i, l;
3569
+
3570
+ if (_is.array(target)) {
3571
+ for (i = 0, l = target.length; i < l; i++) {
3572
+ if (callback.call(thisArg, target[i], i, target)) {
3573
+ return target[i];
3574
+ }
3575
+ }
3576
+ } else if (_is.object(target)) {
3577
+ var keys = Object.keys(target);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3578
 
3579
+ for (i = 0, l = keys.length; i < l; i++) {
3580
+ if (callback.call(thisArg, target[keys[i]], keys[i], target)) {
3581
+ return target[keys[i]];
3582
+ }
3583
+ }
3584
+ }
3585
+ };
3586
+ /**
3587
+ * @summary Executed once for each array index or object property.
3588
+ * @callback FooGallery.utils~eachCallback
3589
+ * @param {*} value - The current value being iterated over. This could be either an element in an array or the value of an object property.
3590
+ * @param {(number|string)} [key] - The array index or property name of the `value`.
3591
+ * @param {(Object|Array)} [object] - The array or object currently being searched.
3592
+ * @returns {(boolean|void)} Return `false` to break out of the loop, all other values are ignored.
3593
+ */
3594
+
3595
+ /**
3596
+ * @summary Iterate over all indexes or properties of the provided target executing the provided callback once per value.
3597
+ * @memberof FooGallery.utils.
3598
+ * @function each
3599
+ * @param {(Object|Array)} object - The object or array to search.
3600
+ * @param {FooGallery.utils~eachCallback} callback - A function to execute for each value in the target.
3601
+ * @param {*} [thisArg] - The `this` value within the `callback`.
3602
+ */
3603
+
3604
+
3605
+ _.each = function (object, callback, thisArg) {
3606
+ if (!_is.fn(callback)) return;
3607
+ thisArg = _is.undef(thisArg) ? callback : thisArg;
3608
+ var i, l, result;
3609
+
3610
+ if (_is.array(object)) {
3611
+ for (i = 0, l = object.length; i < l; i++) {
3612
+ result = callback.call(thisArg, object[i], i, object);
3613
+ if (result === false) break;
3614
+ }
3615
+ } else if (_is.object(object)) {
3616
+ var keys = Object.keys(object);
3617
+
3618
+ for (i = 0, l = keys.length; i < l; i++) {
3619
+ result = callback.call(thisArg, object[keys[i]], keys[i], object);
3620
+ if (result === false) break;
3621
+ }
3622
+ }
3623
+ };
3624
+ /**
3625
+ * @summary Checks if a value exists within an array.
3626
+ * @memberof FooGallery.utils.
3627
+ * @function inArray
3628
+ * @param {*} needle - The value to search for.
3629
+ * @param {Array} haystack - The array to search within.
3630
+ * @returns {number} Returns the index of the value if found otherwise -1.
3631
+ */
3632
+
3633
+
3634
+ _.inArray = function (needle, haystack) {
3635
+ if (_is.array(haystack)) {
3636
+ return haystack.indexOf(needle);
3637
+ }
3638
 
3639
+ return -1;
3640
+ };
3641
+ /**
3642
+ * @summary Convert CSS class names into CSS selectors.
3643
+ * @memberof FooGallery.utils.
3644
+ * @function selectify
3645
+ * @param {(string|string[]|object)} classes - A space delimited string of CSS class names or an array of them with each item being included in the selector using the OR (`,`) syntax as a separator. If an object is supplied the result will be an object with the same property names but the values converted to selectors.
3646
+ * @returns {(object|string)}
3647
+ * @example {@caption Shows how the method can be used.}
3648
+ * // alias the FooGallery.utils namespace
3649
+ * var _ = FooGallery.utils;
3650
+ *
3651
+ * console.log( _.selectify("my-class") ); // => ".my-class"
3652
+ * console.log( _.selectify("my-class my-other-class") ); // => ".my-class.my-other-class"
3653
+ * console.log( _.selectify(["my-class", "my-other-class"]) ); // => ".my-class,.my-other-class"
3654
+ * console.log( _.selectify({
3655
+ * class1: "my-class",
3656
+ * class2: "my-class my-other-class",
3657
+ * class3: ["my-class", "my-other-class"]
3658
+ * }) ); // => { class1: ".my-class", class2: ".my-class.my-other-class", class3: ".my-class,.my-other-class" }
3659
+ */
3660
+
3661
+
3662
+ _.selectify = function (classes) {
3663
+ if (_is.empty(classes)) return null;
3664
+
3665
+ if (_is.hash(classes)) {
3666
+ var result = {},
3667
+ selector;
3668
+
3669
+ for (var name in classes) {
3670
+ if (!classes.hasOwnProperty(name)) continue;
3671
+ selector = _.selectify(classes[name]);
3672
+
3673
+ if (selector) {
3674
+ result[name] = selector;
3675
+ }
3676
+ }
3677
 
3678
+ return result;
3679
+ }
 
 
 
 
3680
 
3681
+ if (_is.string(classes) || _is.array(classes)) {
3682
+ if (_is.string(classes)) classes = [classes];
3683
+ return classes.map(function (str) {
3684
+ return _is.string(str) ? "." + str.split(/\s/g).join(".") : null;
3685
+ }).join(",");
3686
+ }
3687
 
3688
+ return null;
3689
+ };
3690
+ /**
3691
+ * @ignore
3692
+ * @summary Internal replacement for the `requestAnimationFrame` method if the browser doesn't support any form of the method.
3693
+ * @param {function} callback - The function to call when it's time to update your animation for the next repaint.
3694
+ * @return {number} - The request id that uniquely identifies the entry in the callback list.
3695
+ */
3696
+
3697
+
3698
+ function raf(callback) {
3699
+ return setTimeout(callback, 1000 / 60);
3700
+ }
3701
+ /**
3702
+ * @ignore
3703
+ * @summary Internal replacement for the `cancelAnimationFrame` method if the browser doesn't support any form of the method.
3704
+ * @param {number} requestID - The ID value returned by the call to {@link FooGallery.utils.requestFrame|requestFrame} that requested the callback.
3705
+ */
3706
+
3707
+
3708
+ function caf(requestID) {
3709
+ clearTimeout(requestID);
3710
+ }
3711
+ /**
3712
+ * @summary A cross browser wrapper for the `requestAnimationFrame` method.
3713
+ * @memberof FooGallery.utils.
3714
+ * @function requestFrame
3715
+ * @param {function} callback - The function to call when it's time to update your animation for the next repaint.
3716
+ * @return {number} - The request id that uniquely identifies the entry in the callback list.
3717
+ */
3718
+
3719
+
3720
+ _.requestFrame = (window.requestAnimationFrame || window.webkitRequestAnimationFrame || raf).bind(window);
3721
+ /**
3722
+ * @summary A cross browser wrapper for the `cancelAnimationFrame` method.
3723
+ * @memberof FooGallery.utils.
3724
+ * @function cancelFrame
3725
+ * @param {number} requestID - The ID value returned by the call to {@link FooGallery.utils.requestFrame|requestFrame} that requested the callback.
3726
+ */
3727
+
3728
+ _.cancelFrame = (window.cancelAnimationFrame || window.webkitCancelAnimationFrame || caf).bind(window);
3729
+ /**
3730
+ * @summary Registers a callback with the next available animation frame.
3731
+ * @memberof FooGallery.utils.
3732
+ * @function nextFrame
3733
+ * @param {function} callback - The callback to execute for the next frame.
3734
+ * @param {*} [thisArg] - The value of `this` within the callback. Defaults to the callback itself.
3735
+ * @returns {Promise} Returns a promise object that is resolved using the return value of the callback.
3736
+ */
3737
+
3738
+ _.nextFrame = function (callback, thisArg) {
3739
+ return $.Deferred(function (def) {
3740
+ if (!_is.fn(callback)) {
3741
+ def.reject(new Error('Provided callback is not a function.'));
3742
+ } else {
3743
+ thisArg = _is.undef(thisArg) ? callback : thisArg;
3744
+
3745
+ _.requestFrame(function () {
3746
+ try {
3747
+ def.resolve(callback.call(thisArg));
3748
+ } catch (err) {
3749
+ def.reject(err);
3750
+ }
3751
+ });
3752
+ }
3753
+ }).promise();
3754
+ };
3755
+ })( // dependencies
3756
+ FooGallery.utils.$, FooGallery.utils, FooGallery.utils.is);
3757
 
3758
+ (function ($, _, _is, _obj, _fn) {
3759
+ // only register methods if this version is the current version
3760
+ if (_.version !== '1.0.0') return;
3761
+ /**
3762
+ * @summary A base class providing some helper methods for prototypal inheritance.
3763
+ * @memberof FooGallery.utils.
3764
+ * @constructs Class
3765
+ * @description This is a base class for making prototypal inheritance simpler to work with. It provides an easy way to inherit from another class and exposes a `_super` method within the scope of any overriding methods that allows a simple way to execute the overridden function.
3766
+ *
3767
+ * Have a look at the {@link FooGallery.utils.Class.extend|extend} and {@link FooGallery.utils.Class.override|override} method examples to see some basic usage.
3768
+ * @example {@caption When using this base class the actual construction of a class is performed by the `construct` method.}
3769
+ * var MyClass = FooGallery.utils.Class.extend({
3770
+ * construct: function(arg1, arg2){
3771
+ * // handle the construction logic here
3772
+ * }
3773
+ * });
3774
+ *
3775
+ * // use the class
3776
+ * var myClass = new MyClass( "arg1:value", "arg2:value" );
3777
+ */
3778
+
3779
+ _.Class = function () {};
3780
+ /**
3781
+ * @ignore
3782
+ * @summary The original function when within the scope of an overriding method.
3783
+ * @memberof FooGallery.utils.Class#
3784
+ * @function _super
3785
+ * @param {...*} [argN] - The same arguments as the base method.
3786
+ * @returns {*} The result of the base method.
3787
+ * @description This is only available within the scope of an overriding method if it was created using the {@link FooGallery.utils.Class.extend|extend}, {@link FooGallery.utils.Class.override|override} or {@link FooGallery.utils.fn.addOrOverride} methods.
3788
+ * @see {@link FooGallery.utils.fn.addOrOverride} to see an example of how this property is used.
3789
+ */
3790
+
3791
+ /**
3792
+ * @summary Creates a new class that inherits from this one which in turn allows itself to be extended.
3793
+ * @memberof FooGallery.utils.Class.
3794
+ * @function extend
3795
+ * @param {Object} [definition] - An object containing any methods to implement/override.
3796
+ * @returns {function} A new class that inherits from the base class.
3797
+ * @description Every class created using this method has both the {@link FooGallery.utils.Class.extend|extend} and {@link FooGallery.utils.Class.override|override} static methods added to it to allow it to be extended.
3798
+ * @example {@caption The below shows an example of how to implement inheritance using this method.}{@run true}
3799
+ * // create a base Person class
3800
+ * var Person = FooGallery.utils.Class.extend({
3801
+ * construct: function(isDancing){
3802
+ * this.dancing = isDancing;
3803
+ * },
3804
+ * dance: function(){
3805
+ * return this.dancing;
3806
+ * }
3807
+ * });
3808
+ *
3809
+ * var Ninja = Person.extend({
3810
+ * construct: function(){
3811
+ * // Call the inherited version of construct()
3812
+ * this._super( false );
3813
+ * },
3814
+ * dance: function(){
3815
+ * // Call the inherited version of dance()
3816
+ * return this._super();
3817
+ * },
3818
+ * swingSword: function(){
3819
+ * return true;
3820
+ * }
3821
+ * });
3822
+ *
3823
+ * var p = new Person(true);
3824
+ * console.log( p.dance() ); // => true
3825
+ *
3826
+ * var n = new Ninja();
3827
+ * console.log( n.dance() ); // => false
3828
+ * console.log( n.swingSword() ); // => true
3829
+ * console.log(
3830
+ * p instanceof Person && p.constructor === Person && p instanceof FooGallery.utils.Class
3831
+ * && n instanceof Ninja && n.constructor === Ninja && n instanceof Person && n instanceof FooGallery.utils.Class
3832
+ * ); // => true
3833
+ */
3834
+
3835
+
3836
+ _.Class.extend = function (definition) {
3837
+ definition = _is.hash(definition) ? definition : {};
3838
+
3839
+ var proto = _obj.create(this.prototype); // create a new prototype to work with so we don't modify the original
3840
+ // iterate over all properties in the supplied definition and update the prototype
3841
+
3842
+
3843
+ for (var name in definition) {
3844
+ if (!definition.hasOwnProperty(name)) continue;
3845
+
3846
+ _fn.addOrOverride(proto, name, definition[name]);
3847
+ } // if no construct method is defined add a default one that does nothing
3848
+
3849
+
3850
+ proto.construct = _is.fn(proto.construct) ? proto.construct : function () {}; // create the new class using the prototype made above
3851
+
3852
+ function Class() {
3853
+ if (!_is.fn(this.construct)) throw new SyntaxError('FooGallery.utils.Class objects must be constructed with the "new" keyword.');
3854
+ this.construct.apply(this, arguments);
3855
+ }
3856
 
3857
+ Class.prototype = proto; //noinspection JSUnresolvedVariable
3858
+
3859
+ Class.prototype.constructor = _is.fn(proto.__ctor__) ? proto.__ctor__ : Class;
3860
+ Class.extend = _.Class.extend;
3861
+ Class.override = _.Class.override;
3862
+ Class.getBaseClasses = _.Class.getBaseClasses;
3863
+ Class.__baseClass__ = this;
3864
+ return Class;
3865
+ };
3866
+ /**
3867
+ * @summary Overrides a single method on this class.
3868
+ * @memberof FooGallery.utils.Class.
3869
+ * @function override
3870
+ * @param {string} name - The name of the function to override.
3871
+ * @param {function} fn - The new function to override with, the `_super` method will be made available within this function.
3872
+ * @description This is a helper method for overriding a single function of a {@link FooGallery.utils.Class} or one of its child classes. This uses the {@link FooGallery.utils.fn.addOrOverride} method internally and simply provides the correct prototype.
3873
+ * @example {@caption The below example wraps the `Person.prototype.dance` method with a new one that inverts the result. Note the override applies even to instances of the class that are already created.}{@run true}
3874
+ * var Person = FooGallery.utils.Class.extend({
3875
+ * construct: function(isDancing){
3876
+ * this.dancing = isDancing;
3877
+ * },
3878
+ * dance: function(){
3879
+ * return this.dancing;
3880
+ * }
3881
+ * });
3882
+ *
3883
+ * var p = new Person(true);
3884
+ * console.log( p.dance() ); // => true
3885
+ *
3886
+ * Person.override("dance", function(){
3887
+ * // Call the original version of dance()
3888
+ * return !this._super();
3889
+ * });
3890
+ *
3891
+ * console.log( p.dance() ); // => false
3892
+ */
3893
+
3894
+
3895
+ _.Class.override = function (name, fn) {
3896
+ _fn.addOrOverride(this.prototype, name, fn);
3897
+ };
3898
+ /**
3899
+ * @summary The base class for this class.
3900
+ * @memberof FooGallery.utils.Class.
3901
+ * @name __baseClass__
3902
+ * @type {?FooGallery.utils.Class}
3903
+ * @private
3904
+ */
3905
+
3906
+
3907
+ _.Class.__baseClass__ = null;
3908
+
3909
+ function getBaseClasses(klass, result) {
3910
+ if (!_is.array(result)) result = [];
3911
+
3912
+ if (_is.fn(klass) && klass.__baseClass__ !== null) {
3913
+ result.unshift(klass.__baseClass__);
3914
+ return getBaseClasses(klass.__baseClass__, result);
3915
+ }
3916
 
3917
+ return result;
3918
+ }
3919
+ /**
3920
+ * @summary Get an array of all base classes for this class.
3921
+ * @memberof FooGallery.utils.Class.
3922
+ * @function getBaseClasses
3923
+ * @returns {FooGallery.utils.Class[]}
3924
+ */
3925
+
3926
+
3927
+ _.Class.getBaseClasses = function () {
3928
+ return getBaseClasses(this, []);
3929
+ };
3930
+ })( // dependencies
3931
+ FooGallery.utils.$, FooGallery.utils, FooGallery.utils.is, FooGallery.utils.obj, FooGallery.utils.fn);
3932
+
3933
+ (function ($, _, _is, _fn, _obj) {
3934
+ /**
3935
+ * @summary A registry class allowing classes to be easily registered and created.
3936
+ * @memberof FooGallery.utils.
3937
+ * @class ClassRegistry
3938
+ * @param {FooGallery.utils.ClassRegistry~Options} [options] - The options for the registry.
3939
+ * @augments FooGallery.utils.Class
3940
+ * @borrows FooGallery.utils.Class.extend as extend
3941
+ * @borrows FooGallery.utils.Class.override as override
3942
+ * @borrows FooGallery.utils.Class.getBaseClasses as getBaseClasses
3943
+ */
3944
+ _.ClassRegistry = _.Class.extend(
3945
+ /** @lends FooGallery.utils.ClassRegistry.prototype */
3946
+ {
3947
+ /**
3948
+ * @ignore
3949
+ * @constructs
3950
+ * @param {FooGallery.utils.ClassRegistry~Options} [options] - The options for the registry.
3951
+ */
3952
+ construct: function construct(options) {
3953
+ var self = this;
3954
+ /**
3955
+ * @summary A callback allowing the arguments supplied to the constructor of a new class to be modified.
3956
+ * @callback FooGallery.utils.ClassRegistry~beforeCreate
3957
+ * @param {FooGallery.utils.ClassRegistry~RegisteredClass} registered - The registered object containing all the information for the class being created.
3958
+ * @param {Array} args - An array of all arguments to be supplied to the constructor of the new class.
3959
+ * @returns {Array} Returns an array of all arguments to be supplied to the constructor of the new class.
3960
+ * @this FooGallery.utils.ClassRegistry
3961
+ */
3962
+
3963
+ /**
3964
+ * @summary The options for the registry.
3965
+ * @typedef {?Object} FooGallery.utils.ClassRegistry~Options
3966
+ * @property {boolean} [allowBase] - Whether or not to allow base classes to be created. Base classes are registered with a priority below 0.
3967
+ * @property {?FooGallery.utils.ClassRegistry~beforeCreate} [beforeCreate] - A callback executed just prior to creating an instance of a registered class. This must return an array of arguments to supply to the constructor of the new class.
3968
+ */
3969
+
3970
+ /**
3971
+ * @summary The options for this instance.
3972
+ * @memberof FooGallery.utils.ClassRegistry#
3973
+ * @name opt
3974
+ * @type {FooGallery.utils.ClassRegistry~Options}
3975
+ */
3976
+
3977
+ self.opt = _obj.extend({
3978
+ allowBase: true,
3979
+ beforeCreate: null
3980
+ }, options);
3981
+ /**
3982
+ * @summary An object detailing a registered class.
3983
+ * @typedef {?Object} FooGallery.utils.ClassRegistry~RegisteredClass
3984
+ * @property {string} name - The name of the class.
3985
+ * @property {FooGallery.utils.Class} ctor - The class constructor.
3986
+ * @property {string} selector - The CSS selector for the class.
3987
+ * @property {Object} config - The configuration object for the class providing default values that can be overridden at runtime.
3988
+ * @property {number} priority - This determines the index for the class when using the {@link FooGallery.utils.ClassRegistry#find|find} method, a higher value equals a lower index.
3989
+ */
3990
+
3991
+ /**
3992
+ * @summary An object containing all registered classes.
3993
+ * @memberof FooGallery.utils.ClassRegistry#
3994
+ * @name registered
3995
+ * @type {Object.<string, FooGallery.utils.ClassRegistry~RegisteredClass>}
3996
+ * @readonly
3997
+ * @example {@caption The following shows the structure of this object. The `<name>` placeholders would be the name the class was registered with.}
3998
+ * {
3999
+ * "<name>": {
4000
+ * "name": <string>,
4001
+ * "ctor": <function>,
4002
+ * "selector": <string>,
4003
+ * "config": <object>,
4004
+ * "priority": <number>
4005
+ * },
4006
+ * "<name>": {
4007
+ * "name": <string>,
4008
+ * "ctor": <function>,
4009
+ * "selector": <string>,
4010
+ * "config": <object>,
4011
+ * "priority": <number>
4012
+ * },
4013
+ * ...
4014
+ * }
4015
+ */
4016
+
4017
+ self.registered = {};
4018
+ },
4019
 
4020
+ /**
4021
+ * @summary Register a class constructor with the provided `name`.
4022
+ * @memberof FooGallery.utils.ClassRegistry#
4023
+ * @function register
4024
+ * @param {string} name - The name of the class.
4025
+ * @param {FooGallery.utils.Class} klass - The class constructor to register.
4026
+ * @param {Object} [config] - The configuration object for the class providing default values that can be overridden at runtime.
4027
+ * @param {number} [priority=0] - This determines the index for the class when using the {@link FooGallery.utils.ClassRegistry#find|find} method, a higher value equals a lower index.
4028
+ * @returns {boolean} Returns `true` if the class was successfully registered.
4029
+ */
4030
+ register: function register(name, klass, config, priority) {
4031
+ var self = this;
4032
+
4033
+ if (_is.string(name) && !_is.empty(name) && _is.fn(klass)) {
4034
+ priority = _is.number(priority) ? priority : 0;
4035
+ var current = self.registered[name];
4036
+ self.registered[name] = {
4037
+ name: name,
4038
+ ctor: klass,
4039
+ config: _is.hash(config) ? config : {},
4040
+ priority: !_is.undef(current) ? current.priority : priority
4041
+ };
4042
+ return true;
4043
+ }
4044
 
4045
+ return false;
4046
+ },
 
 
 
 
 
4047
 
4048
+ /**
4049
+ * @summary The callback function for the {@link FooGallery.utils.ClassRegistry#each|each} method.
4050
+ * @callback FooGallery.utils.ClassRegistry~eachCallback
4051
+ * @param {FooGallery.utils.ClassRegistry~RegisteredClass} registered - The current registered class being iterated over.
4052
+ * @param {number} index - The array index of the `registered` object.
4053
+ * @returns {(boolean|undefined)} Return `false` to break out of the loop, all other values are ignored.
4054
+ */
 
 
4055
 
4056
+ /**
4057
+ * @summary Iterates over all registered classes executing the provided callback once per class.
4058
+ * @param {FooGallery.utils.ClassRegistry~eachCallback} callback - The callback to execute for each registered class.
4059
+ * @param {boolean} [prioritize=false] - Whether or not the registered classes should be prioritized before iteration.
4060
+ * @param {*} [thisArg] - The value of `this` within the callback.
4061
+ */
4062
+ each: function each(callback, prioritize, thisArg) {
4063
+ prioritize = _is.boolean(prioritize) ? prioritize : false;
4064
+ thisArg = _is.undef(thisArg) ? callback : thisArg;
4065
+ var self = this,
4066
+ names = Object.keys(self.registered),
4067
+ registered = names.map(function (name) {
4068
+ return self.registered[name];
4069
+ });
4070
+
4071
+ if (prioritize) {
4072
+ registered.sort(function (a, b) {
4073
+ return b.priority - a.priority;
4074
+ });
4075
+ }
4076
 
4077
+ var i = 0,
4078
+ l = registered.length;
4079
 
4080
+ for (; i < l; i++) {
4081
+ var result = callback.call(thisArg, registered[i], i);
4082
+ if (result === false) break;
4083
+ }
4084
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4085
 
4086
+ /**
4087
+ * @summary The callback function for the {@link FooGallery.utils.ClassRegistry#find|find} method.
4088
+ * @callback FooGallery.utils.ClassRegistry~findCallback
4089
+ * @param {FooGallery.utils.ClassRegistry~RegisteredClass} registered - The current registered class being iterated over.
4090
+ * @param {number} index - The array index of the `registered` object.
4091
+ * @returns {boolean} `true` to return the current registered class.
4092
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4093
 
4094
+ /**
4095
+ * @summary Iterates through all registered classes until the supplied `callback` returns a truthy value.
4096
+ * @param {FooGallery.utils.ClassRegistry~findCallback} callback - The callback to execute for each registered class.
4097
+ * @param {boolean} [prioritize=false] - Whether or not the registered classes should be prioritized before iteration.
4098
+ * @param {*} [thisArg] - The value of `this` within the callback.
4099
+ * @returns {?FooGallery.utils.ClassRegistry~RegisteredClass} `null` if no registered class satisfied the `callback`.
4100
+ */
4101
+ find: function find(callback, prioritize, thisArg) {
4102
+ prioritize = _is.boolean(prioritize) ? prioritize : false;
4103
+ thisArg = _is.undef(thisArg) ? callback : thisArg;
4104
+ var self = this,
4105
+ names = Object.keys(self.registered),
4106
+ registered = names.map(function (name) {
4107
+ return self.registered[name];
4108
+ });
4109
+
4110
+ if (prioritize) {
4111
+ registered.sort(function (a, b) {
4112
+ return b.priority - a.priority;
4113
+ });
4114
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4115
 
4116
+ var i = 0,
4117
+ l = registered.length;
 
4118
 
4119
+ for (; i < l; i++) {
4120
+ if (callback.call(thisArg, registered[i], i)) {
4121
+ return registered[i];
4122
+ }
4123
+ }
 
 
 
 
 
 
 
 
 
4124
 
4125
+ return null;
4126
+ },
 
 
 
 
 
 
4127
 
4128
+ /**
4129
+ * @summary Create a new instance of a registered class by `name`.
4130
+ * @memberof FooGallery.utils.ClassRegistry#
4131
+ * @function create
4132
+ * @param {string} name - The name of the class to create.
4133
+ * @param {Object} [config] - Any custom configuration to supply to the class.
4134
+ * @param {...*} [argN] - Any number of additional arguments to pass to the class constructor.
4135
+ * @returns {?FooGallery.utils.Class} Returns `null` if no registered class can handle the supplied `element`.
4136
+ */
4137
+ create: function create(name, config, argN) {
4138
+ var self = this,
4139
+ args = _fn.arg2arr(arguments);
4140
+
4141
+ name = args.shift();
4142
+
4143
+ if (_is.string(name) && self.registered.hasOwnProperty(name)) {
4144
+ var registered = self.registered[name];
4145
+ var allowed = true;
4146
+ if (registered.priority < 0 && !self.opt.allowBase) allowed = false;
4147
+
4148
+ if (allowed && _is.fn(registered.ctor)) {
4149
+ config = args.shift();
4150
+ config = self.mergeConfigurations(registered.name, config);
4151
+ args.unshift.apply(args, [registered.name, config]);
4152
+ return _fn.apply(registered.ctor, self.onBeforeCreate(registered, args));
4153
+ }
4154
+ }
4155
 
4156
+ return null;
4157
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4158
 
4159
+ /**
4160
+ * @summary Executes the beforeCreate callback if supplied and gives sub-classes an easy way to modify the arguments supplied to newly created classes.
4161
+ * @memberof FooGallery.utils.ClassRegistry#
4162
+ * @function onBeforeCreate
4163
+ * @param {FooGallery.utils.ClassRegistry~RegisteredClass} registered - The registered class about to be created.
4164
+ * @param {Array} args - The array of arguments to be supplied to the registered class constructor.
4165
+ * @returns {Array}
4166
+ */
4167
+ onBeforeCreate: function onBeforeCreate(registered, args) {
4168
+ var self = this;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4169
 
4170
+ if (self.opt.beforeCreate !== null && _is.fn(self.opt.beforeCreate)) {
4171
+ return self.opt.beforeCreate.call(self, registered, args);
4172
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4173
 
4174
+ return args;
4175
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4176
 
4177
+ /**
4178
+ * @summary Get the merged configuration for a class.
4179
+ * @memberof FooGallery.utils.ClassRegistry#
4180
+ * @function mergeConfigurations
4181
+ * @param {string} name - The name of the class to get the config for.
4182
+ * @param {Object} [config] - The user supplied defaults to override.
4183
+ * @returns {Object}
4184
+ */
4185
+ mergeConfigurations: function mergeConfigurations(name, config) {
4186
+ var self = this;
4187
+
4188
+ if (_is.string(name) && self.registered.hasOwnProperty(name)) {
4189
+ // check params
4190
+ config = _is.hash(config) ? config : {};
4191
+ var baseClasses = self.getBaseClasses(name),
4192
+ eArgs = [{}];
4193
+ baseClasses.push(self.registered[name]);
4194
+ baseClasses.forEach(function (reg) {
4195
+ eArgs.push(reg.config);
4196
+ });
4197
+ eArgs.push(config);
4198
+ return _obj.extend.apply(_obj, eArgs);
4199
+ }
4200
 
4201
+ return {};
4202
+ },
 
 
 
 
 
 
 
 
 
 
4203
 
4204
+ /**
4205
+ * @summary Gets the registered base class for this instance.
4206
+ * @memberof FooGallery.utils.ClassRegistry#
4207
+ * @function getBaseClass
4208
+ * @returns {?FooGallery.utils.ClassRegistry~RegisteredClass}
4209
+ */
4210
+ getBaseClass: function getBaseClass() {
4211
+ return this.find(function (registered) {
4212
+ return registered.priority < 0;
4213
+ }, true);
4214
+ },
 
 
 
 
 
 
 
 
 
 
 
 
4215
 
4216
+ /**
4217
+ * @summary Get all registered base classes for the supplied `name`.
4218
+ * @memberof FooGallery.utils.ClassRegistry#
4219
+ * @function getBaseClasses
4220
+ * @param {string} name - The name of the class to get the base classes for.
4221
+ * @returns {FooGallery.utils.ClassRegistry~RegisteredClass[]}
4222
+ */
4223
+ getBaseClasses: function getBaseClasses(name) {
4224
+ var self = this,
4225
+ reg = self.registered[name],
4226
+ result = [];
4227
+
4228
+ if (!_is.undef(reg)) {
4229
+ reg.ctor.getBaseClasses().forEach(function (base) {
4230
+ var found = self.fromType(base);
4231
+
4232
+ if (_is.hash(found)) {
4233
+ result.push(found);
4234
+ }
4235
+ });
4236
+ }
4237
 
4238
+ return result;
4239
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4240
 
4241
+ /**
4242
+ * @summary Attempts to find a registered class given the type/constructor.
4243
+ * @memberof FooGallery.utils.ClassRegistry#
4244
+ * @function fromType
4245
+ * @param {FooGallery.utils.Class} type - The type/constructor of the registered class to find.
4246
+ * @returns {(FooGallery.utils.ClassRegistry~RegisteredClass|undefined)} Returns the registered class if found. Otherwise, `undefined` is returned.
4247
+ */
4248
+ fromType: function fromType(type) {
4249
+ if (!_is.fn(type)) return;
4250
+ return this.find(function (registered) {
4251
+ return registered.ctor === type;
4252
+ });
4253
+ }
4254
+ });
4255
+ })(FooGallery.utils.$, FooGallery.utils, FooGallery.utils.is, FooGallery.utils.fn, FooGallery.utils.obj);
 
 
 
 
4256
 
4257
+ (function (_, _is, _str) {
4258
+ // only register methods if this version is the current version
4259
+ if (_.version !== '1.0.0') return; // noinspection JSUnusedGlobalSymbols
4260
+
4261
+ /**
4262
+ * @summary A base event class providing just a type and defaultPrevented properties.
4263
+ * @memberof FooGallery.utils.
4264
+ * @class Event
4265
+ * @param {string} type - The type for this event.
4266
+ * @augments FooGallery.utils.Class
4267
+ * @borrows FooGallery.utils.Class.extend as extend
4268
+ * @borrows FooGallery.utils.Class.override as override
4269
+ * @description This is a very basic event class that is used internally by the {@link FooGallery.utils.EventClass#trigger} method when the first parameter supplied is simply the event name.
4270
+ *
4271
+ * To trigger your own custom event you will need to inherit from this class and then supply the instantiated event object as the first parameter to the {@link FooGallery.utils.EventClass#trigger} method.
4272
+ * @example {@caption The following shows how to use this class to create a custom event.}
4273
+ * var MyEvent = FooGallery.utils.Event.extend({
4274
+ * construct: function(type, customProp){
4275
+ * this._super(type);
4276
+ * this.myCustomProp = customProp;
4277
+ * }
4278
+ * });
4279
+ *
4280
+ * // to use the class you would then instantiate it and pass it as the first argument to a FooGallery.utils.EventClass's trigger method
4281
+ * var eventClass = ...; // any class inheriting from FooGallery.utils.EventClass
4282
+ * var event = new MyEvent( "my-event-type", true );
4283
+ * eventClass.trigger(event);
4284
+ */
4285
+
4286
+ _.Event = _.Class.extend(
4287
+ /** @lends FooGallery.utils.Event.prototype */
4288
+ {
4289
+ /**
4290
+ * @ignore
4291
+ * @constructs
4292
+ * @param {string} type
4293
+ **/
4294
+ construct: function construct(type) {
4295
+ if (_is.empty(type)) throw new SyntaxError('FooGallery.utils.Event objects must be supplied a `type`.');
4296
+
4297
+ var self = this,
4298
+ parsed = _.Event.parse(type);
4299
+ /**
4300
+ * @summary The type of event.
4301
+ * @memberof FooGallery.utils.Event#
4302
+ * @name type
4303
+ * @type {string}
4304
+ * @readonly
4305
+ */
4306
+
4307
+
4308
+ self.type = parsed.type;
4309
+ /**
4310
+ * @summary The namespace of the event.
4311
+ * @memberof FooGallery.utils.Event#
4312
+ * @name namespace
4313
+ * @type {string}
4314
+ * @readonly
4315
+ */
4316
+
4317
+ self.namespace = parsed.namespace;
4318
+ /**
4319
+ * @summary Whether the default action should be taken or not.
4320
+ * @memberof FooGallery.utils.Event#
4321
+ * @name defaultPrevented
4322
+ * @type {boolean}
4323
+ * @readonly
4324
+ */
4325
+
4326
+ self.defaultPrevented = false;
4327
+ /**
4328
+ * @summary The original {@link FooGallery.utils.EventClass} that triggered this event.
4329
+ * @memberof FooGallery.utils.Event#
4330
+ * @name target
4331
+ * @type {FooGallery.utils.EventClass}
4332
+ */
4333
+
4334
+ self.target = null;
4335
+ },
4336
 
4337
+ /**
4338
+ * @summary Informs the class that raised this event that its default action should not be taken.
4339
+ * @memberof FooGallery.utils.Event#
4340
+ * @function preventDefault
4341
+ */
4342
+ preventDefault: function preventDefault() {
4343
+ this.defaultPrevented = true;
4344
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4345
 
4346
+ /**
4347
+ * @summary Gets whether the default action should be taken or not.
4348
+ * @memberof FooGallery.utils.Event#
4349
+ * @function isDefaultPrevented
4350
+ * @returns {boolean}
4351
+ */
4352
+ isDefaultPrevented: function isDefaultPrevented() {
4353
+ return this.defaultPrevented;
4354
+ }
4355
+ });
4356
+ /**
4357
+ * @summary Parse the provided event string into a type and namespace.
4358
+ * @memberof FooGallery.utils.Event.
4359
+ * @function parse
4360
+ * @param {string} event - The event to parse.
4361
+ * @returns {{namespaced: boolean, type: string, namespace: string}} Returns an object containing the type and namespace for the event.
4362
+ */
4363
+
4364
+ _.Event.parse = function (event) {
4365
+ event = _is.string(event) && !_is.empty(event) ? event : null;
4366
+
4367
+ var namespaced = _str.contains(event, ".");
4368
+
4369
+ return {
4370
+ namespaced: namespaced,
4371
+ type: namespaced ? _str.startsWith(event, ".") ? null : _str.until(event, ".") : event,
4372
+ namespace: namespaced ? _str.from(event, ".") : null
4373
+ };
4374
+ }; // noinspection JSUnusedGlobalSymbols
4375
+
4376
+ /**
4377
+ * @summary A base class that implements a basic events interface.
4378
+ * @memberof FooGallery.utils.
4379
+ * @class EventClass
4380
+ * @augments FooGallery.utils.Class
4381
+ * @borrows FooGallery.utils.Class.extend as extend
4382
+ * @borrows FooGallery.utils.Class.override as override
4383
+ * @description This is a very basic events implementation that provides just enough to cover most needs.
4384
+ */
4385
+
4386
+
4387
+ _.EventClass = _.Class.extend(
4388
+ /** @lends FooGallery.utils.EventClass.prototype */
4389
+ {
4390
+ /**
4391
+ * @ignore
4392
+ * @constructs
4393
+ **/
4394
+ construct: function construct() {
4395
+ /**
4396
+ * @summary An object containing all the required info to execute a listener.
4397
+ * @typedef {Object} FooGallery.utils.EventClass~RegisteredListener
4398
+ * @property {string} namespace - The namespace for the listener.
4399
+ * @property {function} fn - The callback function for the listener.
4400
+ * @property {*} thisArg - The `this` value to execute the callback with.
4401
+ */
4402
+
4403
+ /**
4404
+ * @summary An object containing a mapping of events to listeners.
4405
+ * @typedef {Object.<string, Array<FooGallery.utils.EventClass~RegisteredListener>>} FooGallery.utils.EventClass~RegisteredEvents
4406
+ */
4407
+
4408
+ /**
4409
+ * @summary The object used to register event handlers.
4410
+ * @memberof FooGallery.utils.EventClass#
4411
+ * @name events
4412
+ * @type {FooGallery.utils.EventClass~RegisteredEvents}
4413
+ */
4414
+ this.events = {};
4415
+ },
4416
 
4417
+ /**
4418
+ * @summary Destroy the current instance releasing used resources.
4419
+ * @memberof FooGallery.utils.EventClass#
4420
+ * @function destroy
4421
+ */
4422
+ destroy: function destroy() {
4423
+ this.events = {};
4424
+ },
4425
 
4426
+ /**
4427
+ * @summary Attach multiple event listeners to the class.
4428
+ * @memberof FooGallery.utils.EventClass#
4429
+ * @function on
4430
+ * @param {Object.<string, function>} events - An object containing event types to listener mappings.
4431
+ * @param {*} [thisArg] - The value of `this` within the listeners. Defaults to the class raising the event.
4432
+ * @returns {this}
4433
+ */
 
 
 
 
 
 
 
 
 
 
4434
 
4435
+ /**
4436
+ * @summary Attach an event listener for one or more events to the class.
4437
+ * @memberof FooGallery.utils.EventClass#
4438
+ * @function on
4439
+ * @param {string} events - One or more space-separated event types.
4440
+ * @param {function} listener - A function to execute when the event is triggered.
4441
+ * @param {*} [thisArg] - The value of `this` within the `listener`. Defaults to the class raising the event.
4442
+ * @returns {this}
4443
+ */
4444
+ on: function on(events, listener, thisArg) {
4445
+ var self = this;
4446
+
4447
+ if (_is.object(events)) {
4448
+ thisArg = listener;
4449
+ Object.keys(events).forEach(function (key) {
4450
+ if (_is.fn(events[key])) {
4451
+ key.split(" ").forEach(function (type) {
4452
+ self.addListener(type, events[key], thisArg);
4453
+ });
4454
+ }
4455
+ });
4456
+ } else if (_is.string(events) && _is.fn(listener)) {
4457
+ events.split(" ").forEach(function (type) {
4458
+ self.addListener(type, listener, thisArg);
4459
+ });
4460
+ }
 
 
 
 
 
 
 
 
4461
 
4462
+ return self;
4463
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4464
 
4465
+ /**
4466
+ * @summary Adds a single event listener to the current class.
4467
+ * @memberof FooGallery.utils.EventClass#
4468
+ * @function addListener
4469
+ * @param {string} event - The event type, this can not contain any whitespace.
4470
+ * @param {function} listener - A function to execute when the event is triggered.
4471
+ * @param {*} [thisArg] - The value of `this` within the `listener`. Defaults to the class raising the event.
4472
+ * @returns {boolean} Returns `true` if added.
4473
+ */
4474
+ addListener: function addListener(event, listener, thisArg) {
4475
+ if (!_is.string(event) || /\s/.test(event) || !_is.fn(listener)) return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4476
 
4477
+ var self = this,
4478
+ parsed = _.Event.parse(event);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4479
 
4480
+ thisArg = _is.undef(thisArg) ? self : thisArg;
 
 
4481
 
4482
+ if (!_is.array(self.events[parsed.type])) {
4483
+ self.events[parsed.type] = [];
4484
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4485
 
4486
+ var exists = self.events[parsed.type].some(function (h) {
4487
+ return h.namespace === parsed.namespace && h.fn === listener && h.thisArg === thisArg;
4488
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4489
 
4490
+ if (!exists) {
4491
+ self.events[parsed.type].push({
4492
+ namespace: parsed.namespace,
4493
+ fn: listener,
4494
+ thisArg: thisArg
4495
+ });
4496
+ return true;
4497
+ }
 
 
 
4498
 
4499
+ return false;
4500
+ },
4501
 
4502
+ /**
4503
+ * @summary Remove multiple event listeners from the class.
4504
+ * @memberof FooGallery.utils.EventClass#
4505
+ * @function off
4506
+ * @param {Object.<string, function>} events - An object containing event types to listener mappings.
4507
+ * @param {*} [thisArg] - The value of `this` within the `listener` function. Defaults to the class raising the event.
4508
+ * @returns {this}
4509
+ */
4510
 
4511
+ /**
4512
+ * @summary Remove an event listener from the class.
4513
+ * @memberof FooGallery.utils.EventClass#
4514
+ * @function off
4515
+ * @param {string} events - One or more space-separated event types.
4516
+ * @param {function} listener - A function to execute when the event is triggered.
4517
+ * @param {*} [thisArg] - The value of `this` within the `listener`. Defaults to the class raising the event.
4518
+ * @returns {this}
4519
+ */
4520
+ off: function off(events, listener, thisArg) {
4521
+ var self = this;
4522
+
4523
+ if (_is.object(events)) {
4524
+ thisArg = listener;
4525
+ Object.keys(events).forEach(function (key) {
4526
+ key.split(" ").forEach(function (type) {
4527
+ self.removeListener(type, events[key], thisArg);
4528
+ });
4529
+ });
4530
+ } else if (_is.string(events)) {
4531
+ events.split(" ").forEach(function (type) {
4532
+ self.removeListener(type, listener, thisArg);
4533
+ });
4534
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4535
 
4536
+ return self;
4537
+ },
 
 
 
 
 
4538
 
4539
+ /**
4540
+ * @summary Removes a single event listener from the current class.
4541
+ * @memberof FooGallery.utils.EventClass#
4542
+ * @function removeListener
4543
+ * @param {string} event - The event type, this can not contain any whitespace.
4544
+ * @param {function} [listener] - The listener registered to the event type.
4545
+ * @param {*} [thisArg] - The value of `this` registered for the `listener`. Defaults to the class raising the event.
4546
+ * @returns {boolean} Returns `true` if removed.
4547
+ */
4548
+ removeListener: function removeListener(event, listener, thisArg) {
4549
+ if (!_is.string(event) || /\s/.test(event)) return false;
4550
 
4551
+ var self = this,
4552
+ parsed = _.Event.parse(event),
4553
+ types = [];
 
 
 
 
 
 
 
4554
 
4555
+ thisArg = _is.undef(thisArg) ? self : thisArg;
 
 
 
 
 
 
 
 
 
4556
 
4557
+ if (!_is.empty(parsed.type)) {
4558
+ types.push(parsed.type);
4559
+ } else if (!_is.empty(parsed.namespace)) {
4560
+ types.push.apply(types, Object.keys(self.events));
4561
+ }
4562
 
4563
+ types.forEach(function (type) {
4564
+ if (!_is.array(self.events[type])) return;
4565
+ self.events[type] = self.events[type].filter(function (h) {
4566
+ if (listener != null) {
4567
+ return !(h.namespace === parsed.namespace && h.fn === listener && h.thisArg === thisArg);
4568
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4569
 
4570
+ if (parsed.namespace != null) {
4571
+ return h.namespace !== parsed.namespace;
4572
+ }
 
 
 
 
 
 
4573
 
4574
+ return false;
4575
+ });
 
 
 
 
4576
 
4577
+ if (self.events[type].length === 0) {
4578
+ delete self.events[type];
4579
+ }
4580
+ });
4581
+ return true;
4582
+ },
4583
 
4584
+ /**
4585
+ * @summary Trigger an event on the current class.
4586
+ * @memberof FooGallery.utils.EventClass#
4587
+ * @function trigger
4588
+ * @param {(string|FooGallery.utils.Event)} event - Either a space-separated string of event types or a custom event object to raise.
4589
+ * @param {Array} [args] - An array of additional arguments to supply to the listeners after the event object.
4590
+ * @returns {(FooGallery.utils.Event|FooGallery.utils.Event[]|null)} Returns the {@link FooGallery.utils.Event|event object} of the triggered event. If more than one event was triggered an array of {@link FooGallery.utils.Event|event objects} is returned. If no `event` was supplied or triggered `null` is returned.
4591
+ */
4592
+ trigger: function trigger(event, args) {
4593
+ args = _is.array(args) ? args : [];
4594
+ var self = this,
4595
+ result = [];
4596
+
4597
+ if (event instanceof _.Event) {
4598
+ result.push(event);
4599
+ self.emit(event, args);
4600
+ } else if (_is.string(event)) {
4601
+ event.split(" ").forEach(function (type) {
4602
+ var e = new _.Event(type);
4603
+ result.push(e);
4604
+ self.emit(e, args);
4605
+ });
4606
+ }
4607
 
4608
+ return _is.empty(result) ? null : result.length === 1 ? result[0] : result;
4609
+ },
 
 
 
 
 
 
4610
 
4611
+ /**
4612
+ * @summary Emits the supplied event on the current class.
4613
+ * @memberof FooGallery.utils.EventClass#
4614
+ * @function emit
4615
+ * @param {FooGallery.utils.Event} event - The event object to emit.
4616
+ * @param {Array} [args] - An array of additional arguments to supply to the listener after the event object.
4617
+ */
4618
+ emit: function emit(event, args) {
4619
+ if (!(event instanceof FooGallery.utils.Event)) return;
4620
+ var self = this;
4621
+ args = _is.array(args) ? args : [];
4622
+ if (event.target === null) event.target = self;
4623
+
4624
+ if (_is.array(self.events[event.type])) {
4625
+ self.events[event.type].forEach(function (h) {
4626
+ if (event.namespace != null && h.namespace !== event.namespace) return;
4627
+ h.fn.apply(h.thisArg, [event].concat(args));
4628
+ });
4629
+ }
4630
 
4631
+ if (_is.array(self.events["__all__"])) {
4632
+ self.events["__all__"].forEach(function (h) {
4633
+ h.fn.apply(h.thisArg, [event].concat(args));
4634
+ });
4635
+ }
4636
+ }
4637
+ });
4638
+ })( // dependencies
4639
+ FooGallery.utils, FooGallery.utils.is, FooGallery.utils.str);
4640
+
4641
+ (function ($, _, _is, _fn, _obj) {
4642
+ // only register methods if this version is the current version
4643
+ if (_.version !== '1.0.0') return;
4644
+ /**
4645
+ * @summary A simple timer that triggers events.
4646
+ * @memberof FooGallery.utils.
4647
+ * @class Timer
4648
+ * @param {number} [interval=1000] - The internal tick interval of the timer.
4649
+ */
4650
+
4651
+ _.Timer = _.EventClass.extend(
4652
+ /** @lends FooGallery.utils.Timer */
4653
+ {
4654
+ /**
4655
+ * @ignore
4656
+ * @constructs
4657
+ * @param {number} [interval=1000]
4658
+ */
4659
+ construct: function construct(interval) {
4660
+ var self = this;
4661
+
4662
+ self._super();
4663
+ /**
4664
+ * @summary The internal tick interval of the timer in milliseconds.
4665
+ * @memberof FooGallery.utils.Timer#
4666
+ * @name interval
4667
+ * @type {number}
4668
+ * @default 1000
4669
+ * @readonly
4670
+ */
4671
+
4672
+
4673
+ self.interval = _is.number(interval) ? interval : 1000;
4674
+ /**
4675
+ * @summary Whether the timer is currently running or not.
4676
+ * @memberof FooGallery.utils.Timer#
4677
+ * @name isRunning
4678
+ * @type {boolean}
4679
+ * @default false
4680
+ * @readonly
4681
+ */
4682
+
4683
+ self.isRunning = false;
4684
+ /**
4685
+ * @summary Whether the timer is currently paused or not.
4686
+ * @memberof FooGallery.utils.Timer#
4687
+ * @name isPaused
4688
+ * @type {boolean}
4689
+ * @default false
4690
+ * @readonly
4691
+ */
4692
+
4693
+ self.isPaused = false;
4694
+ /**
4695
+ * @summary Whether the timer can resume from a previous state or not.
4696
+ * @memberof FooGallery.utils.Timer#
4697
+ * @name canResume
4698
+ * @type {boolean}
4699
+ * @default false
4700
+ * @readonly
4701
+ */
4702
+
4703
+ self.canResume = false;
4704
+ /**
4705
+ * @summary Whether the timer can restart or not.
4706
+ * @memberof FooGallery.utils.Timer#
4707
+ * @name canRestart
4708
+ * @type {boolean}
4709
+ * @default false
4710
+ * @readonly
4711
+ */
4712
+
4713
+ self.canRestart = false;
4714
+ /**
4715
+ * @summary The internal tick timeout ID.
4716
+ * @memberof FooGallery.utils.Timer#
4717
+ * @name __timeout
4718
+ * @type {?number}
4719
+ * @default null
4720
+ * @private
4721
+ */
4722
+
4723
+ self.__timeout = null;
4724
+ /**
4725
+ * @summary Whether the timer is incrementing or decrementing.
4726
+ * @memberof FooGallery.utils.Timer#
4727
+ * @name __decrement
4728
+ * @type {boolean}
4729
+ * @default false
4730
+ * @private
4731
+ */
4732
+
4733
+ self.__decrement = false;
4734
+ /**
4735
+ * @summary The total time for the timer.
4736
+ * @memberof FooGallery.utils.Timer#
4737
+ * @name __time
4738
+ * @type {number}
4739
+ * @default 0
4740
+ * @private
4741
+ */
4742
+
4743
+ self.__time = 0;
4744
+ /**
4745
+ * @summary The remaining time for the timer.
4746
+ * @memberof FooGallery.utils.Timer#
4747
+ * @name __remaining
4748
+ * @type {number}
4749
+ * @default 0
4750
+ * @private
4751
+ */
4752
+
4753
+ self.__remaining = 0;
4754
+ /**
4755
+ * @summary The current time for the timer.
4756
+ * @memberof FooGallery.utils.Timer#
4757
+ * @name __current
4758
+ * @type {number}
4759
+ * @default 0
4760
+ * @private
4761
+ */
4762
+
4763
+ self.__current = 0;
4764
+ /**
4765
+ * @summary The final time for the timer.
4766
+ * @memberof FooGallery.utils.Timer#
4767
+ * @name __finish
4768
+ * @type {number}
4769
+ * @default 0
4770
+ * @private
4771
+ */
4772
+
4773
+ self.__finish = 0;
4774
+ /**
4775
+ * @summary The last arguments supplied to the {@link FooGallery.utils.Timer#start|start} method.
4776
+ * @memberof FooGallery.utils.Timer#
4777
+ * @name __restart
4778
+ * @type {Array}
4779
+ * @default []
4780
+ * @private
4781
+ */
4782
+
4783
+ self.__restart = [];
4784
+ },
4785
 
4786
+ /**
4787
+ * @summary Resets the timer back to a fresh starting state.
4788
+ * @memberof FooGallery.utils.Timer#
4789
+ * @function __reset
4790
+ * @private
4791
+ */
4792
+ __reset: function __reset() {
4793
+ var self = this;
4794
+ clearTimeout(self.__timeout);
4795
+ self.__timeout = null;
4796
+ self.__decrement = false;
4797
+ self.__time = 0;
4798
+ self.__remaining = 0;
4799
+ self.__current = 0;
4800
+ self.__finish = 0;
4801
+ self.isRunning = false;
4802
+ self.isPaused = false;
4803
+ self.canResume = false;
4804
+ },
 
 
 
4805
 
4806
+ /**
4807
+ * @summary Generates event args to be passed to listeners of the timer events.
4808
+ * @memberof FooGallery.utils.Timer#
4809
+ * @function __eventArgs
4810
+ * @param {...*} [args] - Any number of additional arguments to pass to an event listener.
4811
+ * @return {Array} - The first 3 values of the result will always be the current time, the total time and boolean indicating if the timer is decremental.
4812
+ * @private
4813
+ */
4814
+ __eventArgs: function __eventArgs(args) {
4815
+ var self = this;
4816
+ return [self.__current, self.__time, self.__decrement].concat(_fn.arg2arr(arguments));
4817
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4818
 
4819
+ /**
4820
+ * @summary Performs the tick for the timer checking and modifying the various internal states.
4821
+ * @memberof FooGallery.utils.Timer#
4822
+ * @function __tick
4823
+ * @private
4824
+ */
4825
+ __tick: function __tick() {
4826
+ var self = this;
4827
+ self.trigger("tick", self.__eventArgs());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4828
 
4829
+ if (self.__current === self.__finish) {
4830
+ self.trigger("complete", self.__eventArgs());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4831
 
4832
+ self.__reset();
4833
+ } else {
4834
+ if (self.__decrement) {
4835
+ self.__current--;
4836
+ } else {
4837
+ self.__current++;
4838
+ }
4839
 
4840
+ self.__remaining--;
4841
+ self.canResume = self.__remaining > 0;
4842
+ self.__timeout = setTimeout(function () {
4843
+ self.__tick();
4844
+ }, self.interval);
4845
+ }
4846
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4847
 
4848
+ /**
4849
+ * @summary Starts the timer using the supplied `time` and whether or not to increment or decrement from the value.
4850
+ * @memberof FooGallery.utils.Timer#
4851
+ * @function start
4852
+ * @param {number} time - The total time in seconds for the timer.
4853
+ * @param {boolean} [decrement=false] - Whether the timer should increment or decrement from or to the supplied time.
4854
+ */
4855
+ start: function start(time, decrement) {
4856
+ var self = this;
4857
+ if (self.isRunning) return;
4858
+ decrement = _is.boolean(decrement) ? decrement : false;
4859
+ self.__restart = [time, decrement];
4860
+ self.__decrement = decrement;
4861
+ self.__time = time;
4862
+ self.__remaining = time;
4863
+ self.__current = decrement ? time : 0;
4864
+ self.__finish = decrement ? 0 : time;
4865
+ self.canRestart = true;
4866
+ self.isRunning = true;
4867
+ self.isPaused = false;
4868
+ self.trigger("start", self.__eventArgs());
4869
+
4870
+ self.__tick();
4871
+ },
4872
 
4873
+ /**
4874
+ * @summary Starts the timer counting down to `0` from the supplied `time`.
4875
+ * @memberof FooGallery.utils.Timer#
4876
+ * @function countdown
4877
+ * @param {number} time - The total time in seconds for the timer.
4878
+ */
4879
+ countdown: function countdown(time) {
4880
+ this.start(time, true);
4881
+ },
 
 
4882
 
4883
+ /**
4884
+ * @summary Starts the timer counting up from `0` to the supplied `time`.
4885
+ * @memberof FooGallery.utils.Timer#
4886
+ * @function countup
4887
+ * @param {number} time - The total time in seconds for the timer.
4888
+ */
4889
+ countup: function countup(time) {
4890
+ this.start(time, false);
4891
+ },
4892
 
4893
+ /**
4894
+ * @summary Stops and then restarts the timer using the last arguments supplied to the {@link FooGallery.utils.Timer#start|start} method.
4895
+ * @memberof FooGallery.utils.Timer#
4896
+ * @function restart
4897
+ */
4898
+ restart: function restart() {
4899
+ var self = this;
4900
+ self.stop();
 
4901
 
4902
+ if (self.canRestart) {
4903
+ self.start.apply(self, self.__restart);
4904
+ }
4905
+ },
 
 
4906
 
4907
+ /**
4908
+ * @summary Stops the timer.
4909
+ * @memberof FooGallery.utils.Timer#
4910
+ * @function stop
4911
+ */
4912
+ stop: function stop() {
4913
+ var self = this;
4914
 
4915
+ if (self.isRunning || self.isPaused) {
4916
+ self.__reset();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4917
 
4918
+ self.trigger("stop", self.__eventArgs());
4919
+ }
4920
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4921
 
4922
+ /**
4923
+ * @summary Pauses the timer and returns the remaining seconds.
4924
+ * @memberof FooGallery.utils.Timer#
4925
+ * @function pause
4926
+ * @return {number} - The number of seconds remaining for the timer.
4927
+ */
4928
+ pause: function pause() {
4929
+ var self = this;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4930
 
4931
+ if (self.__timeout != null) {
4932
+ clearTimeout(self.__timeout);
4933
+ self.__timeout = null;
4934
+ }
 
 
4935
 
4936
+ if (self.isRunning) {
4937
+ self.isRunning = false;
4938
+ self.isPaused = true;
4939
+ self.trigger("pause", self.__eventArgs());
4940
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4941
 
4942
+ return self.__remaining;
4943
+ },
 
 
 
 
 
 
4944
 
4945
+ /**
4946
+ * @summary Resumes the timer from a previously paused state.
4947
+ * @memberof FooGallery.utils.Timer#
4948
+ * @function resume
4949
+ */
4950
+ resume: function resume() {
4951
+ var self = this;
 
 
 
 
4952
 
4953
+ if (self.canResume) {
4954
+ self.isRunning = true;
4955
+ self.isPaused = false;
4956
+ self.trigger("resume", self.__eventArgs());
4957
 
4958
+ self.__tick();
4959
+ }
4960
+ },
 
 
 
 
 
 
 
4961
 
4962
+ /**
4963
+ * @summary Resets the timer back to a fresh starting state.
4964
+ * @memberof FooGallery.utils.Timer#
4965
+ * @function reset
4966
+ */
4967
+ reset: function reset() {
4968
+ var self = this;
 
 
 
 
 
 
 
 
 
 
 
4969
 
4970
+ self.__reset();
 
 
 
 
 
 
 
 
 
4971
 
4972
+ self.trigger("reset", this.__eventArgs());
4973
+ }
4974
+ });
4975
+ })(FooGallery.utils.$, FooGallery.utils, FooGallery.utils.is, FooGallery.utils.fn, FooGallery.utils.obj);
4976
+
4977
+ (function ($, _, _fn) {
4978
+ // only register methods if this version is the current version
4979
+ if (_.version !== '1.0.0') return; // noinspection JSUnusedGlobalSymbols
4980
+
4981
+ /**
4982
+ * @summary A wrapper around the fullscreen API to ensure cross browser compatibility.
4983
+ * @memberof FooGallery.utils.
4984
+ * @class FullscreenAPI
4985
+ * @augments FooGallery.utils.EventClass
4986
+ * @borrows FooGallery.utils.EventClass.extend as extend
4987
+ * @borrows FooGallery.utils.EventClass.override as override
4988
+ */
4989
+
4990
+ _.FullscreenAPI = _.EventClass.extend(
4991
+ /** @lends FooGallery.utils.FullscreenAPI */
4992
+ {
4993
+ /**
4994
+ * @ignore
4995
+ * @constructs
4996
+ */
4997
+ construct: function construct() {
4998
+ this._super();
4999
+ /**
5000
+ * @summary An object containing a single browsers various methods and events needed for this wrapper.
5001
+ * @typedef {?Object} FooGallery.utils.FullscreenAPI~BrowserAPI
5002
+ * @property {string} enabled
5003
+ * @property {string} element
5004
+ * @property {string} request
5005
+ * @property {string} exit
5006
+ * @property {Object} events
5007
+ * @property {string} events.change
5008
+ * @property {string} events.error
5009
+ */
5010
+
5011
+ /**
5012
+ * @summary An object containing the supported fullscreen browser API's.
5013
+ * @typedef {Object.<string, FooGallery.utils.FullscreenAPI~BrowserAPI>} FooGallery.utils.FullscreenAPI~SupportedBrowsers
5014
+ */
5015
+
5016
+ /**
5017
+ * @summary Contains the various browser specific method and event names.
5018
+ * @memberof FooGallery.utils.FullscreenAPI#
5019
+ * @name apis
5020
+ * @type {FooGallery.utils.FullscreenAPI~SupportedBrowsers}
5021
+ */
5022
+
5023
+
5024
+ this.apis = {
5025
+ w3: {
5026
+ enabled: "fullscreenEnabled",
5027
+ element: "fullscreenElement",
5028
+ request: "requestFullscreen",
5029
+ exit: "exitFullscreen",
5030
+ events: {
5031
+ change: "fullscreenchange",
5032
+ error: "fullscreenerror"
5033
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5034
  },
5035
+ webkit: {
5036
+ enabled: "webkitFullscreenEnabled",
5037
+ element: "webkitCurrentFullScreenElement",
5038
+ request: "webkitRequestFullscreen",
5039
+ exit: "webkitExitFullscreen",
5040
+ events: {
5041
+ change: "webkitfullscreenchange",
5042
+ error: "webkitfullscreenerror"
5043
+ }
 
 
 
 
 
 
 
 
 
5044
  },
5045
+ moz: {
5046
+ enabled: "mozFullScreenEnabled",
5047
+ element: "mozFullScreenElement",
5048
+ request: "mozRequestFullScreen",
5049
+ exit: "mozCancelFullScreen",
5050
+ events: {
5051
+ change: "mozfullscreenchange",
5052
+ error: "mozfullscreenerror"
5053
+ }
 
 
 
 
5054
  },
5055
+ ms: {
5056
+ enabled: "msFullscreenEnabled",
5057
+ element: "msFullscreenElement",
5058
+ request: "msRequestFullscreen",
5059
+ exit: "msExitFullscreen",
5060
+ events: {
5061
+ change: "MSFullscreenChange",
5062
+ error: "MSFullscreenError"
5063
+ }
5064
  }
5065
+ };
5066
+ /**
5067
+ * @summary The current browsers specific method and event names.
5068
+ * @memberof FooGallery.utils.FullscreenAPI#
5069
+ * @name api
5070
+ * @type {FooGallery.utils.FullscreenAPI~BrowserAPI}
5071
+ */
5072
+
5073
+ this.api = this.getAPI();
5074
+ /**
5075
+ * @summary Whether or not the fullscreen API is supported in the current browser.
5076
+ * @memberof FooGallery.utils.FullscreenAPI#
5077
+ * @name supported
5078
+ * @type {boolean}
5079
+ */
5080
+
5081
+ this.supported = this.api != null;
5082
+
5083
+ this.__listen();
5084
+ },
5085
 
5086
+ /**
5087
+ * @summary Destroys the current wrapper unbinding events and freeing up resources.
5088
+ * @memberof FooGallery.utils.FullscreenAPI#
5089
+ * @function destroy
5090
+ * @returns {boolean}
5091
+ */
5092
+ destroy: function destroy() {
5093
+ this.__stopListening();
5094
 
5095
+ return this._super();
5096
+ },
 
5097
 
5098
+ /**
5099
+ * @summary Fetches the correct API for the current browser.
5100
+ * @memberof FooGallery.utils.FullscreenAPI#
5101
+ * @function getAPI
5102
+ * @return {?FooGallery.utils.FullscreenAPI~BrowserAPI} Returns `null` if the fullscreen API is not supported.
5103
+ */
5104
+ getAPI: function getAPI() {
5105
+ for (var vendor in this.apis) {
5106
+ if (!this.apis.hasOwnProperty(vendor)) continue; // Check if document has the "enabled" property
 
 
 
 
 
 
 
 
 
 
 
 
 
5107
 
5108
+ if (this.apis[vendor].enabled in document) {
5109
+ // It seems this browser supports the fullscreen API
5110
+ return this.apis[vendor];
5111
+ }
5112
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5113
 
5114
+ return null;
5115
+ },
 
 
 
 
 
 
5116
 
5117
+ /**
5118
+ * @summary Gets the current fullscreen element or null.
5119
+ * @memberof FooGallery.utils.FullscreenAPI#
5120
+ * @function element
5121
+ * @returns {?Element}
5122
+ */
5123
+ element: function element() {
5124
+ return this.supported ? document[this.api.element] : null;
5125
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5126
 
5127
+ /**
5128
+ * @summary Requests the browser to place the specified element into fullscreen mode.
5129
+ * @memberof FooGallery.utils.FullscreenAPI#
5130
+ * @function request
5131
+ * @param {Element} element - The element to place into fullscreen mode.
5132
+ * @returns {Promise} A Promise which is resolved once the element is placed into fullscreen mode.
5133
+ */
5134
+ request: function request(element) {
5135
+ if (this.supported && !!element[this.api.request]) {
5136
+ var result = element[this.api.request]();
5137
+ return !result ? $.Deferred(this.__resolver(this.api.request)).promise() : result;
5138
+ }
5139
+
5140
+ return _fn.rejected;
5141
+ },
5142
 
5143
  /**
5144
+ * @summary Requests that the browser switch from fullscreen mode back to windowed mode.
5145
+ * @memberof FooGallery.utils.FullscreenAPI#
5146
+ * @function exit
5147
+ * @returns {Promise} A Promise which is resolved once fullscreen mode is exited.
 
 
5148
  */
5149
+ exit: function exit() {
5150
+ if (this.supported && !!this.element()) {
5151
+ var result = document[this.api.exit]();
5152
+ return !result ? $.Deferred(this.__resolver(this.api.exit)).promise() : result;
5153
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
5154
 
5155
+ return _fn.rejected;
5156
+ },
 
 
5157
 
5158
+ /**
5159
+ * @summary Toggles the supplied element between fullscreen and windowed modes.
5160
+ * @memberof FooGallery.utils.FullscreenAPI#
5161
+ * @function toggle
5162
+ * @param {Element} element - The element to switch between modes.
5163
+ * @returns {Promise} A Promise that is resolved once fullscreen mode is either entered or exited.
5164
+ */
5165
+ toggle: function toggle(element) {
5166
+ return !!this.element() ? this.exit() : this.request(element);
5167
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5168
 
5169
+ /**
5170
+ * @summary Starts listening to the document level fullscreen events and triggers an abbreviated version on this class.
5171
+ * @memberof FooGallery.utils.FullscreenAPI#
5172
+ * @function __listen
5173
+ * @private
5174
+ */
5175
+ __listen: function __listen() {
5176
+ var self = this;
5177
+ if (!self.supported) return;
5178
+ $(document).on(self.api.events.change + ".utils", function () {
5179
+ self.trigger("change");
5180
+ }).on(self.api.events.error + ".utils", function () {
5181
+ self.trigger("error");
5182
+ });
5183
+ },
5184
 
5185
+ /**
5186
+ * @summary Stops listening to the document level fullscreen events.
5187
+ * @memberof FooGallery.utils.FullscreenAPI#
5188
+ * @function __stopListening
5189
+ * @private
5190
+ */
5191
+ __stopListening: function __stopListening() {
5192
+ var self = this;
5193
+ if (!self.supported) return;
5194
+ $(document).off(self.api.events.change + ".utils").off(self.api.events.error + ".utils");
5195
+ },
5196
 
5197
+ /**
5198
+ * @summary Creates a resolver function to patch browsers which do not return a Promise from there request and exit methods.
5199
+ * @memberof FooGallery.utils.FullscreenAPI#
5200
+ * @function __resolver
5201
+ * @param {string} method - The request or exit method the resolver is being created for.
5202
+ * @returns {FooGallery.utils.FullscreenAPI~resolver}
5203
+ * @private
5204
+ */
5205
+ __resolver: function __resolver(method) {
5206
+ var self = this;
5207
+ /**
5208
+ * @summary Binds to the fullscreen change and error events and resolves or rejects the supplied deferred accordingly.
5209
+ * @callback FooGallery.utils.FullscreenAPI~resolver
5210
+ * @param {jQuery.Deferred} def - The jQuery.Deferred object to resolve.
5211
+ */
5212
+
5213
+ return function resolver(def) {
5214
+ // Reject the promise if asked to exitFullscreen and there is no element currently in fullscreen
5215
+ if (method === self.api.exit && !!self.element()) {
5216
+ setTimeout(function () {
5217
+ // noinspection JSUnresolvedFunction
5218
+ def.reject(new TypeError());
5219
+ }, 1);
5220
+ return;
5221
+ } // When receiving an internal fullscreenchange event, fulfill the promise
5222
+
5223
+
5224
+ function change() {
5225
+ // noinspection JSUnresolvedFunction
5226
+ def.resolve();
5227
+ $(document).off(self.api.events.change, change).off(self.api.events.error, error);
5228
+ } // When receiving an internal fullscreenerror event, reject the promise
5229
+
5230
+
5231
+ function error() {
5232
+ // noinspection JSUnresolvedFunction
5233
+ def.reject(new TypeError());
5234
+ $(document).off(self.api.events.change, change).off(self.api.events.error, error);
5235
  }
 
5236
 
5237
+ $(document).on(self.api.events.change, change).on(self.api.events.error, error);
5238
+ };
5239
+ }
5240
+ });
5241
+ })(FooGallery.utils.$, FooGallery.utils, FooGallery.utils.fn);
5242
+
5243
+ (function ($, _, _is, _fn) {
5244
+ // only register methods if this version is the current version
5245
+ if (_.version !== '1.0.0') return;
5246
+ /**
5247
+ * @summary Contains common utility methods and members for the CSS transition property.
5248
+ * @memberof FooGallery.utils.
5249
+ * @namespace transition
5250
+ */
5251
+
5252
+ _.transition = {};
5253
+ /**
5254
+ * @summary The data name used by transitions to ensure promises are resolved.
5255
+ * @memberof FooGallery.utils.transition.
5256
+ * @name dataName
5257
+ * @type {string}
5258
+ * @default "__foo-transition__"
5259
+ */
5260
+
5261
+ _.transition.dataName = '__foo-transition__';
5262
+ /**
5263
+ * @summary The CSS className used to disable transitions when using the {@link FooGallery.utils.transition.disable|disable} method instead of inline styles.
5264
+ * @memberof FooGallery.utils.transition.
5265
+ * @name disableClassName
5266
+ * @type {?string}
5267
+ * @default null
5268
+ */
5269
+
5270
+ _.transition.disableClassName = null;
5271
+ /**
5272
+ * @summary The global timeout used as a safety measure when using the {@link FooGallery.utils.transition.start|start} method. This can be overridden using the `timeout` parameter of the {@link FooGallery.utils.transition.start|start} method.
5273
+ * @memberof FooGallery.utils.transition.
5274
+ * @name timeout
5275
+ * @type {number}
5276
+ * @default 3000
5277
+ */
5278
+
5279
+ _.transition.timeout = 3000;
5280
+ /**
5281
+ * @summary Disable transitions temporarily on the provided element so changes can be made immediately within the callback.
5282
+ * @memberof FooGallery.utils.transition.
5283
+ * @function disable
5284
+ * @param {(jQuery|HTMLElement)} element - The element to disable transitions on.
5285
+ * @param {FooGallery.utils.transition~modifyFn} modifyFn - A function to execute while the elements transitions are disabled.
5286
+ */
5287
+
5288
+ _.transition.disable = function (element, modifyFn) {
5289
+ var $el = _is.jq(element) ? element : $(element);
5290
+
5291
+ if ($el.length > 0 && _is.fn(modifyFn)) {
5292
+ var el = $el.get(0),
5293
+ hasClass = _is.string(_.transition.disableClassName);
5294
+
5295
+ var restore = null;
5296
+ if (hasClass) $el.addClass(_.transition.disableClassName);else {
5297
+ restore = {
5298
+ value: el.style.getPropertyValue('transition'),
5299
+ priority: el.style.getPropertyPriority('transition')
5300
+ };
5301
+ el.style.setProperty('transition', 'none', 'important');
5302
+ }
5303
+ modifyFn.call(modifyFn, $el);
5304
+ $el.prop("offsetWidth");
5305
+ if (hasClass) $el.removeClass(_.transition.disableClassName);else {
5306
+ el.style.removeProperty('transition');
5307
+
5308
+ if (_is.string(restore.value) && restore.value.length > 0) {
5309
+ el.style.setProperty('transition', restore.value, restore.priority);
5310
+ }
5311
+ }
5312
+ }
5313
+ };
5314
+ /**
5315
+ * @summary Stop a transition started using the {@link FooGallery.utils.transition.start|start} method.
5316
+ * @memberof FooGallery.utils.transition.
5317
+ * @function stop
5318
+ * @param {(jQuery|HTMLElement)} element - The element to stop the transition on.
5319
+ * @returns {Promise}
5320
+ */
5321
+
5322
+
5323
+ _.transition.stop = function (element) {
5324
+ var d = $.Deferred(),
5325
+ $el = _is.jq(element) ? element : $(element);
5326
+
5327
+ if ($el.length > 0) {
5328
+ var current = $el.data(_.transition.dataName);
5329
+
5330
+ if (_is.promise(current)) {
5331
+ current.always(function () {
5332
+ // request the next frame to give the previous event unbinds time to settle
5333
+ _.requestFrame(function () {
5334
+ d.resolve($el);
5335
+ });
5336
+ }).reject(new Error("Transition cancelled."));
5337
+ } else {
5338
+ d.resolve($el);
5339
+ }
5340
+ } else {
5341
+ d.reject(new Error("Unable to stop transition. Make sure the element exists."));
5342
+ }
5343
 
5344
+ return d.promise();
5345
+ };
5346
+ /**
5347
+ * @summary Creates a new transition event listener ensuring the element and optionally the propertyName matches before executing the callback.
5348
+ * @memberof FooGallery.utils.transition.
5349
+ * @function createListener
5350
+ * @param {HTMLElement} element - The element being listened to.
5351
+ * @param {function(*): void} callback - The callback to execute once the element and optional propertyName are matched.
5352
+ * @param {?string} [propertyName=null] - The propertyName to match on the TransitionEvent object.
5353
+ * @returns {function(*): void}
5354
+ */
5355
+
5356
+
5357
+ _.transition.createListener = function (element, callback, propertyName) {
5358
+ var el = element,
5359
+ fn = callback,
5360
+ prop = propertyName,
5361
+ hasProp = _is.string(propertyName);
5362
+
5363
+ return function (event) {
5364
+ var evt = event.originalEvent instanceof TransitionEvent ? event.originalEvent : event;
5365
+ var matches = false;
5366
+
5367
+ if (evt.target === el) {
5368
+ matches = hasProp ? evt.propertyName === prop : true;
5369
+ }
5370
+
5371
+ if (matches) fn.apply(fn, _fn.arg2arr(arguments));
5372
+ };
5373
+ };
5374
+ /**
5375
+ * @summary Start a transition on an element returning a promise that is resolved once the transition ends.
5376
+ * @memberof FooGallery.utils.transition.
5377
+ * @function start
5378
+ * @param {(jQuery|HTMLElement)} element - The element to perform the transition on.
5379
+ * @param {FooGallery.utils.transition~modifyFn} triggerFn - The callback that triggers the transition on the element.
5380
+ * @param {?string} [propertyName] - A specific property name to wait for before resolving. If not supplied the first instance of the transitionend event will resolve the promise.
5381
+ * @param {number} [timeout] - A safety timeout to ensure the returned promise is finalized. If not supplied the value of the {@link FooGallery.utils.transition.timeout} property is used.
5382
+ * @returns {Promise}
5383
+ */
5384
+
5385
+
5386
+ _.transition.start = function (element, triggerFn, propertyName, timeout) {
5387
+ var d = $.Deferred(),
5388
+ $el = _is.jq(element) ? element : $(element);
5389
+
5390
+ if ($el.length > 0 && _is.fn(triggerFn)) {
5391
+ var el = $el.get(0); // first stop any active transitions
5392
+
5393
+ _.transition.stop($el).always(function () {
5394
+ // then setup the data object and event listeners for the new transition
5395
+ var listener = _.transition.createListener(el, function () {
5396
+ d.resolve($el);
5397
+ }, propertyName);
5398
+
5399
+ $el.data(_.transition.dataName, d).on("transitionend.foo-utils", listener).prop("offsetWidth"); // force layout to ensure transitions on newly appended elements occur
5400
+ // request the next frame to give the event bindings time to settle
5401
+
5402
+ _.requestFrame(function () {
5403
+ // just in case a transition is cancelled by some other means and the transitionend event is never fired this
5404
+ // timeout ensures the returned promise is always finalized.
5405
+ var safety = setTimeout(function () {
5406
+ d.reject(new Error("Transition safety timeout triggered."));
5407
+ }, _is.number(timeout) ? timeout : _.transition.timeout); // we always want to cleanup after ourselves so clear the safety, remove the data object and unbind the events
5408
+
5409
+ d.always(function () {
5410
+ clearTimeout(safety);
5411
+ $el.removeData(_.transition.dataName).off("transitionend.foo-utils", listener);
5412
+ }); // now that everything is setup kick off the transition by calling the triggerFn
5413
+
5414
+ triggerFn.call(triggerFn, $el);
5415
+ });
5416
+ });
5417
+ } else {
5418
+ d.reject(new Error("Unable to perform transition. Make sure the element exists and a trigger function is supplied."));
5419
+ }
5420
+
5421
+ return d.promise();
5422
+ };
5423
+ /**
5424
+ * @summary Used to modify an element which has transitions optionally allowing the transition to occur or not.
5425
+ * @memberof FooGallery.utils.transition.
5426
+ * @function modify
5427
+ * @param {(jQuery|HTMLElement)} element - The element to perform the modifications to.
5428
+ * @param {FooGallery.utils.transition~modifyFn} modifyFn - The callback used to perform the modifications.
5429
+ * @param {boolean} [immediate=false] - Whether or not transitions should be allowed to execute and waited on. The default value of `false` means transitions are allowed and the promise will only resolve once there transitionend event has fired.
5430
+ * @param {?string} [propertyName=null] - A specific property name to wait for before resolving. If not supplied the first instance of the transitionend event will resolve the promise.
5431
+ * @returns {Promise} Returns a promise that is resolved once the modifications to the element have ended.
5432
+ */
5433
+
5434
+
5435
+ _.transition.modify = function (element, modifyFn, immediate, propertyName) {
5436
+ var $el = _is.jq(element) ? element : $(element);
5437
+
5438
+ if ($el.length > 0 && _is.fn(modifyFn)) {
5439
+ if (immediate) {
5440
+ _.transition.disable($el, modifyFn);
5441
+
5442
+ return _fn.resolve();
5443
+ }
5444
+
5445
+ return _.transition.start($el, modifyFn, propertyName);
5446
+ }
5447
+
5448
+ return _fn.reject(new Error("Unable to perform modification. Make sure the element exists and a modify function is supplied."));
5449
+ };
5450
+ /**
5451
+ * @summary Perform one or more modifications to the element such as setting inline styles or toggling classNames.
5452
+ * @callback FooGallery.utils.transition~modifyFn
5453
+ * @param {jQuery} $element - The jQuery object for the element to modify.
5454
+ */
5455
+
5456
+ })( // dependencies
5457
+ FooGallery.utils.$, FooGallery.utils, FooGallery.utils.is, FooGallery.utils.fn);
5458
+
5459
+ (function ($, _, _utils, _is, _fn, _str) {
5460
 
5461
  /**
5462
  * @summary The name to use when getting or setting an instance of a {@link FooGallery.Template|template} on an element using jQuery's `.data()` method.
5495
  return tmpl instanceof _.Template ? tmpl.initialize() : _fn.rejected;
5496
  };
5497
 
 
 
 
 
 
 
5498
  /**
5499
  * @summary Expose FooGallery as a jQuery plugin.
5500
  * @memberof external:"jQuery.fn"#
5612
  return _.supportedExifProperties.indexOf(key) !== -1 && !_is.empty(value[key]);
5613
  });
5614
  }
5615
+ return false;
5616
+ };
5617
+
5618
+ /**
5619
+ * @summary Trims the value if it exceeds the specified length and appends the suffix.
5620
+ * @memberof FooGallery.utils.str.
5621
+ * @function trimTo
5622
+ * @param {string} value - The value to trim if required.
5623
+ * @param {number} length - The length to trim the string to.
5624
+ * @param {string} [suffix="&hellip;"] - The suffix to append to a trimmed value.
5625
+ * @returns {string|null}
5626
+ */
5627
+ _str.trimTo = function(value, length, suffix){
5628
+ if (_is.string(value) && _is.number(length) && length > 0 && value.length > length) {
5629
+ return value.substr(0, length) + (_is.string(suffix) ? suffix : "&hellip;");
5630
+ }
5631
+ return value;
5632
+ };
5633
+
5634
+ /**
5635
+ * @typedef {Object} ResizeObserverSize
5636
+ * @property {number} inlineSize
5637
+ * @property {number} blockSize
5638
+ * @property {number} width
5639
+ * @property {number} height
5640
+ */
5641
+ /**
5642
+ * @typedef {Object} ResizeObserverEntry
5643
+ * @property {ResizeObserverSize|Array<ResizeObserverSize>|undefined} contentBoxSize
5644
+ * @property {DOMRect} contentRect
5645
+ */
5646
+ /**
5647
+ * @summary Gets the width and height from the ResizeObserverEntry
5648
+ * @memberof FooGallery.utils.
5649
+ * @function getResizeObserverSize
5650
+ * @param {ResizeObserverEntry} entry - The entry to retrieve the size from.
5651
+ * @returns {{width: Number,height: Number}}
5652
+ */
5653
+ _utils.getResizeObserverSize = function(entry){
5654
+ var width, height;
5655
+ if(entry.contentBoxSize) {
5656
+ // Checking for chrome as using a non-standard array
5657
+ if (entry.contentBoxSize[0]) {
5658
+ width = entry.contentBoxSize[0].inlineSize;
5659
+ height = entry.contentBoxSize[0].blockSize;
5660
+ } else {
5661
+ width = entry.contentBoxSize.inlineSize;
5662
+ height = entry.contentBoxSize.blockSize;
5663
+ }
5664
+ } else {
5665
+ width = entry.contentRect.width;
5666
+ height = entry.contentRect.height;
5667
+ }
5668
+ return {
5669
+ width: width,
5670
+ height: height
5671
+ };
5672
+ };
5673
+
5674
+ /**
5675
+ * @summary Whether or not the current browser supports "webp" images.
5676
+ * @memberof FooGallery
5677
+ * @name supportsWebP
5678
+ * @type {boolean}
5679
+ * @default false
5680
+ */
5681
+ _.supportsWebP = false;
5682
+
5683
+ var webp = new Image();
5684
+ webp.onload = function(){
5685
+ _.supportsWebP = 0 < webp.width && 0 < webp.height;
5686
  };
5687
+ webp.onerror=function(){
5688
+ _.supportsWebP = false;
5689
+ };
5690
+ webp.src = 'data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==';
5691
 
5692
  })(
5693
  FooGallery.$,
5697
  FooGallery.utils.fn,
5698
  FooGallery.utils.str
5699
  );
5700
+ (function($, _, _utils, _is, _obj){
5701
+
5702
+ _.Icons = _utils.Class.extend({
5703
+ construct: function(){
5704
+ this.className = "fg-icon";
5705
+ this.registered = {
5706
+ "default": {
5707
+ "close": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.957 3.457l-1.414-1.414-4.543 4.543-4.543-4.543-1.414 1.414 4.543 4.543-4.543 4.543 1.414 1.414 4.543-4.543 4.543 4.543 1.414-1.414-4.543-4.543z"></path></svg>',
5708
+ "arrow-left": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M10.5 16l1.5-1.5-6.5-6.5 6.5-6.5-1.5-1.5-8 8 8 8z"></path></svg>',
5709
+ "arrow-right": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M5.5 0l-1.5 1.5 6.5 6.5-6.5 6.5 1.5 1.5 8-8-8-8z"></path></svg>',
5710
+ "maximize": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M2 2v4h-2v-5c0-0.552 0.448-1 1-1h14c0.552 0 1 0.448 1 1v14c0 0.552-0.448 1-1 1h-14c-0.552 0-1-0.448-1-1v-9h9c0.552 0 1 0.448 1 1v7h4v-12h-12z"/></svg>',
5711
+ "expand": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M2 5h-2v-4c0-0.552 0.448-1 1-1h4v2h-3v3z"></path><path d="M16 5h-2v-3h-3v-2h4c0.552 0 1 0.448 1 1v4z"></path><path d="M15 16h-4v-2h3v-3h2v4c0 0.552-0.448 1-1 1z"></path><path d="M5 16h-4c-0.552 0-1-0.448-1-1v-4h2v3h3v2z"></path></svg>',
5712
+ "shrink": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 0h2v4c0 0.552-0.448 1-1 1h-4v-2h3v-3z"></path><path d="M11 0h2v3h3v2h-4c-0.552 0-1-0.448-1-1v-4z"></path><path d="M12 11h4v2h-3v3h-2v-4c0-0.552 0.448-1 1-1z"></path><path d="M0 11h4c0.552 0 1 0.448 1 1v4h-2v-3h-3v-2z"></path></svg>',
5713
+ "info": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M7 4.75c0-0.412 0.338-0.75 0.75-0.75h0.5c0.412 0 0.75 0.338 0.75 0.75v0.5c0 0.412-0.338 0.75-0.75 0.75h-0.5c-0.412 0-0.75-0.338-0.75-0.75v-0.5z"></path><path d="M10 12h-4v-1h1v-3h-1v-1h3v4h1z"></path><path d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM8 14.5c-3.59 0-6.5-2.91-6.5-6.5s2.91-6.5 6.5-6.5 6.5 2.91 6.5 6.5-2.91 6.5-6.5 6.5z"></path></svg>',
5714
+ "comment": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 4h10v1h-10zM3 6h8v1h-8zM3 8h4v1h-4zM14.5 1h-13c-0.825 0-1.5 0.675-1.5 1.5v8c0 0.825 0.675 1.5 1.5 1.5h2.5v4l4.8-4h5.7c0.825 0 1.5-0.675 1.5-1.5v-8c0-0.825-0.675-1.5-1.5-1.5zM14 10h-5.924l-3.076 2.73v-2.73h-3v-7h12v7z"></path></svg>',
5715
+ "thumbs": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 3v10h-2v-11c0-0.552 0.448-1 1-1h12c0.552 0 1 0.448 1 1v12c0 0.552-0.448 1-1 1h-12c-0.552 0-1-0.448-1-1v-1h4v-2h-2v-2h2v-2h-2v-2h2v-2h2v10h6v-10h-10z"></path></svg>',
5716
+ "cart": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.238 9c0.55 0 1.124-0.433 1.275-0.962l1.451-5.077c0.151-0.529-0.175-0.962-0.725-0.962h-10.238c0-1.105-0.895-2-2-2h-3v2h3v8.5c0 0.828 0.672 1.5 1.5 1.5h9.5c0.552 0 1-0.448 1-1s-0.448-1-1-1h-9v-1h8.238zM5 4h9.044l-0.857 3h-8.187v-3z"></path><path d="M6 14.5c0 0.828-0.672 1.5-1.5 1.5s-1.5-0.672-1.5-1.5c0-0.828 0.672-1.5 1.5-1.5s1.5 0.672 1.5 1.5z"></path><path d="M15 14.5c0 0.828-0.672 1.5-1.5 1.5s-1.5-0.672-1.5-1.5c0-0.828 0.672-1.5 1.5-1.5s1.5 0.672 1.5 1.5z"></path></svg>',
5717
+ "circle-close": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM8 14.5c-3.59 0-6.5-2.91-6.5-6.5s2.91-6.5 6.5-6.5 6.5 2.91 6.5 6.5-2.91 6.5-6.5 6.5z"></path><path d="M10.5 4l-2.5 2.5-2.5-2.5-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 2.5-2.5 2.5 2.5 1.5-1.5-2.5-2.5 2.5-2.5z"></path></svg>',
5718
+ "auto-progress": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path class="[ICON_CLASS]-idle" d="M11.39 8c2.152-1.365 3.61-3.988 3.61-7 0-0.339-0.019-0.672-0.054-1h-13.891c-0.036 0.328-0.054 0.661-0.054 1 0 3.012 1.457 5.635 3.609 7-2.152 1.365-3.609 3.988-3.609 7 0 0.339 0.019 0.672 0.054 1h13.891c0.036-0.328 0.054-0.661 0.054-1 0-3.012-1.457-5.635-3.609-7zM2.5 15c0-2.921 1.253-5.397 3.5-6.214v-1.572c-2.247-0.817-3.5-3.294-3.5-6.214v0h11c0 2.921-1.253 5.397-3.5 6.214v1.572c2.247 0.817 3.5 3.294 3.5 6.214h-11zM9.462 10.462c-1.12-0.635-1.181-1.459-1.182-1.959v-1.004c0-0.5 0.059-1.327 1.184-1.963 0.602-0.349 1.122-0.88 1.516-1.537h-6.4c0.395 0.657 0.916 1.188 1.518 1.538 1.12 0.635 1.181 1.459 1.182 1.959v1.004c0 0.5-0.059 1.327-1.184 1.963-1.135 0.659-1.98 1.964-2.236 3.537h7.839c-0.256-1.574-1.102-2.879-2.238-3.538z"/><circle class="[ICON_CLASS]-circle" r="4" cx="8" cy="8"/><path class="[ICON_CLASS]-play" d="M3 2l10 6-10 6z"/><path class="[ICON_CLASS]-pause" d="M2 2h5v12h-5zM9 2h5v12h-5z"/></svg>',
5719
+ "exif-aperture": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 8,0 C 3.5876443,0 0,3.5876443 0,8 c 0,4.412356 3.5876443,8 8,8 4.412356,0 8,-3.587644 8,-8 C 16,3.5876443 12.412356,0 8,0 Z m 0,1 c 3.871916,0 7,3.1280844 7,7 0,3.871916 -3.128084,7 -7,7 C 4.1280844,15 1,11.871916 1,8 1,4.1280844 4.1280844,1 8,1 Z M 7.53125,2.0214844 A 6,6 0 0 0 3.1835938,4.4335938 H 8.9257812 Z M 8.6132812,2.03125 C 9.5587451,3.6702105 10.504247,5.3091484 11.451172,6.9472656 L 12.863281,4.5 A 6,6 0 0 0 8.6132812,2.03125 Z M 2.5957031,5.4101562 A 6,6 0 0 0 2,8 6,6 0 0 0 2.5273438,10.439453 L 5.4296875,5.4101562 Z m 10.8261719,0.033203 -2.855469,4.9433598 h 2.935547 A 6,6 0 0 0 14,8 6,6 0 0 0 13.421875,5.4433592 Z M 4.5722656,8.8945312 3.0996094,11.449219 a 6,6 0 0 0 4.40625,2.527343 z m 2.5820313,2.4707028 1.4960937,2.591797 a 6,6 0 0 0 4.3144534,-2.591797 z"></path></svg>',
5720
+ "exif-camera": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="m 8.0000002,5 a 4,4 0 0 0 -4,4 4,4 0 0 0 4,4 A 4,4 0 0 0 12,9 4,4 0 0 0 8.0000002,5 Z m 0.019531,1.015625 a 3,2.9814477 0 0 1 2.9804688,3 l -1,-0.00586 a 2,2 0 0 0 0,-0.00976 2,2 0 0 0 -1.9863279,-2 z M 5.125,1 C 4.5,1 4,1.5 4,2.125 V 3.0000004 L 1.125,3 C 0.5,2.9999999 0,3.5 0,4.125 v 9.75 C 0,14.5 0.5,15 1.125,15 h 13.75 C 15.5,15 16,14.5 16,13.875 V 4.125 C 16,3.5 15.5,3 14.875,3 H 12 V 2.125 C 12,1.5 11.5,1 10.875,1 Z M 5.25,2.0000004 h 5.5 c 0.125,0 0.25,0.1249996 0.25,0.25 v 1.75 h 3.75 c 0.125,0 0.25,0.1249996 0.25,0.25 V 13.75 C 15,13.875 14.875,14 14.75,14 H 1.25 C 1.125,14 1,13.875 1,13.75 V 4.25 C 1,4.125 1.125,4 1.25,4 l 3.75,4e-7 v -1.75 c 0,-0.1250004 0.125,-0.25 0.25,-0.25 z"></path></svg>',
5721
+ "exif-created-timestamp": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 3,1 V 2 H 1 V 15 H 16 V 2 H 14 V 1 H 13 V 2 H 4 V 1 Z M 2,4 H 15 V 14 H 2 Z M 6,5 V 7 H 8 V 5 Z m 3,0 v 2 h 2 V 5 Z m 3,0 v 2 h 2 V 5 Z M 3,8 v 2 H 5 V 8 Z m 3,0 v 2 H 8 V 8 Z m 3,0 v 2 h 2 V 8 Z m 3,0 v 2 h 2 V 8 Z m -9,3 v 2 h 2 v -2 z m 3,0 v 2 h 2 v -2 z m 3,0 v 2 h 2 v -2 z"></path></svg>',
5722
+ "exif-shutter-speed": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 8,0 C 3.5876443,0 -2.9415707e-8,3.5876443 0,8 c 2.3532563e-7,4.412356 3.5876445,8 8,8 4.412356,0 8,-3.587644 8,-8 C 16,3.5876443 12.412356,0 8,0 Z m 0,1 c 3.871916,0 7,3.1280844 7,7 0,3.871915 -3.128085,7 -7,7 -3.8719154,0 -6.9999998,-3.128085 -7,-7 -3e-8,-3.8719156 3.1280844,-7 7,-7 z M 11.646484,3.6464844 8.6445312,6.6484375 A 1.5,1.5 0 0 0 8,6.5 1.5,1.5 0 0 0 6.5,8 1.5,1.5 0 0 0 8,9.5 1.5,1.5 0 0 0 9.5,8 1.5,1.5 0 0 0 9.3515625,7.3554688 L 12.353516,4.3535156 Z M 2,7.5 v 1 h 2 v -1 z M 7.5,12 v 2 h 1 V 12 Z M 12,7.5 v 1 h 2 v -1 z M 7.5,2 v 2 h 1 V 2 Z"></path></svg>',
5723
+ "exif-focal-length": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="m 1,4.125 -1,0.25 v 7.25 l 1,0.25 z M 5,1 2,4 v 8 l 3,3 h 6.875 C 12.500003,15 13,14.5 13,13.875 V 2.125 C 13,1.4999986 12.5,1 11.875,1 9.576807,0.99914375 7.1414067,0.96597644 5,1 Z M 5.5,2 H 6 V 14 H 5.5 L 3,11.5 v -7 z M 7,2 h 4.75 C 11.875,2 12,2.1249997 12,2.25 v 11.5 c 0,0.125 -0.125,0.250622 -0.25,0.25 H 7 Z m 7,0 c 1,2.2 1.5,4.35 1.5,6 0,1.65 -0.5,3.8 -1.5,6"></path></svg>',
5724
+ "exif-iso": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 7.5,0 V 1.6015625 C 6.0969201,1.7146076 4.8392502,2.256185 3.828125,3.1210938 L 2.6035156,1.8964844 1.8964844,2.6035156 3.1210938,3.828125 C 2.256185,4.8392502 1.7146076,6.0969201 1.6015625,7.5 H 0 v 1 h 1.6015625 c 0.1130451,1.4030799 0.6546225,2.66075 1.5195313,3.671875 l -1.2246094,1.224609 0.7070312,0.707032 1.2246094,-1.22461 C 4.8392502,13.743815 6.0969201,14.285392 7.5,14.398438 V 16 h 1 v -1.601562 c 1.4030799,-0.113046 2.66075,-0.654623 3.671875,-1.519532 l 1.224609,1.22461 0.707032,-0.707032 -1.22461,-1.224609 C 13.743815,11.16075 14.285392,9.9030799 14.398438,8.5 H 16 v -1 H 14.398438 C 14.285392,6.0969201 13.743815,4.8392502 12.878906,3.828125 L 14.103516,2.6035156 13.396484,1.8964844 12.171875,3.1210938 C 11.16075,2.256185 9.9030799,1.7146076 8.5,1.6015625 V 0 Z M 8,2.5 c 3.043488,0 5.5,2.4565116 5.5,5.5 0,3.043488 -2.456512,5.5 -5.5,5.5 C 4.9565116,13.5 2.5,11.043488 2.5,8 2.5,4.9565116 4.9565116,2.5 8,2.5 Z"></path></svg>',
5725
+ "exif-orientation": '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 1.25,0 C 0.625,0 0,0.625 0,1.25 V 5 H 1 V 3 h 8 v 2 h 1 V 1.25 C 10,0.625 9.375,0 8.75,0 Z m 0,1 h 7.5 C 8.875,1 9,1.125 9,1.25 V 2 H 1 V 1.25 C 1,1.125 1.125,1 1.25,1 Z m 0,5 C 0.625,6 0,6.625 0,7.25 v 7.5 C 0,15.375 0.625,16 1.25,16 h 13.5 C 15.375,16 16,15.375 16,14.75 V 7.25 C 16,6.625 15.375,6 14.75,6 Z m 0,1 H 2 v 3 H 1 V 7.25 C 1,7.125 1.125,7 1.25,7 Z M 3,7 h 10 v 8 H 3 Z m 11,0 h 0.75 C 14.875,7 15,7.125 15,7.25 v 7.5 C 15,14.875 14.875,15 14.75,15 H 14 Z M 1,12 h 1 v 3 H 1.25 C 1.125,15 1,14.875 1,14.75 Z"></path></svg>'
5726
+ }
5727
+ };
5728
+ },
5729
+ register: function(setName, icons){
5730
+ if (_is.empty(setName) || _is.empty(icons) || !_is.string(setName) || !_is.hash(icons)) return false;
5731
+ this.registered[setName] = _obj.extend({}, this.registered.default, icons);
5732
+ return true;
5733
+ },
5734
+ get: function(name, setNameOrObject){
5735
+ var self = this, setName = "default",
5736
+ icons = _obj.extend({}, self.registered.default);
5737
+
5738
+ if (_is.string(setNameOrObject) && setNameOrObject !== "default"){
5739
+ setName = setNameOrObject;
5740
+ icons = _obj.extend(icons, self.registered[setNameOrObject]);
5741
+ } else if (_is.hash(setNameOrObject)){
5742
+ setName = "custom";
5743
+ icons = _obj.extend(icons, setNameOrObject);
5744
+ }
5745
+
5746
+ var icon = _is.string(name) && icons.hasOwnProperty(name) ? icons[name].replace(/\[ICON_CLASS]/g, self.className + "-" + name) : null,
5747
+ classNames = [false, name, setName].map(function(val){
5748
+ return val === false ? self.className : self.className + "-" + val;
5749
+ }).join(" ");
5750
+
5751
+ return $(icon).addClass(classNames);
5752
+ }
5753
+ });
5754
+
5755
+ /**
5756
+ * @summary Icon manager for FooGallery.
5757
+ * @memberof FooGallery
5758
+ * @name icons
5759
+ * @type {FooGallery.Icons}
5760
+ */
5761
+ _.icons = new _.Icons();
5762
+
5763
+ })(
5764
+ FooGallery.$,
5765
+ FooGallery,
5766
+ FooGallery.utils,
5767
+ FooGallery.utils.is,
5768
+ FooGallery.utils.obj
5769
+ );
5770
  (function($, _, _utils, _is, _obj) {
5771
 
5772
  var DATA_NAME = "__FooGallerySwipe__",
6086
  FooGallery.utils.is,
6087
  FooGallery.utils.obj
6088
  );
6089
+ (function($, _, _utils, _is, _fn){
6090
+
6091
+ /**
6092
+ * @summary A factory for classes allowing them to be registered and created using a friendly name.
6093
+ * @memberof FooGallery.
6094
+ * @class Factory
6095
+ * @description This class allows other classes to register themselves for use at a later time. Depending on how you intend to use the registered classes you can also specify a load and execution order through the `priority` parameter of the {@link FooGallery.utils.Factory#register|register} method.
6096
+ * @augments FooGallery.utils.Class
6097
+ * @borrows FooGallery.utils.Class.extend as extend
6098
+ * @borrows FooGallery.utils.Class.override as override
6099
+ */
6100
+ _.Factory = _utils.Class.extend(/** @lends FooGallery.Factory.prototype */{
6101
+ /**
6102
+ * @ignore
6103
+ * @constructs
6104
+ **/
6105
+ construct: function(){
6106
+ /**
6107
+ * @summary An object containing all the required info to create a new instance of a registered class.
6108
+ * @typedef {Object} FooGallery.Factory~RegisteredClass
6109
+ * @property {string} name - The friendly name of the registered class.
6110
+ * @property {function} klass - The constructor for the registered class.
6111
+ * @property {number} priority - The priority for the registered class.
6112
+ */
6113
+
6114
+ /**
6115
+ * @summary An object containing all registered classes.
6116
+ * @memberof FooGallery.Factory#
6117
+ * @name registered
6118
+ * @type {Object.<string, FooGallery.Factory~RegisteredClass>}
6119
+ * @readonly
6120
+ * @example {@caption The following shows the structure of this object. The `<name>` placeholders would be the name the class was registered with.}
6121
+ * {
6122
+ * "<name>": {
6123
+ * "name": <string>,
6124
+ * "klass": <function>,
6125
+ * "priority": <number>
6126
+ * },
6127
+ * "<name>": {
6128
+ * "name": <string>,
6129
+ * "klass": <function>,
6130
+ * "priority": <number>
6131
+ * },
6132
+ * ...
6133
+ * }
6134
+ */
6135
+ this.registered = {};
6136
+ },
6137
+ /**
6138
+ * @summary Checks if the factory contains a class registered using the supplied `name`.
6139
+ * @memberof FooGallery.Factory#
6140
+ * @function contains
6141
+ * @param {string} name - The name of the class to check.
6142
+ * @returns {boolean}
6143
+ * @example {@run true}
6144
+ * // create a new instance of the factory, this is usually exposed by the class that will be using the factory.
6145
+ * var factory = new FooGallery.Factory();
6146
+ *
6147
+ * // create a class to register
6148
+ * function Test(){}
6149
+ *
6150
+ * // register the class with the factory with the default priority
6151
+ * factory.register( "test", Test );
6152
+ *
6153
+ * // test if the class was registered
6154
+ * console.log( factory.contains( "test" ) ); // => true
6155
+ */
6156
+ contains: function(name){
6157
+ return !_is.undef(this.registered[name]);
6158
+ },
6159
+ /**
6160
+ * @summary Create a new instance of a class registered with the supplied `name` and arguments.
6161
+ * @memberof FooGallery.Factory#
6162
+ * @function make
6163
+ * @param {string} name - The name of the class to create.
6164
+ * @param {*} [arg1] - The first argument to supply to the new instance.
6165
+ * @param {...*} [argN] - Any number of additional arguments to supply to the new instance.
6166
+ * @returns {Object}
6167
+ * @example {@caption The following shows how to create a new instance of a registered class.}{@run true}
6168
+ * // create a new instance of the factory, this is usually done by the class that will be using it.
6169
+ * var factory = new FooGallery.Factory();
6170
+ *
6171
+ * // create a Logger class to register, this would usually be in another file
6172
+ * var Logger = FooGallery.Class.extend({
6173
+ * write: function( message ){
6174
+ * console.log( "Logger#write: " + message );
6175
+ * }
6176
+ * });
6177
+ *
6178
+ * factory.register( "logger", Logger );
6179
+ *
6180
+ * // create a new instances of the class registered as "logger"
6181
+ * var logger = factory.make( "logger" );
6182
+ * logger.write( "My message" ); // => "Logger#write: My message"
6183
+ */
6184
+ make: function(name, arg1, argN){
6185
+ var self = this, args = _fn.arg2arr(arguments), reg;
6186
+ name = args.shift();
6187
+ reg = self.registered[name];
6188
+ if (_is.hash(reg) && _is.fn(reg.klass)){
6189
+ return _fn.apply(reg.klass, args);
6190
+ }
6191
+ return null;
6192
+ },
6193
+ /**
6194
+ * @summary Gets an array of all registered names.
6195
+ * @memberof FooGallery.Factory#
6196
+ * @function names
6197
+ * @param {boolean} [prioritize=false] - Whether or not to order the names by the priority they were registered with.
6198
+ * @returns {Array.<string>}
6199
+ * @example {@run true}
6200
+ * // create a new instance of the factory, this is usually exposed by the class that will be using the factory.
6201
+ * var factory = new FooGallery.Factory();
6202
+ *
6203
+ * // create some classes to register
6204
+ * function Test1(){}
6205
+ * function Test2(){}
6206
+ *
6207
+ * // register the classes with the factory with the default priority
6208
+ * factory.register( "test-1", Test1 );
6209
+ * factory.register( "test-2", Test2, 1 );
6210
+ *
6211
+ * // log all registered names
6212
+ * console.log( factory.names() ); // => ["test-1","test-2"]
6213
+ * console.log( factory.names( true ) ); // => ["test-2","test-1"] ~ "test-2" appears before "test-1" as it was registered with a higher priority
6214
+ */
6215
+ names: function( prioritize ){
6216
+ prioritize = _is.boolean(prioritize) ? prioritize : false;
6217
+ var names = [], name;
6218
+ if (prioritize){
6219
+ var reg = [];
6220
+ for (name in this.registered){
6221
+ if (!this.registered.hasOwnProperty(name)) continue;
6222
+ reg.push(this.registered[name]);
6223
+ }
6224
+ reg.sort(function(a, b){ return b.priority - a.priority; });
6225
+ $.each(reg, function(i, r){
6226
+ names.push(r.name);
6227
+ });
6228
+ } else {
6229
+ for (name in this.registered){
6230
+ if (!this.registered.hasOwnProperty(name)) continue;
6231
+ names.push(name);
6232
+ }
6233
+ }
6234
+ return names;
6235
+ },
6236
+ /**
6237
+ * @summary Registers a `klass` constructor with the factory using the given `name`.
6238
+ * @memberof FooGallery.Factory#
6239
+ * @function register
6240
+ * @param {string} name - The friendly name of the class.
6241
+ * @param {function} klass - The class constructor to register.
6242
+ * @param {number} [priority=0] - This determines the index for the class when using the {@link FooGallery.Factory#names|names} method, a higher value equals a lower index.
6243
+ * @returns {boolean} `true` if the `klass` was successfully registered.
6244
+ * @description Once a class is registered you can use either the {@link FooGallery.Factory#make|make} method to create new instances.
6245
+ * @example {@run true}
6246
+ * // create a new instance of the factory, this is usually exposed by the class that will be using the factory.
6247
+ * var factory = new FooGallery.Factory();
6248
+ *
6249
+ * // create a class to register
6250
+ * function Test(){}
6251
+ *
6252
+ * // register the class with the factory with the default priority
6253
+ * var succeeded = factory.register( "test", Test );
6254
+ *
6255
+ * console.log( succeeded ); // => true
6256
+ * console.log( factory.registered.hasOwnProperty( "test" ) ); // => true
6257
+ * console.log( factory.registered[ "test" ].name === "test" ); // => true
6258
+ * console.log( factory.registered[ "test" ].klass === Test ); // => true
6259
+ * console.log( factory.registered[ "test" ].priority === 0 ); // => true
6260
+ */
6261
+ register: function(name, klass, priority){
6262
+ if (!_is.string(name) || _is.empty(name) || !_is.fn(klass)) return false;
6263
+ priority = _is.number(priority) ? priority : 0;
6264
+ var current = this.registered[name];
6265
+ this.registered[name] = {
6266
+ name: name,
6267
+ klass: klass,
6268
+ priority: !_is.undef(current) ? current.priority : priority
6269
+ };
6270
+ return true;
6271
+ },
6272
+ load: function(){
6273
+ var self = this, result = [], reg = [], name;
6274
+ for (name in self.registered){
6275
+ if (!self.registered.hasOwnProperty(name)) continue;
6276
+ reg.push(self.registered[name]);
6277
+ }
6278
+ reg.sort(function(a, b){ return b.priority - a.priority; });
6279
+ $.each(reg, function(i, r){
6280
+ result.push(self.make(r.name));
6281
+ });
6282
+ return result;
6283
+ }
6284
+ });
6285
+
6286
+ })(
6287
+ // dependencies
6288
+ FooGallery.$,
6289
+ FooGallery,
6290
+ FooGallery.utils,
6291
+ FooGallery.utils.is,
6292
+ FooGallery.utils.fn
6293
+ );
6294
  (function ($, _, _utils, _is, _fn, _obj) {
6295
 
6296
+ _.TemplateFactory = _.Factory.extend(/** @lends FooGallery.TemplateFactory */{
6297
  /**
6298
  * @summary A factory for galleries allowing them to be easily registered and created.
6299
  * @memberof FooGallery
6300
  * @constructs TemplateFactory
6301
  * @description The plugin makes use of an instance of this class exposed as {@link FooGallery.template}.
6302
+ * @augments FooGallery.Factory
6303
  * @borrows FooGallery.utils.Class.extend as extend
6304
  * @borrows FooGallery.utils.Class.override as override
6305
  */
6356
  * @memberof FooGallery.TemplateFactory#
6357
  * @function make
6358
  * @param {(object|FooGallery~Options)} [options] - The options for the template. If not supplied this will fall back to using the {@link FooGallery.defaults|defaults}.
6359
+ * @param {(jQuery|HTMLElement|string)} [element] - The jQuery object, HTMLElement or selector of the template element to create. If not supplied the {@link FooGallery~Options#type|type} options' value is used.
6360
+ * @returns {FooGallery.Template}
6361
+ */
6362
+ make: function (options, element) {
6363
+ element = _is.jq(element) ? element : $(element);
6364
+ options = _obj.extend({}, options, element.data("foogallery"));
6365
+ var self = this, type = self.type(options, element);
6366
+ if (!self.contains(type)) return null;
6367
+ options = self.options(type, options);
6368
+ return self._super(type, options, element);
6369
+ },
6370
+ type: function (options, element) {
6371
+ element = _is.jq(element) ? element : $(element);
6372
+ var self = this, type = _is.hash(options) && _is.hash(options) && _is.string(options.type) && self.contains(options.type) ? options.type : null;
6373
+ if (type === null && element.length > 0) {
6374
+ var reg = self.registered, names = self.names(true);
6375
+ for (var i = 0, l = names.length; i < l; i++) {
6376
+ if (!reg.hasOwnProperty(names[i]) || names[i] === "core") continue;
6377
+ var name = names[i], cls = reg[name].cls;
6378
+ if (!_is.string(cls.container)) continue;
6379
+ var selector = _utils.selectify(cls.container);
6380
+ if (element.is(selector)) {
6381
+ type = names[i];
6382
+ break;
6383
+ }
6384
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6385
  }
6386
+ return type;
6387
  },
6388
+ configure: function (name, options, classes, il8n) {
6389
  var self = this;
6390
+ if (self.contains(name)) {
6391
  var reg = self.registered;
6392
  _obj.extend(reg[name].opt, options);
6393
  _obj.extend(reg[name].cls, classes);
6394
  _obj.extend(reg[name].il8n, il8n);
6395
  }
6396
  },
6397
+ options: function (name, options) {
6398
+ options = _obj.extend({type: name}, options);
6399
+ var self = this, reg = self.registered,
6400
+ def = reg["core"].opt,
6401
+ cls = reg["core"].cls,
6402
+ il8n = reg["core"].il8n;
6403
+
6404
+ if (!_is.hash(options.cls)) options.cls = {};
6405
+ if (!_is.hash(options.il8n)) options.il8n = {};
6406
+ if (!_is.undef(_.filtering)) options = _.filtering.merge(options);
6407
+ if (!_is.undef(_.paging)) options = _.paging.merge(options);
6408
+
6409
+ if (name !== "core" && self.contains(name)) {
6410
+ options = _obj.extend({}, def, reg[name].opt, options);
6411
+ options.cls = _obj.extend({}, cls, reg[name].cls, options.cls);
6412
+ options.il8n = _obj.extend({}, il8n, reg[name].il8n, options.il8n);
6413
+ } else {
6414
+ options = _obj.extend({}, def, options);
6415
+ options.cls = _obj.extend({}, cls, options.cls);
6416
+ options.il8n = _obj.extend({}, il8n, options.il8n);
 
 
 
 
 
6417
  }
6418
+ return options;
6419
  }
6420
  });
6421
 
6422
  /**
6423
+ * @summary The factory used to register and create the various template types of FooGallery.
6424
  * @memberof FooGallery
6425
+ * @name template
6426
+ * @type {FooGallery.TemplateFactory}
6427
  */
6428
+ _.template = new _.TemplateFactory();
6429
 
6430
  })(
6431
+ FooGallery.$,
6432
  FooGallery,
6433
  FooGallery.utils,
6434
  FooGallery.utils.is,
6467
  * @type {jQuery}
6468
  */
6469
  self.$el = _is.jq(element) ? element : $(element);
6470
+ /**
6471
+ * @summary The element for the template container.
6472
+ * @memberof FooGallery.Template#
6473
+ * @name el
6474
+ * @type {?Element}
6475
+ */
6476
+ self.el = self.$el.get(0) || null;
6477
  /**
6478
  * @summary The jQuery object for the template containers scroll parent.
6479
  * @memberof FooGallery.Template#
6559
  * @private
6560
  */
6561
  self._initialize = null;
6562
+
6563
  self._layoutTimeout = null;
6564
+ /**
6565
+ * @memberof FooGallery.Template#
6566
+ * @name _layoutWidths
6567
+ * @type {Number[]}
6568
+ * @private
6569
+ */
6570
  self._layoutWidths = [];
6571
+ /**
6572
+ * @memberof FooGallery.Template#
6573
+ * @name lastWidth
6574
+ * @type {Number}
6575
+ */
6576
+ self.lastWidth = 0;
6577
  self.initializing = false;
6578
  self.initialized = false;
6579
  self.destroying = false;
6584
  create: false,
6585
  children: false
6586
  };
6587
+ self.robserver = new ResizeObserver(_fn.throttle(function(entries) {
6588
+ if (!self.destroying && !self.destroyed && entries.length === 1 && entries[0].target === self.el){
6589
+ var size = _utils.getResizeObserverSize(entries[0]);
6590
+ self.layout(size.width);
6591
+ }
6592
+ }, 50));
6593
  },
6594
 
6595
  // ################
6606
  * @fires FooGallery.Template~"pre-init.foogallery"
6607
  * @fires FooGallery.Template~"init.foogallery"
6608
  * @fires FooGallery.Template~"post-init.foogallery"
 
6609
  * @fires FooGallery.Template~"ready.foogallery"
6610
  */
6611
  initialize: function (parent) {
6615
  if (self.preInit(parent)){
6616
  self.init().then(function(){
6617
  if (self.postInit()){
6618
+ self.ready();
6619
+ def.resolve(self);
 
 
6620
  } else {
6621
  def.reject("post-init failed");
6622
  }
6626
  }
6627
  }).fail(function (err) {
6628
  console.log("initialize failed", self, err);
6629
+ return self.destroy();
6630
  }).promise();
6631
  },
6632
  /**
6648
  }
6649
  if (self.$el.length === 0) {
6650
  self.$el = self.create();
6651
+ self.el = self.$el.get(0);
6652
  self._undo.create = true;
6653
  }
6654
  if (parent.length > 0) {
6665
 
6666
  // at this point we have our container element free of pre-existing instances so let's bind any event listeners supplied by the .on option
6667
  if (!_is.empty(self.opt.on)) {
6668
+ self.on(self.opt.on);
6669
  }
6670
  self._undo.classes = self.$el.attr("class");
6671
  self._undo.style = self.$el.attr("style");
6678
  if (selector != null && !self.$el.is(selector)) {
6679
  self.$el.addClass(self.opt.classes);
6680
  }
 
6681
 
6682
  // if the container currently has no children make them
6683
  if (self.$el.children().not(self.sel.item.elem).length === 0) {
6712
  * }
6713
  * });
6714
  */
6715
+ return !self.trigger("pre-init").isDefaultPrevented();
6716
  },
6717
  /**
6718
  * @summary Occurs as the template is initialized.
6764
  * }
6765
  * });
6766
  */
6767
+ var e = self.trigger("init");
6768
+ if (e.isDefaultPrevented()) return _fn.reject("init default prevented");
6769
  return self.items.fetch();
6770
  },
6771
  /**
6819
  * }
6820
  * });
6821
  */
6822
+ var e = self.trigger("post-init");
6823
  if (e.isDefaultPrevented()) return false;
6824
  self.state.init();
6825
+ if (self.pages) self.pages.init();
 
 
6826
  $(window).on("popstate" + self.namespace, {self: self}, self.onWindowPopState);
6827
+ self.robserver.observe(self.el);
6828
  return true;
6829
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6830
  /**
6831
  * @summary Occurs once the template is ready.
6832
  * @memberof FooGallery.Template#
6839
  if (self.destroying) return false;
6840
  self.initializing = false;
6841
  self.initialized = true;
 
 
6842
  /**
6843
  * @summary Raised after the template is fully initialized and is ready to be interacted with.
6844
  * @event FooGallery.Template~"ready.foogallery"
6855
  * }
6856
  * });
6857
  */
6858
+ self.trigger("ready");
6859
  return true;
6860
  },
6861
  /**
6934
  * }
6935
  * });
6936
  */
6937
+ self.trigger("destroy");
6938
  self.robserver.disconnect();
 
 
6939
  $(window).off(self.namespace);
6940
  self.state.destroy(preserveState);
6941
  if (self.filter) self.filter.destroy();
6959
  * }
6960
  * });
6961
  */
6962
+ self.trigger("destroyed");
6963
  self.$el.removeData(_.DATA_TEMPLATE);
6964
 
6965
  if (_is.empty(self._undo.classes)) self.$el.removeAttr("class");
7004
  return this.pages ? this.pages.available() : this.items.available();
7005
  },
7006
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7007
  // #############
7008
  // ## Utility ##
7009
  // #############
7010
 
7011
  /**
 
7012
  * @memberof FooGallery.Template#
7013
+ * @function layout
 
 
 
 
 
 
 
 
 
 
7014
  */
7015
+ layout: function (width) {
7016
+ var self = this;
7017
+ if (self._initialize === null) return;
7018
+ if (!_is.number(width)){
7019
+ var rect = self.el.getBoundingClientRect();
7020
+ width = rect.width;
7021
+ }
7022
+ if (width === 0 || self._checkWidth(width)) return;
7023
+
7024
+ self.lastWidth = width;
7025
+
 
 
 
 
 
 
 
 
 
 
7026
  /**
7027
  * @summary Raised when the templates' {@link FooGallery.Template#layout|layout} method is called.
7028
  * @event FooGallery.Template~"layout.foogallery"
7039
  * }
7040
  * });
7041
  */
7042
+ self.trigger("layout", [width]);
7043
  },
7044
  /**
7045
  * @summary This method was added to prevent an infinite loop in the ResizeObserver.
7046
+ * @memberof FooGallery.Template#
7047
+ * @function _checkWidth
7048
  * @description When the viewport has no scrollbar by default and is then resized down until the gallery layout requires a scrollbar
7049
  * to show. There could be an infinite loop as follows:
7050
  * 1. No scrollbar shown, layout occurs, scrollbar is then required.
7067
  return exists;
7068
  },
7069
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7070
  /**
7071
  * @summary Gets a specific type of CSS class from the template.
7072
  * @memberof FooGallery.Template#
7099
  var self = e.data.self, state = e.originalEvent.state;
7100
  if (!_is.empty(state) && state.id === self.id) {
7101
  self.state.set(state);
 
7102
  }
7103
  }
7104
  });
7109
  classes: "",
7110
  on: {},
7111
  lazy: true,
 
7112
  items: [],
 
7113
  scrollParent: null,
7114
  delay: 0,
7115
  throttle: 50,
7116
+ shortpixel: false,
7117
  srcset: "data-srcset-fg",
7118
  src: "data-src-fg",
7119
  template: {},
7122
  loadingIcon: /(?:\s|^)(fg-loading-(?:default|bars|dots|partial|pulse|trail))(?:\s|$)/,
7123
  hoverIcon: /(?:\s|^)(fg-hover-(?:zoom|zoom2|zoom3|plus|circle-plus|eye|external|tint))(?:\s|$)/,
7124
  videoIcon: /(?:\s|^)(fg-video-(?:default|1|2|3|4))(?:\s|$)/,
7125
+ border: /(?:\s|^)(fg-border-(?:thin|medium|thick))(?:\s|$)/,
7126
  hoverColor: /(?:\s|^)(fg-hover-(?:colorize|grayscale))(?:\s|$)/,
7127
  hoverScale: /(?:\s|^)(fg-hover-scale)(?:\s|$)/,
7128
  stickyVideoIcon: /(?:\s|^)(fg-video-sticky)(?:\s|$)/,
7141
  * @property {string} [classes=""] - A space delimited string of any additional CSS classes to append to the container element of the template.
7142
  * @property {object} [on={}] - An object containing any template events to bind to.
7143
  * @property {boolean} [lazy=true] - Whether or not to enable lazy loading of images.
 
7144
  * @property {(FooGallery.Item~Options[]|FooGallery.Item[]| string)} [items=[]] - An array of items to load when required. A url can be provided and the items will be fetched using an ajax call, the response should be a properly formatted JSON array of {@link FooGallery.Item~Options|item} object.
 
7145
  * @property {string} [scrollParent=null] - The selector used to bind to the scroll parent for the gallery. If not supplied the template will attempt to find the element itself.
7146
  * @property {number} [delay=0] - The number of milliseconds to delay the initialization of a template.
7147
  * @property {number} [throttle=50] - The number of milliseconds to wait once scrolling has stopped before performing any work.
 
7148
  * @property {string} [src="data-src-fg"] - The name of the attribute to retrieve an images src url from.
7149
  * @property {string} [srcset="data-srcset-fg"] - The name of the attribute to retrieve an images srcset url from.
7150
  * @property {object} [template={}] - An object containing any additional custom options for the template.
7186
  );
7187
  (function(_, _utils, _is){
7188
 
7189
+ _.Component = _utils.EventClass.extend(/** @lend FooGallery.Component */{
7190
  /**
7191
  * @summary The base class for all child components of a {@link FooGallery.Template|template}.
7192
+ * @constructs
 
7193
  * @param {FooGallery.Template} template - The template creating the component.
7194
+ * @augments FooGallery.utils.EventClass
7195
  * @borrows FooGallery.utils.Class.extend as extend
7196
  * @borrows FooGallery.utils.Class.override as override
7197
  */
7198
  construct: function(template){
7199
+ this._super();
7200
  /**
7201
  * @summary The template that created this component.
7202
  * @memberof FooGallery.Component#
7212
  */
7213
  destroy: function(){
7214
  this.tmpl = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7215
  this._super();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7216
  }
7217
  });
7218
 
7220
  * @summary A factory for registering and creating basic gallery components.
7221
  * @memberof FooGallery
7222
  * @name components
7223
+ * @type {FooGallery.Factory}
7224
  */
7225
+ _.components = new _.Factory();
7226
 
7227
  })(
7228
  FooGallery,
7526
  if (_is.hash(state)){
7527
  var obj = _obj.extend({ filter: [], page: 1, item: null }, state);
7528
  tmpl.items.reset();
7529
+ var e = tmpl.trigger("before-state", [obj]);
7530
  if (!e.isDefaultPrevented()){
7531
  if (!!tmpl.filter){
7532
  tmpl.filter.setState(obj);
7534
  if (!!tmpl.pages){
7535
  tmpl.pages.setState(obj);
7536
  } else {
7537
+ var available = tmpl.items.available();
7538
+ if (!tmpl.items.isAll(available)){
7539
+ var notAvailable = tmpl.items.not(available);
7540
+ tmpl.items.detach(notAvailable);
7541
+ }
7542
+ tmpl.items.create(available, true);
7543
  }
7544
+ if (obj.item instanceof _.Item){
7545
  if (self.opt.scrollTo) {
7546
  obj.item.scrollTo();
7547
  }
7551
  }
7552
  }
7553
  self.current = obj;
7554
+ tmpl.trigger("after-state", [obj]);
7555
  }
7556
  }
7557
  },
7604
  );
7605
  (function ($, _, _utils, _is, _fn, _obj) {
7606
 
7607
+ _.Items = _.Component.extend(/** @lends FooGallery.Items.prototype */{
7608
  /**
7609
  * @summary This class controls everything related to items and serves as the base class for the various paging types.
7610
  * @memberof FooGallery
7618
  var self = this;
7619
  self.ALLOW_CREATE = true;
7620
  self.ALLOW_APPEND = true;
 
7621
  /**
7622
  * @ignore
7623
  * @memberof FooGallery.Items#
7624
  * @function _super
7625
  */
7626
  self._super(template);
7627
+ self._typeRegex = /(?:^|\s)?fg-type-(.*?)(?:$|\s)/;
7628
  self._fetched = null;
7629
+ self._all = [];
7630
  self._available = [];
7631
+ self._unavailable = [];
7632
+ self._observed = new Map();
7633
+
7634
  // add the .all caption selector
7635
  var cls = self.tmpl.cls.item.caption;
7636
  self.tmpl.sel.item.caption.all = _utils.selectify([cls.elem, cls.inner, cls.title, cls.description]);
7637
+
7638
+ self.iobserver = new IntersectionObserver(function(entries){
7639
+ if (!self.tmpl.destroying && !self.tmpl.destroyed){
7640
+ entries.forEach(function(entry){
7641
+ if (entry.isIntersecting){
7642
+ var item = self._observed.get(entry.target);
7643
+ if (item instanceof _.Item){
7644
+ item.load();
7645
+ }
7646
+ }
7647
+ });
7648
+ }
7649
+ });
7650
  },
7651
  fromHash: function(hash){
7652
+ return this.find(this._all, function(item){ return item.id === hash; });
7653
  },
7654
  toHash: function(value){
7655
  return value instanceof _.Item ? value.id : null;
7656
  },
7657
  destroy: function () {
7658
  var self = this, items = self.all(), destroyed = [];
7659
+ self.iobserver.disconnect();
7660
  if (items.length > 0) {
7661
  /**
7662
  * @summary Raised before the template destroys its' items.
7674
  * }
7675
  * });
7676
  */
7677
+ self.tmpl.trigger("destroy-items", [items]);
7678
  destroyed = $.map(items, function (item) {
7679
  return item.destroy() ? item : null;
7680
  });
7694
  * }
7695
  * });
7696
  */
7697
+ if (destroyed.length > 0) self.tmpl.trigger("destroyed-items", [destroyed]);
7698
  // should we handle a case where the destroyed.length != items.length??
7699
  }
 
7700
  self._fetched = null;
7701
+ self._all = [];
7702
  self._available = [];
7703
+ self._unavailable = [];
7704
+ self._observed.clear();
7705
  self._super();
7706
  },
7707
  fetch: function (refresh) {
7708
  var self = this;
7709
  if (!refresh && _is.promise(self._fetched)) return self._fetched;
7710
+ var itemsId = self.tmpl.id + "_items",
7711
+ selectors = self.tmpl.sel,
7712
+ option = self.tmpl.opt.items,
7713
+ def = $.Deferred();
7714
 
7715
+ var items = self.make(self.tmpl.$el.find(selectors.item.elem));
7716
 
7717
  if (!_is.empty(option)) {
7718
  if (_is.array(option)) {
7730
  def.resolve(items);
7731
  }
7732
  } else {
7733
+ if (_is.array(window[itemsId])) {
7734
+ items.push.apply(items, self.make(window[itemsId]));
7735
+ }
7736
  def.resolve(items);
7737
  }
7738
  def.then(function (items) {
7747
  });
7748
  },
7749
  all: function () {
7750
+ return this._all.slice();
7751
  },
7752
  count: function (all) {
7753
  return all ? this.all().length : this.available().length;
7758
  }
7759
  return this._available.slice();
7760
  },
7761
+ unavailable: function (where) {
7762
+ if (_is.fn(where)){
7763
+ return this._unavailable.filter(where, this);
7764
+ }
7765
+ return this._unavailable.slice();
7766
  },
7767
  setAll: function (items) {
7768
+ this._all = _is.array(items) ? items : [];
7769
+ this._all.forEach(function(item, i){
7770
+ item.index = i;
7771
+ if (_is.empty(item.id)) item.id = (i + 1) + "";
7772
+ });
7773
  this._available = this.all();
7774
+ this._unavailable = [];
7775
  },
7776
  setAvailable: function (items) {
7777
+ var self = this;
7778
+ self._available = _is.array(items) ? items : [];
7779
+ if (self._all.length !== self._available.length){
7780
+ self._unavailable = self._all.filter(function(item){
7781
+ return self._available.indexOf(item) === -1;
7782
+ });
7783
+ } else {
7784
+ self._unavailable = [];
7785
+ }
7786
  },
7787
  reset: function () {
7788
  this.setAvailable(this.all());
7798
  }
7799
  return null;
7800
  },
7801
+ not: function(items){
7802
+ var all = this.all();
7803
+ if (_is.array(items)){
7804
+ return all.filter(function(item){
7805
+ return items.indexOf(item) === -1;
7806
+ });
7807
+ }
7808
+ return all;
7809
+ },
7810
+ isAll: function(items){
7811
+ if (_is.array(items)){
7812
+ return this._all.length === items.length;
7813
+ }
7814
+ return false;
7815
+ },
7816
  first: function(where){
7817
  return this.find(this._available, where);
7818
  },
7849
  }
7850
  return null;
7851
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7852
  /**
7853
  * @summary Filter the supplied `items` and return only those that can be created.
7854
  * @memberof FooGallery.Items#
7940
  * }
7941
  * });
7942
  */
7943
+ var e = self.tmpl.trigger("make-items", [arr]);
7944
  if (!e.isDefaultPrevented()) {
7945
  made = $.map(arr, function (obj) {
7946
  var type = self.type(obj), opt = _obj.extend(_is.hash(obj) ? obj : {}, {type: type});
7973
  * }
7974
  * });
7975
  */
7976
+ if (made.length > 0) self.tmpl.trigger("made-items", [made]);
7977
 
7978
  /**
7979
  * @summary Raised after the template has parsed any elements into an array of {@link FooGallery.Item|item} objects.
7991
  * }
7992
  * });
7993
  */
7994
+ if (parsed.length > 0) self.tmpl.trigger("parsed-items", [parsed]);
7995
  }
7996
  return made;
7997
  },
7998
  type: function (objOrElement) {
7999
+ var self = this, type;
8000
  if (_is.hash(objOrElement)) {
8001
  type = objOrElement.type;
8002
  } else if (_is.element(objOrElement)) {
8003
+ var match = objOrElement.className.match(self._typeRegex);
8004
+ if (match !== null && match.length === 2){
8005
+ type = match[1];
8006
+ }
8007
+ // var $el = $(objOrElement), item = this.tmpl.sel.item;
8008
+ // type = $el.find(item.anchor).data("type");
8009
  }
8010
  return _is.string(type) && _.components.contains(type) ? type : "image";
8011
  },
8053
  * }
8054
  * });
8055
  */
8056
+ var e = self.tmpl.trigger("create-items", [creatable]);
8057
  if (!e.isDefaultPrevented()) {
8058
  created = $.map(creatable, function (item) {
8059
  return item.create() ? item : null;
8075
  * }
8076
  * });
8077
  */
8078
+ if (created.length > 0) self.tmpl.trigger("created-items", [created]);
8079
  }
8080
  if (_is.boolean(append) ? append : false) return self.append(items);
8081
  return created;
8119
  * }
8120
  * });
8121
  */
8122
+ var e = self.tmpl.trigger("append-items", [appendable]);
8123
  if (!e.isDefaultPrevented()) {
8124
  appended = $.map(appendable, function (item) {
8125
  return item.append() ? item : null;
8141
  * }
8142
  * });
8143
  */
8144
+ if (appended.length > 0) self.tmpl.trigger("appended-items", [appended]);
8145
  }
8146
  return appended;
8147
  },
8184
  * }
8185
  * });
8186
  */
8187
+ var e = self.tmpl.trigger("detach-items", [detachable]);
8188
  if (!e.isDefaultPrevented()) {
8189
  detached = $.map(detachable, function (item) {
8190
  return item.detach() ? item : null;
8204
  * // do something
8205
  * }
8206
  * }
8207
+ * });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8208
  */
8209
+ if (detached.length > 0) self.tmpl.trigger("detached-items", [detached]);
8210
+ }
8211
+ return detached;
8212
+ },
8213
+ observe: function(item){
8214
+ var self = this;
8215
+ if (self.iobserver && item.isCreated && item.isAttached && (!item.isLoading || !item.isLoaded)){
8216
+ self.iobserver.observe(item.el);
8217
+ self._observed.set(item.el, item);
8218
+ }
8219
+ },
8220
+ unobserve: function(item){
8221
+ var self = this;
8222
+ if (self.iobserver) {
8223
+ self.iobserver.unobserve(item.el);
8224
+ self._observed.delete(item.el);
 
 
 
 
 
 
 
 
 
8225
  }
 
8226
  }
8227
  });
8228
 
8324
  * @type {?jQuery}
8325
  */
8326
  self.$el = null;
8327
+ /**
8328
+ * @memberof FooGallery.Item#
8329
+ * @name el
8330
+ * @type {?Element}
8331
+ */
8332
+ self.el = null;
8333
  /**
8334
  * @memberof FooGallery.Item#
8335
  * @name $inner
8366
  * @type {?jQuery}
8367
  */
8368
  self.$caption = null;
 
8369
  /**
8370
  * @memberof FooGallery.Item#
8371
+ * @name $loader
8372
+ * @type {?jQuery}
8373
  */
8374
+ self.$loader = null;
8375
 
8376
  /**
8377
  * @memberof FooGallery.Item#
8404
  * @type {string}
8405
  */
8406
  self.href = self.opt.href;
8407
+ /**
8408
+ * @memberof FooGallery.Item#
8409
+ * @name placeholder
8410
+ * @type {string}
8411
+ */
8412
+ self.placeholder = self.opt.placeholder;
8413
  /**
8414
  * @memberof FooGallery.Item#
8415
  * @name src
8470
  * @type {string[]}
8471
  */
8472
  self.tags = self.opt.tags;
 
 
 
 
 
 
8473
  /**
8474
  * @memberof FooGallery.Item#
8475
  * @name maxCaptionLength
8518
  * @type {boolean}
8519
  */
8520
  self.hasExif = _is.exif(self.exif);
 
 
 
 
 
 
 
 
8521
  /**
8522
  * @summary This property is used to store the promise created when loading an item for the first time.
8523
  * @memberof FooGallery.Item#
8536
  self._undo = {
8537
  classes: "",
8538
  style: "",
 
 
 
8539
  placeholder: false
8540
  };
8541
  },
8589
  * }
8590
  * });
8591
  */
8592
+ var e = self.tmpl.trigger("destroy-item", [self]);
8593
  if (!e.isDefaultPrevented()) {
8594
  self.isDestroyed = self.doDestroyItem();
8595
  }
8610
  * }
8611
  * });
8612
  */
8613
+ self.tmpl.trigger("destroyed-item", [self]);
8614
  // call the original method that simply nulls the tmpl property
8615
  self._super();
8616
  }
8627
  if (self.isParsed) {
8628
  self.$anchor.add(self.$caption).off("click.foogallery");
8629
  self.append();
8630
+
8631
+ self.tmpl.items.unobserve(self);
8632
+
8633
  if (_is.empty(self._undo.classes)) self.$el.removeAttr("class");
8634
  else self.$el.attr("class", self._undo.classes);
8635
 
8636
  if (_is.empty(self._undo.style)) self.$el.removeAttr("style");
8637
  else self.$el.attr("style", self._undo.style);
8638
 
8639
+ if (self._undo.placeholder && self.$image.prop("src") === self.placeholder) {
 
 
 
 
 
 
 
 
 
 
8640
  self.$image.removeAttr("src");
8641
  }
8642
  } else if (self.isCreated) {
8698
  * }
8699
  * });
8700
  */
8701
+ var e = self.tmpl.trigger("parse-item", [self, $el]);
8702
  if (!e.isDefaultPrevented() && (self.isCreated = $el.is(self.sel.elem))) {
8703
  self.isParsed = self.doParseItem($el);
 
8704
  // We don't load the attributes when parsing as they are only ever used to create an item and if you're parsing it's already created.
8705
  }
8706
  if (self.isParsed) {
8707
+ self.tmpl.items.observe(self);
8708
  /**
8709
  * @summary Raised after an item has been parsed from an element.
8710
  * @event FooGallery.Template~"parsed-item.foogallery"
8722
  * }
8723
  * });
8724
  */
8725
+ self.tmpl.trigger("parsed-item", [self]);
8726
  }
8727
  return self.isParsed;
8728
  },
8734
  * @returns {boolean}
8735
  */
8736
  doParseItem: function ($el) {
8737
+ var self = this,
8738
+ cls = self.cls,
8739
+ sel = self.sel,
8740
+ el = $el.get(0);
8741
 
8742
  self._undo.classes = $el.attr("class") || "";
8743
  self._undo.style = $el.attr("style") || "";
8744
 
8745
  self.$el = $el.data(_.DATA_ITEM, self);
8746
+ self.el = el;
8747
+ self.$inner = $(el.querySelector(sel.inner));
8748
+ self.$anchor = $(el.querySelector(sel.anchor)).on("click.foogallery", {self: self}, self.onAnchorClick);
8749
+ self.$image = $(el.querySelector(sel.image));
8750
+ self.$caption = $(el.querySelector(sel.caption.elem)).on("click.foogallery", {self: self}, self.onCaptionClick);
8751
+ self.$overlay = $(el.querySelector(sel.overlay));
8752
+ self.$wrap = $(el.querySelector(sel.wrap));
8753
+ self.$loader = $(el.querySelector(sel.loader));
8754
 
8755
  if ( !self.$el.length || !self.$inner.length || !self.$anchor.length || !self.$image.length ){
8756
  console.error("FooGallery Error: Invalid HTML markup. Check the item markup for additional elements or malformed HTML in the title or description.", self);
8757
  self.isError = true;
8758
+ self.tmpl.trigger("error-item", [self]);
8759
  if (self.$el.length !== 0){
8760
  self.$el.remove();
8761
  }
8762
  return false;
8763
  }
8764
 
8765
+ self.isAttached = el.parentNode !== null;
8766
+ self.isLoading = self.$el.hasClass(cls.loading);
8767
+ self.isLoaded = self.$el.hasClass(cls.loaded);
8768
+ self.isError = self.$el.hasClass(cls.error);
8769
 
8770
+ var data = self.$anchor.data();
8771
  self.id = data.id || self.id;
8772
  self.productId = data.productId || self.productId;
8773
  self.tags = data.tags || self.tags;
8774
  self.href = data.href || self.$anchor.attr('href') || self.href;
8775
+ self.src = self.$image.attr(self.tmpl.opt.src) || self.src;
8776
+ self.srcset = self.$image.attr(self.tmpl.opt.srcset) || self.srcset;
8777
  self.width = parseInt(self.$image.attr("width")) || self.width;
8778
  self.height = parseInt(self.$image.attr("height")) || self.height;
8779
  self.title = self.$image.attr("title") || self.title;
8786
  self.exif = _obj.extend(self.exif, data.exif);
8787
  self.hasExif = true;
8788
  }
 
 
 
8789
  // enforce the max lengths for the caption and description
8790
+ if (self.maxCaptionLength > 0){
8791
+ var title = _str.trimTo(self.caption, self.maxCaptionLength);
8792
+ if (title !== self.caption) {
8793
+ self.$caption.find(sel.caption.title).html(title);
8794
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8795
  }
8796
+ if (self.maxDescriptionLength){
8797
+ var desc = _str.trimTo(self.description, self.maxDescriptionLength);
8798
+ if (desc !== self.description) {
8799
+ self.$caption.find(sel.caption.description).html(desc);
8800
+ }
8801
+ }
8802
+
8803
  // if the image has no src url then set the placeholder
8804
  var img = self.$image.get(0);
8805
+ if (!_is.string(img.src) || img.src.length === 0) {
8806
+ if (!_is.string(self.placeholder) || self.placeholder.length === 0){
8807
+ self.placeholder = self.createPlaceholder(self.width, self.height);
8808
+ }
8809
+ if (self.placeholder.length > 0){
8810
+ img.src = self.placeholder;
8811
+ self._undo.placeholder = true;
8812
+ }
8813
+ }
8814
+ var typeClass = self.getTypeClass();
8815
+ if (!self.$el.hasClass(typeClass)){
8816
+ self.$el.addClass(typeClass);
8817
  }
8818
+ if (self.hasExif && !self.$el.hasClass(cls.exif)){
 
8819
  self.$el.addClass(cls.exif);
8820
  }
8821
+ if (self.isCreated && self.isAttached && !self.isLoading && !self.isLoaded && !self.isError && !self.$el.hasClass(cls.idle)) {
8822
  self.$el.addClass(cls.idle);
8823
  }
8824
+
8825
+ self.doShortPixel();
8826
+
8827
  return true;
8828
  },
8829
  /**
8878
  * }
8879
  * });
8880
  */
8881
+ var e = self.tmpl.trigger("create-item", [self]);
8882
  if (!e.isDefaultPrevented()) {
8883
  self.isCreated = self.doCreateItem();
8884
  }
8899
  * }
8900
  * });
8901
  */
8902
+ self.tmpl.trigger("created-item", [self]);
8903
  }
8904
  }
8905
  return self.isCreated;
8906
  },
8907
+ /**
8908
+ * @memberof FooGallery.Item#
8909
+ * @function _setAttributes
8910
+ * @param element
8911
+ * @param attributes
8912
+ * @private
8913
+ */
8914
+ _setAttributes: function(element, attributes){
8915
+ Object.keys(attributes).forEach(function(key){
8916
+ if (!_is.empty(attributes[key])){
8917
+ element.setAttribute(key, _is.string(attributes[key]) ? attributes[key] : JSON.stringify(attributes[key]));
8918
+ }
8919
+ });
8920
+ },
8921
+ /**
8922
+ * @summary Performs some checks for ShortPixel integration and WebP support.
8923
+ * @memberof FooGallery.Item#
8924
+ * @function doShortPixel
8925
+ */
8926
+ doShortPixel: function(){
8927
+ var self = this;
8928
+ if (self.tmpl.opt.shortpixel && !_.supportsWebP){
8929
+ var regex = /([\/,+])to_webp([\/,+])/i;
8930
+ function spReplacer(match, $1, $2){
8931
+ return $1 === "/" || $2 === "/" ? "/" : $1;
8932
+ }
8933
+ self.href = self.href.replace(regex, spReplacer);
8934
+ self.src = self.src.replace(regex, spReplacer);
8935
+ self.srcset = self.srcset.replace(regex, spReplacer);
8936
+ }
8937
+ },
8938
  /**
8939
  * @summary Performs the actual create logic for the item.
8940
  * @memberof FooGallery.Item#
8942
  * @returns {boolean}
8943
  */
8944
  doCreateItem: function () {
8945
+ var self = this,
8946
+ cls = self.cls,
8947
+ attr = self.attr,
8948
+ exif = self.hasExif ? cls.exif : "";
8949
+
8950
+ self.doShortPixel();
8951
 
8952
+ var elem = document.createElement("div");
8953
+ self._setAttributes(elem, attr.elem);
8954
+ elem.className = [cls.elem, self.getTypeClass(), exif, cls.idle].join(" ");
8955
+
8956
+ var inner = document.createElement("figure");
8957
+ self._setAttributes(inner, attr.inner);
8958
+ inner.className = cls.inner;
8959
 
8960
  var anchorClasses = [cls.anchor];
8961
  if (self.noLightbox){
8964
  if (self.panelHide){
8965
  anchorClasses.push(cls.panelHide);
8966
  }
8967
+
8968
+ var anchor = document.createElement("a");
8969
+ self._setAttributes(anchor, attr.anchor);
8970
+ self._setAttributes(anchor, {
8971
+ "class": anchorClasses.join(" "),
8972
+ "href": self.href,
8973
+ "data-id": self.id,
8974
+ "data-type": self.type,
8975
+ "data-title": self.caption,
8976
+ "data-description": self.description,
8977
+ "data-tags": self.tags,
8978
+ "data-exif": self.exif,
8979
+ "data-product-id": self.productId
8980
+ });
8981
+
8982
+ if (!_is.string(self.placeholder) || self.placeholder.length === 0){
8983
+ self.placeholder = self.createPlaceholder(self.width, self.height);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8984
  }
8985
+
8986
+ var image = document.createElement("img");
8987
+ self._setAttributes(image, attr.image);
8988
+ self._setAttributes(image, {
8989
+ "class": cls.image,
8990
+ "src": self.placeholder,
8991
+ "width": self.width + "",
8992
+ "height": self.height + "",
8993
+ "title": self.title,
8994
+ "alt": self.alt
8995
+ });
8996
+ image.setAttribute(self.tmpl.opt.src, self.src);
8997
+ image.setAttribute(self.tmpl.opt.srcset, self.srcset);
8998
+
8999
+ var overlay = document.createElement("span");
9000
+ overlay.className = cls.overlay;
9001
+
9002
+ var wrap = document.createElement("span");
9003
+ wrap.className = cls.wrap;
9004
+
9005
+ var loader = document.createElement("div");
9006
+ loader.className = cls.loader;
9007
+
9008
+ var caption = document.createElement("figcaption");
9009
+ self._setAttributes(caption, attr.caption.elem);
9010
+ caption.className = cls.caption.elem;
9011
+
9012
+ var captionInner = document.createElement("div");
9013
+ self._setAttributes(captionInner, attr.caption.inner);
9014
+ captionInner.className = cls.caption.inner;
9015
+
9016
+ var captionTitle = null;
9017
+ if (self.showCaptionTitle && _is.string(self.caption) && self.caption.length > 0) {
9018
+ captionTitle = document.createElement("div");
9019
+ self._setAttributes(captionTitle, attr.caption.title);
9020
+ captionTitle.className = cls.caption.title;
9021
+ captionTitle.innerHTML = self.maxCaptionLength > 0 ? _str.trimTo(self.caption, self.maxCaptionLength) : self.caption;
9022
+ }
9023
+ var captionDesc = null;
9024
+ if (self.showCaptionDescription && _is.string(self.description) && self.description.length > 0) {
9025
+ captionDesc = document.createElement("div");
9026
+ self._setAttributes(captionDesc, attr.caption.description);
9027
+ captionDesc.className = cls.caption.description;
9028
+ captionDesc.innerHTML = self.maxDescriptionLength > 0 ? _str.trimTo(self.description, self.maxDescriptionLength) : self.description;
9029
+ }
9030
+
9031
+ if (captionTitle !== null) captionInner.appendChild(captionTitle);
9032
+ if (captionDesc !== null) captionInner.appendChild(captionDesc);
9033
+ caption.appendChild(captionInner);
9034
+
9035
+ wrap.appendChild(image);
9036
+ anchor.appendChild(overlay);
9037
+ anchor.appendChild(wrap);
9038
+ inner.appendChild(anchor);
9039
+ inner.appendChild(caption);
9040
+ elem.appendChild(inner);
9041
+ elem.appendChild(loader);
9042
+
9043
+ self.$el = $(elem).data(_.DATA_ITEM, self);
9044
+ self.el = elem;
9045
+ self.$inner = $(inner);
9046
+ self.$anchor = $(anchor).on("click.foogallery", {self: self}, self.onAnchorClick);
9047
+ self.$overlay = $(overlay);
9048
+ self.$wrap = $(wrap);
9049
+ self.$image = $(image);
9050
+ self.$caption = $(caption).on("click.foogallery", {self: self}, self.onCaptionClick);
9051
+ self.$loader = $(loader);
9052
+
9053
  return true;
9054
  },
9055
  /**
9104
  * }
9105
  * });
9106
  */
9107
+ var e = self.tmpl.trigger("append-item", [self]);
9108
  if (!e.isDefaultPrevented()) {
9109
+ self.tmpl.$el.append(self.$el.removeClass(self.cls.hidden));
 
9110
  self.isAttached = true;
9111
  }
9112
  if (self.isAttached) {
9113
+ self.tmpl.items.observe(self);
9114
  /**
9115
  * @summary Raised after an item has appended its' elements to the template.
9116
  * @event FooGallery.Template~"appended-item.foogallery"
9127
  * }
9128
  * });
9129
  */
9130
+ self.tmpl.trigger("appended-item", [self]);
9131
  }
9132
  }
9133
  return self.isAttached;
9141
  detach: function () {
9142
  var self = this;
9143
  if (self.isCreated && self.isAttached) {
9144
+ self.tmpl.items.unobserve(self);
9145
  /**
9146
  * @summary Raised when an item needs to detach its' elements from the template.
9147
  * @event FooGallery.Template~"detach-item.foogallery"
9183
  * }
9184
  * });
9185
  */
9186
+ var e = self.tmpl.trigger("detach-item", [self]);
9187
  if (!e.isDefaultPrevented()) {
9188
+ self.$el.detach().removeClass(self.cls.hidden);
 
9189
  self.isAttached = false;
9190
  }
9191
  if (!self.isAttached) {
9205
  * }
9206
  * });
9207
  */
9208
+ self.tmpl.trigger("detached-item", [self]);
9209
  }
9210
  }
9211
  return !self.isAttached;
9219
  load: function () {
9220
  var self = this;
9221
  if (_is.promise(self._load)) return self._load;
9222
+ if (!self.isCreated || !self.isAttached) return _fn.reject("not created or attached");
9223
+ var e = self.tmpl.trigger("load-item", [self]);
9224
+ if (e.isDefaultPrevented()) return _fn.reject("default prevented");
9225
  var cls = self.cls, img = self.$image.get(0), placeholder = img.src;
9226
  self.isLoading = true;
9227
+ self.tmpl.items.unobserve(self);
9228
+ self.$el.removeClass(cls.idle).removeClass(cls.hidden).removeClass(cls.loaded).removeClass(cls.error).addClass(cls.loading);
9229
  return self._load = $.Deferred(function (def) {
9230
  img.onload = function () {
9231
  img.onload = img.onerror = null;
9232
  self.isLoading = false;
9233
  self.isLoaded = true;
9234
  self.$el.removeClass(cls.loading).addClass(cls.loaded);
9235
+ self.tmpl.trigger("loaded-item", [self]);
 
9236
  def.resolve(self);
9237
  };
9238
  img.onerror = function () {
9243
  if (_is.string(placeholder)) {
9244
  self.$image.prop("src", placeholder);
9245
  }
9246
+ self.tmpl.trigger("error-item", [self]);
9247
  def.reject(self);
9248
  };
9249
  // set everything in motion by setting the src
9250
+ img.src = self.src;
9251
+ img.srcset = self.srcset;
9252
  if (img.complete){
9253
  img.onload();
9254
  }
9255
  }).promise();
9256
  },
9257
  /**
9258
+ * @summary Create an empty placeholder image using the supplied dimensions.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9259
  * @memberof FooGallery.Item#
9260
+ * @function createPlaceholder
9261
+ * @param {number} width - The width of the placeholder.
9262
+ * @param {number} height - The height of the placeholder.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9263
  * @returns {string}
9264
  */
9265
+ createPlaceholder: function(width, height){
9266
+ if (_is.number(width) && _is.number(height)){
9267
+ return "data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20" + width + "%20" + height + "%22%3E%3C/svg%3E";
9268
+ }
9269
+ return "";
9270
  },
9271
  /**
9272
  * @summary Gets the type specific CSS class for the item.
9275
  * @returns {string}
9276
  */
9277
  getTypeClass: function(){
9278
+ return this.cls.types[this.type] || "";
9279
  },
9280
  /**
9281
  * @summary Scroll the item into the center of the viewport.
9285
  scrollTo: function (align) {
9286
  var self = this;
9287
  if (self.isAttached) {
9288
+ var el = self.$el.get(0);
9289
+ if (!!el.scrollIntoViewIfNeeded){
9290
+ el.scrollIntoViewIfNeeded();
9291
+ } else {
9292
+ el.scrollIntoView(align === "top");
 
 
 
 
 
9293
  }
 
9294
  }
9295
  return self;
9296
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9297
  /**
9298
  * @summary Updates the current state to this item.
9299
  * @memberof FooGallery.Item#
9340
  * @private
9341
  */
9342
  onAnchorClick: function (e) {
9343
+ var self = e.data.self, evt = self.tmpl.trigger("anchor-click-item", [self]);
9344
  if (evt.isDefaultPrevented()) {
9345
  e.preventDefault();
9346
  } else {
9355
  * @private
9356
  */
9357
  onCaptionClick: function (e) {
9358
+ var self = e.data.self, evt = self.tmpl.trigger("caption-click-item", [self]);
9359
  if (!evt.isDefaultPrevented() && self.$anchor.length > 0 && !$(e.target).is("a,:input")) {
9360
  self.$anchor.get(0).click();
9361
  }
9362
  }
9363
  });
9364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9365
  /**
9366
  * @summary A simple object containing an items' default values.
9367
  * @typedef {object} FooGallery.Item~Options
9377
  * @property {?string} [caption=null] - The caption for the image. This can contain HTML content.
9378
  * @property {?string} [description=null] - The description for the image. This can contain HTML content.
9379
  * @property {string[]} [tags=[]] - The `data-tags` attribute for the outer element.
 
9380
  * @property {number} [maxCaptionLength=0] - The max length of the title for the caption.
9381
  * @property {number} [maxDescriptionLength=0] - The max length of the description for the caption.
9382
  * @property {boolean} [showCaptionTitle=true] - Whether or not the caption title should be displayed.
9388
  type: "item",
9389
  id: "",
9390
  href: "",
9391
+ placeholder: "",
9392
  src: "",
9393
  srcset: "",
9394
  width: 0,
9398
  caption: "",
9399
  description: "",
9400
  tags: [],
 
9401
  maxCaptionLength: 0,
9402
  maxDescriptionLength: 0,
9403
  showCaptionTitle: true,
9440
  loading: "fg-loading",
9441
  loaded: "fg-loaded",
9442
  error: "fg-error",
9443
+ hidden: "fg-hidden",
9444
  noLightbox: "fg-no-lightbox",
9445
  panelHide: "fg-panel-hide",
9446
  types: {
9533
  FooGallery.utils,
9534
  FooGallery.utils.is
9535
  );
9536
+ (function(_, _is, _fn, _obj){
9537
+
9538
+ _.PagingFactory = _.Factory.extend(/** @lends FooGallery.PagingFactory */{
9539
+ /**
9540
+ * @summary A factory for paging types allowing them to be easily registered and created.
9541
+ * @memberof FooGallery
9542
+ * @constructs PagingFactory
9543
+ * @description The plugin makes use of an instance of this class exposed as {@link FooGallery.paging}.
9544
+ * @augments FooGallery.Factory
9545
+ * @borrows FooGallery.utils.Class.extend as extend
9546
+ * @borrows FooGallery.utils.Class.override as override
9547
+ */
9548
+ construct: function(){
9549
+ /**
9550
+ * @summary An object containing all registered paging types.
9551
+ * @memberof FooGallery.PagingFactory#
9552
+ * @name registered
9553
+ * @type {Object.<string, Object>}
9554
+ * @readonly
9555
+ * @example {@caption The following shows the structure of this object. The `<name>` placeholders would be the name the class was registered with.}
9556
+ * {
9557
+ * "<name>": {
9558
+ * "name": <string>,
9559
+ * "klass": <function>,
9560
+ * "ctrl": <function>,
9561
+ * "priority": <number>
9562
+ * },
9563
+ * "<name>": {
9564
+ * "name": <string>,
9565
+ * "klass": <function>,
9566
+ * "ctrl": <function>,
9567
+ * "priority": <number>
9568
+ * },
9569
+ * ...
9570
+ * }
9571
+ */
9572
+ this.registered = {};
9573
+ },
9574
+ /**
9575
+ * @summary Registers a paging `type` constructor with the factory using the given `name` and `test` function.
9576
+ * @memberof FooGallery.PagingFactory#
9577
+ * @function register
9578
+ * @param {string} name - The friendly name of the class.
9579
+ * @param {FooGallery.Paging} type - The paging type constructor to register.
9580
+ * @param {FooGallery.PagingControl} [ctrl] - An optional control to register for the paging type.
9581
+ * @param {object} [options={}] - The default options for the paging type.
9582
+ * @param {object} [classes={}] - The CSS classes for the paging type.
9583
+ * @param {object} [il8n={}] - The il8n strings for the paging type.
9584
+ * @param {number} [priority=0] - This determines the index for the class when using either the {@link FooGallery.PagingFactory#load|load} or {@link FooGallery.PagingFactory#names|names} methods, a higher value equals a lower index.
9585
+ * @returns {boolean} `true` if the `klass` was successfully registered.
9586
+ */
9587
+ register: function(name, type, ctrl, options, classes, il8n, priority){
9588
+ var self = this, result = self._super(name, type, priority);
9589
+ if (result){
9590
+ var reg = self.registered;
9591
+ reg[name].ctrl = _is.fn(ctrl) ? ctrl : null;
9592
+ reg[name].opt = _is.hash(options) ? options : {};
9593
+ reg[name].cls = _is.hash(classes) ? classes : {};
9594
+ reg[name].il8n = _is.hash(il8n) ? il8n : {};
9595
+ }
9596
+ return result;
9597
+ },
9598
+ type: function(options){
9599
+ var self = this, opt;
9600
+ return _is.hash(options) && _is.hash(opt = options.paging) && _is.string(opt.type) && self.contains(opt.type) ? opt.type : null;
9601
+ },
9602
+ merge: function(options){
9603
+ options = _obj.extend({}, options);
9604
+ var self = this, type = self.type(options),
9605
+ reg = self.registered,
9606
+ def = reg["default"].opt,
9607
+ def_cls = reg["default"].cls,
9608
+ def_il8n = reg["default"].il8n,
9609
+ opt = _is.hash(options.paging) ? options.paging : {},
9610
+ cls = _is.hash(options.cls) && _is.hash(options.cls.paging) ? _obj.extend({}, options.cls.paging) : {},
9611
+ il8n = _is.hash(options.il8n) && _is.hash(options.il8n.paging) ? _obj.extend({}, options.il8n.paging) : {};
9612
+
9613
+ if (!_is.hash(options.cls)) options.cls = {};
9614
+ if (!_is.hash(options.il8n)) options.il8n = {};
9615
+ if (type !== "default" && self.contains(type)){
9616
+ options.paging = _obj.extend({}, def, reg[type].opt, opt, {type: type});
9617
+ options.cls = _obj.extend(options.cls, {paging: def_cls}, {paging: reg[type].cls}, {paging: cls});
9618
+ options.il8n = _obj.extend(options.il8n, {paging: def_il8n}, {paging: reg[type].il8n}, {paging: il8n});
9619
+ } else {
9620
+ options.paging = _obj.extend({}, def, opt, {type: type});
9621
+ options.cls = _obj.extend(options.cls, {paging: def_cls}, {paging: cls});
9622
+ options.il8n = _obj.extend(options.il8n, {paging: def_il8n}, {paging: il8n});
9623
+ }
9624
+ return options;
9625
+ },
9626
+ configure: function(name, options, classes, il8n){
9627
+ var self = this;
9628
+ if (self.contains(name)){
9629
+ var reg = self.registered;
9630
+ _obj.extend(reg[name].opt, options);
9631
+ _obj.extend(reg[name].cls, classes);
9632
+ _obj.extend(reg[name].il8n, il8n);
9633
+ }
9634
+ },
9635
+ /**
9636
+ * @summary Checks if the factory contains a control registered using the supplied `name`.
9637
+ * @memberof FooGallery.PagingFactory#
9638
+ * @function hasCtrl
9639
+ * @param {string} name - The friendly name of the class.
9640
+ * @returns {boolean}
9641
+ */
9642
+ hasCtrl: function(name){
9643
+ var self = this, reg = self.registered[name];
9644
+ return _is.hash(reg) && _is.fn(reg.ctrl);
9645
+ },
9646
+ /**
9647
+ * @summary Create a new instance of a control class registered with the supplied `name` and arguments.
9648
+ * @memberof FooGallery.PagingFactory#
9649
+ * @function makeCtrl
9650
+ * @param {string} name - The friendly name of the class.
9651
+ * @param {FooGallery.Template} template - The template creating the control.
9652
+ * @param {FooGallery.Paging} parent - The parent paging class creating the control.
9653
+ * @param {string} position - The position the control will be displayed at.
9654
+ * @returns {?FooGallery.PagingControl}
9655
+ */
9656
+ makeCtrl: function(name, template, parent, position){
9657
+ var self = this, reg = self.registered[name];
9658
+ if (_is.hash(reg) && _is.fn(reg.ctrl)){
9659
+ return new reg.ctrl(template, parent, position);
9660
+ }
9661
+ return null;
9662
+ }
9663
+ });
9664
+
9665
+ /**
9666
+ * @summary The factory used to register and create the various paging types of FooGallery.
9667
+ * @memberof FooGallery
9668
+ * @name paging
9669
+ * @type {FooGallery.PagingFactory}
9670
+ */
9671
+ _.paging = new _.PagingFactory();
9672
+
9673
+ })(
9674
+ FooGallery,
9675
+ FooGallery.utils.is,
9676
+ FooGallery.utils.fn,
9677
+ FooGallery.utils.obj
9678
+ );
9679
  (function ($, _, _utils, _is) {
9680
 
9681
  _.Paging = _.Component.extend({
9700
  self.current = 0;
9701
  self.total = 0;
9702
  self.ctrls = [];
9703
+ self._pages = [];
9704
  },
9705
+ init: function(){},
9706
  fromHash: function(hash){
9707
  var parsed = parseInt(hash);
9708
  return isNaN(parsed) ? null : parsed;
9715
  },
9716
  setState: function(state){
9717
  this.rebuild();
9718
+ var shouldScroll = false;
9719
  if (!!state.item && !this.contains(state.page, state.item)){
9720
  state.page = this.find(state.item);
9721
  state.page = state.page !== 0 ? state.page : 1;
9722
+ shouldScroll = true;
9723
  }
9724
+ this.set(state.page, shouldScroll, false, false);
9725
  },
9726
  destroy: function () {
9727
  var self = this;
9728
+ self._pages.splice(0, self._pages.length);
9729
  $.each(self.ctrls.splice(0, self.ctrls.length), function (i, control) {
9730
  control.destroy();
9731
  });
9735
  var self = this, items = self.tmpl.items.available();
9736
  self.total = self.size > 0 && items.length > 0 ? Math.ceil(items.length / self.size) : 1;
9737
  for (var i = 0; i < self.total; i++) {
9738
+ self._pages.push(items.splice(0, self.size));
9739
  }
9740
  if (self.total > 1 && _.paging.hasCtrl(self.type)) {
9741
  var pos = self.position, top, bottom;
9759
  var self = this;
9760
  self.current = 0;
9761
  self.total = 0;
9762
+ self._pages.splice(0, self._pages.length);
9763
  $.each(self.ctrls.splice(0, self.ctrls.length), function (i, control) {
9764
  control.destroy();
9765
  });
9766
  self.build();
9767
  },
9768
  all: function () {
9769
+ return this._pages.slice();
9770
  },
9771
  available: function () {
9772
  return this.get(this.current);
9773
  },
 
 
 
9774
  controls: function (pageNumber) {
9775
  var self = this;
9776
  if (self.isValid(pageNumber)) {
9788
  create: function (pageNumber, isFilter) {
9789
  var self = this;
9790
  pageNumber = self.number(pageNumber);
9791
+
9792
+ var pageIndex = pageNumber - 1, pageItems = self._pages[pageIndex], detach;
9793
+ if (isFilter){
9794
+ detach = self.tmpl.items.all();
9795
+ } else {
9796
+ detach = self._pages.reduce(function(detach, page, index){
9797
+ return index === pageIndex ? detach : detach.concat(page);
9798
+ }, self.tmpl.items.unavailable());
9799
+ }
9800
+
9801
  self.current = pageNumber;
9802
+ self.tmpl.items.detach(detach);
9803
+ self.tmpl.items.create(pageItems, true);
9804
  },
9805
  get: function (pageNumber) {
9806
  var self = this;
9807
  if (self.isValid(pageNumber)) {
9808
  pageNumber = self.number(pageNumber);
9809
+ return self._pages[pageNumber - 1];
9810
  }
9811
  return [];
9812
  },
9813
  set: function (pageNumber, scroll, updateState, isFilter) {
9814
  var self = this;
9815
  if (self.isValid(pageNumber)) {
9816
+ self.controls(pageNumber);
9817
  var num = self.number(pageNumber), state;
9818
  if (num !== self.current) {
9819
  var prev = self.current, setPage = function () {
9823
  state = self.tmpl.state.get();
9824
  self.tmpl.state.update(state, self.pushOrReplace);
9825
  }
 
9826
  self.create(num, isFilter);
9827
  if (updateState) {
9828
  state = self.tmpl.state.get();
9829
  self.tmpl.state.update(state, self.pushOrReplace);
9830
  }
9831
+ self.tmpl.trigger("page-change", [self.current, prev, isFilter]);
9832
  if (self.scrollToTop && _is.boolean(scroll) ? scroll : false) {
9833
  var page = self.get(self.current);
9834
  if (page.length > 0) {
9835
  page[0].scrollTo("top");
9836
  }
9837
  }
9838
+ self.tmpl.trigger("after-page-change", [self.current, prev, isFilter]);
9839
  };
9840
+ var e = self.tmpl.trigger("before-page-change", [self.current, num, setPage, isFilter]);
9841
  if (e.isDefaultPrevented()) return false;
9842
  setPage();
9843
  return true;
9847
  },
9848
  find: function (item) {
9849
  var self = this;
9850
+ for (var i = 0, l = self._pages.length; i < l; i++) {
9851
+ if (_utils.inArray(item, self._pages[i]) !== -1) {
9852
  return i + 1;
9853
  }
9854
  }
9862
  this.goto(1);
9863
  },
9864
  last: function () {
9865
+ this.goto(this._pages.length);
9866
  },
9867
  prev: function () {
9868
  this.goto(this.current - 1);
9871
  this.goto(this.current + 1);
9872
  },
9873
  goto: function (pageNumber) {
9874
+ this.set(pageNumber, true);
 
 
 
9875
  }
9876
  });
9877
 
9882
  self.pages = parent;
9883
  self.position = position;
9884
  self.$container = null;
9885
+ self._containerExisted = false;
9886
+ self._placeholderClasses = [];
9887
  },
9888
  create: function () {
9889
  var self = this;
9890
+ self.$container = $("#" + self.tmpl.id + "_paging-" + self.position);
9891
+ if (self.$container.length > 0){
9892
+ self._containerExisted = true;
9893
+ self.$container.removeClass(function(i, classNames){
9894
+ self._placeholderClasses = classNames.match(/(^|\s)fg-ph-\S+/g) || [];
9895
+ return self._placeholderClasses.join(' ');
9896
+ }).addClass([self.pages.cls.container, self.pages.theme].join(' '));
9897
+ } else {
9898
+ self.$container = $("<nav/>", {"class": [self.pages.cls.container, self.pages.theme].join(' ')});
9899
+ }
9900
  return true;
9901
  },
9902
  destroy: function () {
9903
  var self = this;
9904
+ if (self._containerExisted){
9905
+ self.$container.empty()
9906
+ .removeClass()
9907
+ .addClass(self._placeholderClasses.join(' '));
9908
+ } else {
9909
+ self.$container.remove();
9910
+ }
9911
  self.$container = null;
9912
  },
9913
  append: function () {
9914
  var self = this;
9915
+ if (self._containerExisted) return;
9916
  if (self.position === "top") {
9917
  self.$container.insertBefore(self.tmpl.$el);
9918
  } else {
9947
  _.DotsControl = _.PagingControl.extend({
9948
  construct: function(template, parent, position){
9949
  this._super(template, parent, position);
9950
+ this.$list = null;
9951
+ this.$items = null;
 
9952
  },
9953
  create: function(){
 
 
 
 
 
 
 
 
 
 
 
 
 
9954
  var self = this;
9955
+ if (self._super()){
9956
+ var cls = self.pages.cls, il8n = self.pages.il8n,
9957
+ items = [], $list = $("<ul/>", {"class": cls.list});
9958
+
9959
+ for (var i = 0, l = self.pages.total, $item; i < l; i++){
9960
+ items.push($item = self.createItem(i + 1, il8n.page));
9961
+ $list.append($item);
9962
+ }
9963
+ self.$list = $list;
9964
+ self.$items = $($.map(items, function($item){ return $item.get(); }));
9965
+ self.$container.append($list);
9966
+ return true;
9967
  }
9968
+ return false;
9969
  },
9970
  destroy: function(){
9971
  var self = this, sel = self.pages.sel;
9972
  self.$list.find(sel.link).off("click.foogallery", self.onLinkClick);
 
 
9973
  self.$list = $();
9974
  self.$items = $();
9975
+ self._super();
9976
  },
9977
  update: function(pageNumber){
9978
  this.setSelected(pageNumber - 1);
10043
  // this check should not be required as we use the CSS pointer-events: none; property on disabled links but just in case test for the class here
10044
  if (!$(this).closest(sel.item).is(sel.disabled)){
10045
  self.pages.set(page, true);
 
10046
  }
10047
  }
10048
  });
10087
 
10088
  /**
10089
  * @summary The Masonry template for FooGallery.
10090
+ * @memberof FooGallery.
10091
  * @constructs MasonryTemplate
10092
+ * @param {Object} [options] - The options for the template.
10093
  * @param {(jQuery|HTMLElement)} [element] - The jQuery object or HTMLElement of the template. If not supplied one will be created within the `parent` element supplied to the {@link FooGallery.Template#initialize|initialize} method.
10094
  * @augments FooGallery.Template
10095
  * @borrows FooGallery.utils.Class.extend as extend
10096
  * @borrows FooGallery.utils.Class.override as override
10097
  * @description This template makes use of the popular [Masonry library](http://masonry.desandro.com/) to perform its layout. It supports two basic layout types, fixed and column based.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10098
  */
10099
  _.MasonryTemplate = _.Template.extend(/** @lends FooGallery.MasonryTemplate */{
10100
  construct: function(options, element){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10101
  var self = this;
10102
+ self._super(options, element);
10103
+ self.masonry = null;
10104
+ self.on({
10105
+ "pre-init": self.onPreInit,
10106
+ "destroyed": self.onDestroyed,
10107
+ "appended-items": self.onAppendedItems,
10108
+ "detach-item": self.onDetachItem,
10109
+ "layout after-filter-change": self.onLayoutRequired,
10110
+ "page-change": self.onPageChange
10111
+ }, self);
10112
+ },
10113
+ onPreInit: function(){
10114
+ var self = this, sel = self.sel,
10115
+ fixed = self.$el.hasClass("fg-fixed");
10116
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10117
  self.template.isFitWidth = fixed;
10118
  self.template.percentPosition = !fixed;
10119
  self.template.transitionDuration = 0;
10120
  self.template.itemSelector = sel.item.elem;
 
 
 
10121
  if (!fixed){
 
 
 
 
10122
  self.template.gutter = sel.gutterWidth;
10123
+ self.template.columnWidth = sel.columnWidth;
10124
  }
10125
+ self.masonry = new Masonry( self.el, self.template );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10126
  },
10127
+ onDestroyed: function(){
10128
+ var self = this;
10129
  if (self.masonry instanceof Masonry){
10130
  self.masonry.destroy();
10131
  }
10132
  },
10133
+ onLayoutRequired: function(){
10134
+ this.masonry.layout();
10135
  },
10136
+ onPageChange: function(event, current, prev, isFilter){
10137
+ if (!isFilter){
10138
+ this.masonry.layout();
10139
+ }
 
 
 
 
 
 
 
 
 
10140
  },
10141
+ onAppendedItems: function(event, items){
10142
+ var self = this,
10143
+ elements = items.map(function(item){
10144
+ return item.el;
10145
+ }),
10146
+ mItems = self.masonry.addItems(elements);
 
 
 
 
 
 
 
 
10147
  // add and layout the new items with no transitions
10148
+ self.masonry.layoutItems(mItems, true);
10149
  },
10150
+ onDetachItem: function(event, item){
 
 
 
 
 
 
 
 
 
 
 
10151
  if (!event.isDefaultPrevented()){
10152
  event.preventDefault();
10153
+ this.masonry.remove(item.el);
10154
+ item.$el.removeClass(this.cls.hidden);
10155
  item.isAttached = false;
 
10156
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10157
  }
10158
  });
10159
 
10160
  _.template.register("masonry", _.MasonryTemplate, {
10161
+ template: {}
 
 
 
 
 
10162
  }, {
10163
  container: "foogallery fg-masonry",
10164
  columnWidth: "fg-column-width",
10165
+ gutterWidth: "fg-gutter-width"
 
 
 
 
 
 
 
10166
  });
10167
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10168
  })(
10169
  FooGallery.$,
10170
  FooGallery,
10175
 
10176
  _.Justified = _utils.Class.extend({
10177
  construct: function(template, options){
10178
+ var self = this;
10179
+ self.tmpl = template;
10180
+ self.$el = template.$el;
10181
+ self.options = $.extend(true, {}, _.Justified.defaults, options);
10182
+ self._items = [];
10183
+ self.maxRowHeight = 0;
10184
+ self.borderSize = 0;
10185
+ self.align = ["left","center","right"].indexOf(self.options.align) !== -1 ? self.options.align : "center";
10186
  },
10187
  init: function(){
10188
  var self = this;
10189
+ self.maxRowHeight = self.getMaxRowHeight(self.options.maxRowHeight, self.options.rowHeight);
10190
+ self.borderSize = self.getBorderSize();
 
 
 
 
 
10191
  },
10192
  destroy: function(){
10193
  this.$el.removeAttr("style");
10194
  },
10195
+ getBorderSize: function(){
10196
+ var border = this.tmpl.getCSSClass("border", "");
10197
+ switch (border){
10198
+ case "fg-border-thin":
10199
+ return 4;
10200
+ case "fg-border-medium":
10201
+ return 10;
10202
+ case "fg-border-thick":
10203
+ return 16;
10204
+ default:
10205
+ return 0;
10206
+ }
10207
+ },
10208
+ getMaxRowHeight: function(value, def) {
10209
+ if (_is.string(value)){
10210
+ var parsed = parseInt(value);
10211
+ if (isNaN(parsed)) return def;
10212
+ if (parsed <= 0) return Infinity;
10213
+ return value.indexOf('%') !== -1 ? def * (parsed / 100) : parsed;
10214
+ }
10215
+ if (_is.number(value)){
10216
+ if (value <= 0) return Infinity;
10217
+ return value;
10218
+ }
10219
+ return def;
10220
  },
10221
+ layout: function(width){
10222
  var self = this;
10223
+ if (!_is.number(width)){
10224
+ width = self.$el.width();
10225
+ }
10226
+ if (width > 0){
10227
+ var result = self.createRows(width);
10228
+ if (result.height !== 0 && result.rows.length > 0){
10229
+ self.$el.height(result.height);
10230
+ result.rows.forEach(function(row, i){
10231
+ self.render(row);
10232
+ });
10233
  }
10234
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10235
  },
10236
  render: function(row){
10237
+ var self = this;
10238
+ row.items.forEach(function(item){
10239
+ if (item.elem){
10240
+ if (row.visible){
10241
+ item.elem.style.setProperty("position", "absolute");
10242
+ item.elem.style.setProperty("width", item.width + "px");
10243
+ item.elem.style.setProperty("height", item.height + "px");
10244
+ item.elem.style.setProperty("top", item.top + "px");
10245
+ item.elem.style.setProperty("left", item.left + "px");
10246
+ item.elem.style.setProperty("margin", "0");
10247
+ item.elem.style.removeProperty("display");
10248
+ if (self.maxRowHeight > 0){
10249
+ item.elem.style.setProperty("max-height", (self.maxRowHeight + (self.borderSize * 2)) + "px");
10250
+ } else {
10251
+ item.elem.style.removeProperty("max-height");
10252
+ }
10253
+ if (!item.elem.classList.contains("fg-positioned")){
10254
+ item.elem.classList.add("fg-positioned");
10255
+ }
10256
+ } else {
10257
+ item.elem.style.setProperty("display", "none");
10258
+ }
10259
  }
10260
+ });
10261
  },
10262
  justify: function(row, top, maxWidth, maxHeight){
10263
  var self = this,
10264
+ margin = self.options.margins,
10265
+ margins = margin * (row.items.length - 1),
10266
+ max = maxWidth - margins,
10267
+ rowWidth = row.width - margins;
10268
 
10269
+ var w_ratio = max / rowWidth;
10270
+ row.width = rowWidth * w_ratio;
10271
  row.height = row.height * w_ratio;
 
 
 
 
 
 
 
 
 
 
 
 
10272
 
10273
+ if (row.height > (maxHeight + (self.borderSize * 2))){
10274
+ var h_ratio = (maxHeight + (self.borderSize * 2)) / row.height;
10275
+ row.width = row.width * h_ratio;
10276
+ row.height = row.height * h_ratio;
 
 
 
 
 
 
 
 
10277
  }
10278
 
 
 
 
 
 
 
 
10279
  row.top = top;
10280
+ // default is left 0 because a full row starts at 0 and it matches default layouts
10281
  row.left = 0;
10282
+ // if we don't have a full row and align !== left
10283
+ if (self.align !== "left" && row.width < max){
10284
+ if (self.align === "right"){
10285
+ row.left = max - row.width;
10286
+ } else {
10287
+ row.left = (max - row.width) / 2;
 
 
10288
  }
10289
  }
10290
+
10291
  row.width += margins;
10292
 
10293
  var left = row.left;
10294
+ row.items.forEach(function(item, i){
10295
+ if (i > 0) left += margin;
 
10296
  item.left = left;
10297
  item.top = top;
10298
+ var i_ratio = row.height / item.height;
10299
+ item.width = item.width * i_ratio;
10300
+ item.height = item.height * i_ratio;
10301
  left += item.width;
10302
+ });
10303
 
10304
  return row.height;
10305
  },
10306
+ createRows: function(maxWidth){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10307
  var self = this,
10308
+ margin = self.options.margins,
10309
+ items = self.tmpl.getAvailable(),
10310
+ rows = [],
10311
+ index = -1;
10312
 
10313
+ function newRow(){
10314
+ return {
10315
  index: ++index,
10316
  visible: true,
10317
  width: 0,
10318
+ height: self.options.rowHeight + (self.borderSize * 2),
10319
  top: 0,
10320
  left: 0,
10321
  items: []
10322
  };
 
 
 
10323
  }
10324
 
10325
+ function newItem(item, rowHeight){
10326
+ var width = item.width, height = item.height;
10327
+ // make the item match the row height
10328
+ if (height !== rowHeight){
10329
+ var ratio = rowHeight / height;
10330
+ height = height * ratio;
10331
+ width = width * ratio;
 
10332
  }
10333
+ var maxRatio = self.maxRowHeight / rowHeight,
10334
+ maxWidth = width * maxRatio,
10335
+ maxHeight = height * maxRatio;
10336
+ return {
10337
+ __item: item,
10338
+ elem: item.el,
10339
+ width: width,
10340
+ height: height,
10341
+ maxWidth: maxWidth,
10342
+ maxHeight: maxHeight,
10343
+ top: 0,
10344
+ left: 0
10345
+ };
10346
+ }
10347
 
10348
+ var row = newRow(), top = 0, max = 0;
10349
+ items.forEach(function(fgItem){
10350
+ var item = newItem(fgItem, row.height);
10351
+ // adding this item to the row would exceed the max width
10352
+ if (row.width + item.width > maxWidth && row.items.length > 0){
10353
+ if (rows.length > 0) top += margin;
10354
+ var height = self.justify(row, top, maxWidth, self.maxRowHeight); // first justify the current row
10355
+ if (height > max) max = height;
10356
+ top += height;
10357
+ rows.push(row);
10358
+ row = newRow(); // then make the new one
10359
  }
10360
 
10361
+ if (row.items.length > 0) row.width += margin;
 
10362
  row.width += item.width;
10363
  row.items.push(item);
10364
+ });
10365
+
10366
+ if (row.items.length > 0){
10367
+ if (rows.length > 0) top += margin;
10368
+ var height = self.justify(row, top, maxWidth, self.maxRowHeight);
10369
+ if (max !== 0 && height > max){
10370
+ var h_ratio = max / height,
10371
+ w_ratio = (row.width * h_ratio) / maxWidth;
10372
+
10373
+ if (h_ratio < 0.9 || w_ratio < 0.9){
10374
+ height = self.justify(row, top, maxWidth, max - (self.borderSize * 2));
10375
+ }
10376
+ }
10377
+ top += height;
10378
+ rows.push(row);
10379
  }
10380
+
10381
+ return {
10382
+ height: top,
10383
+ rows: rows
10384
+ };
10385
  }
10386
  });
10387
 
10388
  _.Justified.defaults = {
 
10389
  rowHeight: 150,
10390
  maxRowHeight: "200%",
10391
  margins: 0,
10392
+ align: "center"
 
 
10393
  };
10394
 
10395
  })(
10398
  FooGallery.utils,
10399
  FooGallery.utils.is
10400
  );
10401
+ (function($, _){
10402
 
10403
  _.JustifiedTemplate = _.Template.extend({
10404
+ construct: function(options, element){
10405
+ var self = this;
10406
+ self._super(options, element);
10407
+ self.justified = null;
10408
+ self.on({
10409
+ "pre-init": self.onPreInit,
10410
+ "init": self.onInit,
10411
+ "destroyed": self.onDestroyed,
10412
+ "layout after-filter-change": self.onLayoutRequired,
10413
+ "page-change": self.onPageChange
10414
+ }, self);
10415
+ },
10416
+ onPreInit: function(){
10417
+ var self = this;
10418
  self.justified = new _.Justified( self, self.template );
10419
  },
10420
+ onInit: function(){
10421
+ this.justified.init();
 
 
 
10422
  },
10423
+ onDestroyed: function(){
10424
+ var self = this;
10425
+ if (self.justified instanceof _.Justified){
10426
+ self.justified.destroy();
10427
+ }
10428
  },
10429
+ onLayoutRequired: function(){
10430
+ this.justified.layout(this.lastWidth);
10431
  },
10432
+ onPageChange: function(event, current, prev, isFilter){
10433
  if (!isFilter){
10434
+ this.justified.layout(this.lastWidth);
10435
  }
 
 
 
10436
  }
10437
  });
10438
 
10441
  });
10442
 
10443
  })(
10444
+ FooGallery.$,
10445
+ FooGallery
 
10446
  );
10447
+ (function($, _){
10448
 
10449
+ _.JustifiedCSSTemplate = _.Template.extend({});
 
 
 
 
 
 
 
10450
 
10451
+ _.template.register("justified-css", _.JustifiedCSSTemplate, null, {
10452
+ container: "foogallery fg-justified-css"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10453
  });
10454
 
10455
+ })(
10456
+ FooGallery.$,
10457
+ FooGallery
10458
+ );
10459
+ (function($, _, _utils, _is, _fn){
10460
+
10461
+ _.PortfolioTemplate = _.Template.extend({});
10462
+
10463
+ _.template.register("simple_portfolio", _.PortfolioTemplate, {}, {
10464
  container: "foogallery fg-simple_portfolio"
10465
  });
10466
 
10475
 
10476
  _.ImageViewerTemplate = _.Template.extend({
10477
  construct: function (options, element) {
10478
+ var self = this;
10479
+ self._super(_obj.extend({}, options, {
10480
  paging: {
10481
  pushOrReplace: "replace",
10482
  theme: "fg-light",
10492
  * @name $inner
10493
  * @type {jQuery}
10494
  */
10495
+ self.$inner = $();
10496
  /**
10497
  * @summary The jQuery object that displays the current image count.
10498
  * @memberof FooGallery.ImageViewerTemplate#
10499
  * @name $current
10500
  * @type {jQuery}
10501
  */
10502
+ self.$current = $();
10503
  /**
10504
  * @summary The jQuery object that displays the current image count.
10505
  * @memberof FooGallery.ImageViewerTemplate#
10506
  * @name $current
10507
  * @type {jQuery}
10508
  */
10509
+ self.$total = $();
10510
  /**
10511
  * @summary The jQuery object for the previous button.
10512
  * @memberof FooGallery.ImageViewerTemplate#
10513
  * @name $prev
10514
  * @type {jQuery}
10515
  */
10516
+ self.$prev = $();
10517
  /**
10518
  * @summary The jQuery object for the next button.
10519
  * @memberof FooGallery.ImageViewerTemplate#
10520
  * @name $next
10521
  * @type {jQuery}
10522
  */
10523
+ self.$next = $();
10524
  /**
10525
  * @summary The CSS classes for the Image Viewer template.
10526
  * @memberof FooGallery.ImageViewerTemplate#
10533
  * @name sel
10534
  * @type {FooGallery.ImageViewerTemplate~CSSSelectors}
10535
  */
10536
+ self.on({
10537
+ "pre-init": self.onPreInit,
10538
+ "init": self.onInit,
10539
+ "destroy": self.onDestroy,
10540
+ "append-item": self.onAppendItem,
10541
+ "after-page-change": self.onAfterPageChange,
10542
+ "after-filter-change": self.onAfterFilterChange
10543
+ }, self);
10544
  },
10545
  createChildren: function(){
10546
  var self = this;
10561
  var self = this;
10562
  self.$el.find(self.sel.inner).remove();
10563
  },
10564
+
10565
+ onPreInit: function(event){
10566
+ var self = this;
10567
  self.$inner = self.$el.find(self.sel.innerContainer);
10568
  self.$current = self.$el.find(self.sel.countCurrent);
10569
  self.$total = self.$el.find(self.sel.countTotal);
10570
  self.$prev = self.$el.find(self.sel.prev);
10571
  self.$next = self.$el.find(self.sel.next);
10572
  },
10573
+ onInit: function (event) {
10574
+ var self = this;
10575
  if (self.template.attachFooBox) {
10576
  self.$el.on('foobox.previous', {self: self}, self.onFooBoxPrev)
10577
  .on('foobox.next', {self: self}, self.onFooBoxNext);
10579
  self.$prev.on('click', {self: self}, self.onPrevClick);
10580
  self.$next.on('click', {self: self}, self.onNextClick);
10581
  },
 
 
 
10582
  /**
10583
  * @summary Destroy the plugin cleaning up any bound events.
10584
  * @memberof FooGallery.ImageViewerTemplate#
10585
  * @function onDestroy
10586
  */
10587
+ onDestroy: function (event) {
10588
+ var self = this;
10589
  if (self.template.attachFooBox) {
10590
  self.$el.off({
10591
  'foobox.previous': self.onFooBoxPrev,
10595
  self.$prev.off('click', self.onPrevClick);
10596
  self.$next.off('click', self.onNextClick);
10597
  },
10598
+ onAppendItem: function (event, item) {
10599
  event.preventDefault();
10600
+ this.$inner.append(item.$el);
 
10601
  item.isAttached = true;
10602
  },
10603
+ onAfterPageChange: function(event, current, prev, isFilter){
10604
  if (!isFilter){
10605
+ this.update();
10606
  }
10607
  },
10608
+ onAfterFilterChange: function(event){
10609
+ this.update();
10610
  },
10611
+
10612
  update: function(){
10613
  if (this.pages){
10614
  this.$current.text(this.pages.current);
10875
  }
10876
  _t.start(self.$piles, function($el){
10877
  $el.css({width: size.width + 'px', height: size.height + 'px'});
10878
+ }, null, 350).then(function(){
10879
  self.ignoreResize = false;
10880
  });
10881
  },
11121
  def.reject();
11122
  }
11123
  });
11124
+ self.$image.prop('src', self.$image.attr(self.opt.src))
11125
+ .prop('srcset', self.$image.attr(self.opt.srcset));
11126
  }).promise();
11127
  }
11128
  });
11129
 
11130
  _.StackAlbum.Item.defaults = {
11131
  index: -1,
11132
+ src: 'data-src-fg',
11133
+ srcset: 'data-srcset-fg'
11134
  };
11135
 
11136
  })(
11172
  );
11173
  (function ($, _, _utils, _obj, _is) {
11174
 
11175
+ _.triggerPostLoad = function (e, current, prev, isFilter) {
11176
+ var tmpl = e.target;
11177
+ if (tmpl instanceof _.Template){
11178
+ if (tmpl.initialized && (e.type === "after-page-change" && !isFilter || e.type === "after-filter-change")) {
11179
+ try {
11180
+ // if the gallery is displayed within a FooBox do not trigger the post-load which would cause the lightbox to re-init
11181
+ if (tmpl.$el.parents(".fbx-item").length > 0) return;
11182
+ if (tmpl.$el.hasClass("fbx-instance") && !!window.FOOBOX && !!$.fn.foobox){
11183
+ tmpl.$el.foobox(window.FOOBOX.o);
11184
+ } else {
11185
+ $("body").trigger("post-load");
11186
+ }
11187
+ } catch(err) {
11188
+ console.error(err);
11189
  }
 
 
11190
  }
11191
  }
11192
  };
11193
 
11194
  _.autoDefaults = {
11195
  on: {
11196
+ "after-page-change after-filter-change": _.triggerPostLoad
11197
  }
11198
  };
11199
 
11210
  if (window.FooGallery_il8n && _is.object(window.FooGallery_il8n)){
11211
  var il8n = window.FooGallery_il8n;
11212
  for (var factory in il8n){
11213
+ if (!il8n.hasOwnProperty(factory) || !(_[factory] instanceof _.Factory) || !_is.object(il8n[factory])) continue;
11214
  for (var component in il8n[factory]){
11215
  if (il8n[factory].hasOwnProperty(component)){
11216
  _[factory].configure(component, null, null, il8n[factory][component]);
extensions/default-templates/shared/js/foogallery.min.js CHANGED
@@ -1,12 +1,12 @@
1
  /*
2
  * FooGallery - The Most Intuitive and Extensible Gallery Creation and Management Tool Ever Created for WordPress
3
- * @version 1.4.26
4
  * @link
5
  * @copyright Steven Usher & Brad Vincent 2015
6
  * @license Released under the GPLv3 license.
7
  */
8
 
9
- !function(){"use strict";function a(a){this.time=a.time,this.target=a.target,this.rootBounds=a.rootBounds,this.boundingClientRect=a.boundingClientRect,this.intersectionRect=a.intersectionRect||i(),this.isIntersecting=!!a.intersectionRect;var b=this.boundingClientRect,c=b.width*b.height,d=this.intersectionRect,e=d.width*d.height;this.intersectionRatio=c?Number((e/c).toFixed(4)):this.isIntersecting?1:0}function b(a,b){var c=b||{};if("function"!=typeof a)throw new Error("callback must be a function");if(c.root&&1!=c.root.nodeType)throw new Error("root must be an Element");this._checkForIntersections=d(this._checkForIntersections.bind(this),this.THROTTLE_TIMEOUT),this._callback=a,this._observationTargets=[],this._queuedEntries=[],this._rootMarginValues=this._parseRootMargin(c.rootMargin),this.thresholds=this._initThresholds(c.threshold),this.root=c.root||null,this.rootMargin=this._rootMarginValues.map(function(a){return a.value+a.unit}).join(" ")}function c(){return window.performance&&performance.now&&performance.now()}function d(a,b){var c=null;return function(){c||(c=setTimeout(function(){a(),c=null},b))}}function e(a,b,c,d){"function"==typeof a.addEventListener?a.addEventListener(b,c,d||!1):"function"==typeof a.attachEvent&&a.attachEvent("on"+b,c)}function f(a,b,c,d){"function"==typeof a.removeEventListener?a.removeEventListener(b,c,d||!1):"function"==typeof a.detatchEvent&&a.detatchEvent("on"+b,c)}function g(a,b){var c=Math.max(a.top,b.top),d=Math.min(a.bottom,b.bottom),e=Math.max(a.left,b.left),f=Math.min(a.right,b.right),g=f-e,h=d-c;return g>=0&&h>=0&&{top:c,bottom:d,left:e,right:f,width:g,height:h}}function h(a){var b;try{b=a.getBoundingClientRect()}catch(a){}return b?(b.width&&b.height||(b={top:b.top,right:b.right,bottom:b.bottom,left:b.left,width:b.right-b.left,height:b.bottom-b.top}),b):i()}function i(){return{top:0,bottom:0,left:0,right:0,width:0,height:0}}function j(a,b){for(var c=b;c;){if(c==a)return!0;c=k(c)}return!1}function k(a){var b=a.parentNode;return b&&11==b.nodeType&&b.host?b.host:b&&b.assignedSlot?b.assignedSlot.parentNode:b}if("object"==typeof window){if("IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype)return void("isIntersecting"in window.IntersectionObserverEntry.prototype||Object.defineProperty(window.IntersectionObserverEntry.prototype,"isIntersecting",{get:function(){return this.intersectionRatio>0}}));var l=window.document,m=[];b.prototype.THROTTLE_TIMEOUT=100,b.prototype.POLL_INTERVAL=null,b.prototype.USE_MUTATION_OBSERVER=!0,b.prototype.observe=function(a){if(!this._observationTargets.some(function(b){return b.element==a})){if(!a||1!=a.nodeType)throw new Error("target must be an Element");this._registerInstance(),this._observationTargets.push({element:a,entry:null}),this._monitorIntersections(),this._checkForIntersections()}},b.prototype.unobserve=function(a){this._observationTargets=this._observationTargets.filter(function(b){return b.element!=a}),this._observationTargets.length||(this._unmonitorIntersections(),this._unregisterInstance())},b.prototype.disconnect=function(){this._observationTargets=[],this._unmonitorIntersections(),this._unregisterInstance()},b.prototype.takeRecords=function(){var a=this._queuedEntries.slice();return this._queuedEntries=[],a},b.prototype._initThresholds=function(a){var b=a||[0];return Array.isArray(b)||(b=[b]),b.sort().filter(function(a,b,c){if("number"!=typeof a||isNaN(a)||a<0||a>1)throw new Error("threshold must be a number between 0 and 1 inclusively");return a!==c[b-1]})},b.prototype._parseRootMargin=function(a){var b=a||"0px",c=b.split(/\s+/).map(function(a){var b=/^(-?\d*\.?\d+)(px|%)$/.exec(a);if(!b)throw new Error("rootMargin must be specified in pixels or percent");return{value:parseFloat(b[1]),unit:b[2]}});return c[1]=c[1]||c[0],c[2]=c[2]||c[0],c[3]=c[3]||c[1],c},b.prototype._monitorIntersections=function(){this._monitoringIntersections||(this._monitoringIntersections=!0,this.POLL_INTERVAL?this._monitoringInterval=setInterval(this._checkForIntersections,this.POLL_INTERVAL):(e(window,"resize",this._checkForIntersections,!0),e(l,"scroll",this._checkForIntersections,!0),this.USE_MUTATION_OBSERVER&&"MutationObserver"in window&&(this._domObserver=new MutationObserver(this._checkForIntersections),this._domObserver.observe(l,{attributes:!0,childList:!0,characterData:!0,subtree:!0}))))},b.prototype._unmonitorIntersections=function(){this._monitoringIntersections&&(this._monitoringIntersections=!1,clearInterval(this._monitoringInterval),this._monitoringInterval=null,f(window,"resize",this._checkForIntersections,!0),f(l,"scroll",this._checkForIntersections,!0),this._domObserver&&(this._domObserver.disconnect(),this._domObserver=null))},b.prototype._checkForIntersections=function(){var b=this._rootIsInDom(),d=b?this._getRootRect():i();this._observationTargets.forEach(function(e){var f=e.element,g=h(f),i=this._rootContainsTarget(f),j=e.entry,k=b&&i&&this._computeTargetAndRootIntersection(f,d),l=e.entry=new a({time:c(),target:f,boundingClientRect:g,rootBounds:d,intersectionRect:k});j?b&&i?this._hasCrossedThreshold(j,l)&&this._queuedEntries.push(l):j&&j.isIntersecting&&this._queuedEntries.push(l):this._queuedEntries.push(l)},this),this._queuedEntries.length&&this._callback(this.takeRecords(),this)},b.prototype._computeTargetAndRootIntersection=function(a,b){if("none"!=window.getComputedStyle(a).display){for(var c=h(a),d=c,e=k(a),f=!1;!f;){var i=null,j=1==e.nodeType?window.getComputedStyle(e):{};if("none"==j.display)return;if(e==this.root||e==l?(f=!0,i=b):e!=l.body&&e!=l.documentElement&&"visible"!=j.overflow&&(i=h(e)),i&&!(d=g(i,d)))break;e=k(e)}return d}},b.prototype._getRootRect=function(){var a;if(this.root)a=h(this.root);else{var b=l.documentElement,c=l.body;a={top:0,left:0,right:b.clientWidth||c.clientWidth,width:b.clientWidth||c.clientWidth,bottom:b.clientHeight||c.clientHeight,height:b.clientHeight||c.clientHeight}}return this._expandRectByRootMargin(a)},b.prototype._expandRectByRootMargin=function(a){var b=this._rootMarginValues.map(function(b,c){return"px"==b.unit?b.value:b.value*(c%2?a.width:a.height)/100}),c={top:a.top-b[0],right:a.right+b[1],bottom:a.bottom+b[2],left:a.left-b[3]};return c.width=c.right-c.left,c.height=c.bottom-c.top,c},b.prototype._hasCrossedThreshold=function(a,b){var c=a&&a.isIntersecting?a.intersectionRatio||0:-1,d=b.isIntersecting?b.intersectionRatio||0:-1;if(c!==d)for(var e=0;e<this.thresholds.length;e++){var f=this.thresholds[e];if(f==c||f==d||f<c!=f<d)return!0}},b.prototype._rootIsInDom=function(){return!this.root||j(l,this.root)},b.prototype._rootContainsTarget=function(a){return j(this.root||l,a)},b.prototype._registerInstance=function(){m.indexOf(this)<0&&m.push(this)},b.prototype._unregisterInstance=function(){var a=m.indexOf(this);-1!=a&&m.splice(a,1)},window.IntersectionObserver=b,window.IntersectionObserverEntry=a}}(),function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.ResizeObserver=b()}(this,function(){"use strict";function a(a,b){function c(){f&&(f=!1,a()),g&&e()}function d(){n(c)}function e(){var a=Date.now();if(f){if(a-h<o)return;g=!0}else f=!0,g=!1,setTimeout(d,b);h=a}var f=!1,g=!1,h=0;return e}function b(a){return parseFloat(a)||0}function c(a){for(var c=[],d=1;d<arguments.length;d++)c[d-1]=arguments[d];return c.reduce(function(c,d){return c+b(a["border-"+d+"-width"])},0)}function d(a){for(var c=["top","right","bottom","left"],d={},e=0,f=c;e<f.length;e++){var g=f[e],h=a["padding-"+g];d[g]=b(h)}return d}function e(a){var b=a.getBBox();return j(0,0,b.width,b.height)}function f(a){var e=a.clientWidth,f=a.clientHeight;if(!e&&!f)return v;var h=u(a).getComputedStyle(a),i=d(h),k=i.left+i.right,l=i.top+i.bottom,m=b(h.width),n=b(h.height);if("border-box"===h.boxSizing&&(Math.round(m+k)!==e&&(m-=c(h,"left","right")+k),Math.round(n+l)!==f&&(n-=c(h,"top","bottom")+l)),!g(a)){var o=Math.round(m+k)-e,p=Math.round(n+l)-f;1!==Math.abs(o)&&(m-=o),1!==Math.abs(p)&&(n-=p)}return j(i.left,i.top,m,n)}function g(a){return a===u(a).document.documentElement}function h(a){return l?w(a)?e(a):f(a):v}function i(a){var b=a.x,c=a.y,d=a.width,e=a.height,f="undefined"!=typeof DOMRectReadOnly?DOMRectReadOnly:Object,g=Object.create(f.prototype);return t(g,{x:b,y:c,width:d,height:e,top:c,right:b+d,bottom:e+c,left:b}),g}function j(a,b,c,d){return{x:a,y:b,width:c,height:d}}var k=function(){function a(a,b){var c=-1;return a.some(function(a,d){return a[0]===b&&(c=d,!0)}),c}return"undefined"!=typeof Map?Map:function(){function b(){this.__entries__=[]}return Object.defineProperty(b.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),b.prototype.get=function(b){var c=a(this.__entries__,b),d=this.__entries__[c];return d&&d[1]},b.prototype.set=function(b,c){var d=a(this.__entries__,b);~d?this.__entries__[d][1]=c:this.__entries__.push([b,c])},b.prototype.delete=function(b){var c=this.__entries__,d=a(c,b);~d&&c.splice(d,1)},b.prototype.has=function(b){return!!~a(this.__entries__,b)},b.prototype.clear=function(){this.__entries__.splice(0)},b.prototype.forEach=function(a,b){void 0===b&&(b=null);for(var c=0,d=this.__entries__;c<d.length;c++){var e=d[c];a.call(b,e[1],e[0])}},b}()}(),l="undefined"!=typeof window&&"undefined"!=typeof document&&window.document===document,m=function(){return"undefined"!=typeof global&&global.Math===Math?global:"undefined"!=typeof self&&self.Math===Math?self:"undefined"!=typeof window&&window.Math===Math?window:Function("return this")()}(),n=function(){return"function"==typeof requestAnimationFrame?requestAnimationFrame.bind(m):function(a){return setTimeout(function(){return a(Date.now())},1e3/60)}}(),o=2,p=20,q=["top","right","bottom","left","width","height","size","weight"],r="undefined"!=typeof MutationObserver,s=function(){function b(){this.connected_=!1,this.mutationEventsAdded_=!1,this.mutationsObserver_=null,this.observers_=[],this.onTransitionEnd_=this.onTransitionEnd_.bind(this),this.refresh=a(this.refresh.bind(this),p)}return b.prototype.addObserver=function(a){~this.observers_.indexOf(a)||this.observers_.push(a),this.connected_||this.connect_()},b.prototype.removeObserver=function(a){var b=this.observers_,c=b.indexOf(a);~c&&b.splice(c,1),!b.length&&this.connected_&&this.disconnect_()},b.prototype.refresh=function(){this.updateObservers_()&&this.refresh()},b.prototype.updateObservers_=function(){var a=this.observers_.filter(function(a){return a.gatherActive(),a.hasActive()});return a.forEach(function(a){return a.broadcastActive()}),a.length>0},b.prototype.connect_=function(){l&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),r?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},b.prototype.disconnect_=function(){l&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},b.prototype.onTransitionEnd_=function(a){var b=a.propertyName,c=void 0===b?"":b;q.some(function(a){return!!~c.indexOf(a)})&&this.refresh()},b.getInstance=function(){return this.instance_||(this.instance_=new b),this.instance_},b.instance_=null,b}(),t=function(a,b){for(var c=0,d=Object.keys(b);c<d.length;c++){var e=d[c];Object.defineProperty(a,e,{value:b[e],enumerable:!1,writable:!1,configurable:!0})}return a},u=function(a){return a&&a.ownerDocument&&a.ownerDocument.defaultView||m},v=j(0,0,0,0),w=function(){return"undefined"!=typeof SVGGraphicsElement?function(a){return a instanceof u(a).SVGGraphicsElement}:function(a){return a instanceof u(a).SVGElement&&"function"==typeof a.getBBox}}(),x=function(){function a(a){this.broadcastWidth=0,this.broadcastHeight=0,this.contentRect_=j(0,0,0,0),this.target=a}return a.prototype.isActive=function(){var a=h(this.target);return this.contentRect_=a,a.width!==this.broadcastWidth||a.height!==this.broadcastHeight},a.prototype.broadcastRect=function(){var a=this.contentRect_;return this.broadcastWidth=a.width,this.broadcastHeight=a.height,a},a}(),y=function(){function a(a,b){var c=i(b);t(this,{target:a,contentRect:c})}return a}(),z=function(){function a(a,b,c){if(this.activeObservations_=[],this.observations_=new k,"function"!=typeof a)throw new TypeError("The callback provided as parameter 1 is not a function.");this.callback_=a,this.controller_=b,this.callbackCtx_=c}return a.prototype.observe=function(a){if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");if("undefined"!=typeof Element&&Element instanceof Object){if(!(a instanceof u(a).Element))throw new TypeError('parameter 1 is not of type "Element".');var b=this.observations_;b.has(a)||(b.set(a,new x(a)),this.controller_.addObserver(this),this.controller_.refresh())}},a.prototype.unobserve=function(a){if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");if("undefined"!=typeof Element&&Element instanceof Object){if(!(a instanceof u(a).Element))throw new TypeError('parameter 1 is not of type "Element".');var b=this.observations_;b.has(a)&&(b.delete(a),b.size||this.controller_.removeObserver(this))}},a.prototype.disconnect=function(){this.clearActive(),this.observations_.clear(),this.controller_.removeObserver(this)},a.prototype.gatherActive=function(){var a=this;this.clearActive(),this.observations_.forEach(function(b){b.isActive()&&a.activeObservations_.push(b)})},a.prototype.broadcastActive=function(){if(this.hasActive()){var a=this.callbackCtx_,b=this.activeObservations_.map(function(a){return new y(a.target,a.broadcastRect())});this.callback_.call(a,b,a),this.clearActive()}},a.prototype.clearActive=function(){this.activeObservations_.splice(0)},a.prototype.hasActive=function(){return this.activeObservations_.length>0},a}(),A="undefined"!=typeof WeakMap?new WeakMap:new k,B=function(){function a(b){if(!(this instanceof a))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var c=s.getInstance(),d=new z(b,c,this);A.set(this,d)}return a}();return["observe","unobserve","disconnect"].forEach(function(a){B.prototype[a]=function(){var b;return(b=A.get(this))[a].apply(b,arguments)}}),function(){return void 0!==m.ResizeObserver?m.ResizeObserver:B}()}),function(a,b){b.$=a}(jQuery,window.FooGallery=window.FooGallery||{}),function(a){if(!a)return void console.warn("jQuery must be included in the page prior to the FooGallery.utils library.");(function(){try{return!!window.FooGallery.utils}catch(a){return!1}})()||(window.FooGallery.utils={$:a,version:"0.2.2"})}(jQuery),function(a,b){"0.2.2"===b.version&&(b.is={},b.is.array=function(a){return"[object Array]"===Object.prototype.toString.call(a)},b.is.boolean=function(a){return"[object Boolean]"===Object.prototype.toString.call(a)},b.is.element=function(a){return"object"==typeof HTMLElement?a instanceof HTMLElement:!!a&&"object"==typeof a&&1===a.nodeType&&"string"==typeof a.nodeName},b.is.empty=function(a){if(b.is.undef(a)||null===a)return!0;if(b.is.number(a)&&0===a)return!0;if(b.is.boolean(a)&&!1===a)return!0;if(b.is.string(a)&&0===a.length)return!0;if(b.is.array(a)&&0===a.length)return!0;if(b.is.jq(a)&&0===a.length)return!0;if(b.is.hash(a)){for(var c in a)if(a.hasOwnProperty(c))return!1;return!0}return!1},b.is.error=function(a){return"[object Error]"===Object.prototype.toString.call(a)},b.is.fn=function(a){return a===window.alert||"[object Function]"===Object.prototype.toString.call(a)},b.is.hash=function(a){return b.is.object(a)&&a.constructor===Object&&!a.nodeType&&!a.setInterval},b.is.jq=function(c){return!b.is.undef(a)&&c instanceof a},b.is.number=function(a){return"[object Number]"===Object.prototype.toString.call(a)&&!isNaN(a)},b.is.object=function(a){return"[object Object]"===Object.prototype.toString.call(a)&&!b.is.undef(a)&&null!==a},b.is.promise=function(a){return b.is.object(a)&&b.is.fn(a.then)&&b.is.fn(a.promise)},b.is.size=function(a){return!!(b.is.string(a)&&!b.is.empty(a)||b.is.number(a))&&/^(auto|none|(?:[\d.]*)+?(?:%|px|mm|q|cm|in|pt|pc|em|ex|ch|rem|vh|vw|vmin|vmax)?)$/.test(a)},b.is.string=function(a){return"[object String]"===Object.prototype.toString.call(a)},b.is.undef=function(a){return void 0===a})}(FooGallery.utils.$,FooGallery.utils),function(a,b,c){if("0.2.2"===b.version){b.fn={};var d=Function.prototype.toString;b.fn.CONTAINS_SUPER=/xyz/.test(d.call(function(){xyz}))?/\b_super\b/:/.*/,b.fn.addOrOverride=function(a,e,f){if(c.object(a)&&c.string(e)&&!c.empty(e)&&c.fn(f)){var g=a[e],h=c.fn(g)&&b.fn.CONTAINS_SUPER.test(d.call(f));a[e]=h?function(a,b){return function(){var c=this._super;this._super=a;var d=b.apply(this,arguments);return this._super=c,d}}(g,f):f}},b.fn.apply=function(a,b){return b.unshift(a),new(Function.prototype.bind.apply(a,b))},b.fn.arg2arr=function(a){return Array.prototype.slice.call(a)},b.fn.debounce=function(a,c){var d;return function(){var e=this,f=b.fn.arg2arr(arguments);clearTimeout(d),d=setTimeout(function(){a.apply(e,f)},c)}},b.fn.throttle=function(a,c){var d,e;return function(){var f=this,g=b.fn.arg2arr(arguments);d?(clearTimeout(e),e=setTimeout(function(){Date.now()-d>=c&&(a.apply(f,g),d=Date.now())},c-(Date.now()-d))):(a.apply(f,g),d=Date.now())}},b.fn.check=function(d,e,f,g){function h(a){return function(){return a.apply(d,arguments)}}return f=c.fn(f)?f:a.noop,d=c.object(d)?d:window,e=c.string(e)?b.fn.fetch(e,g):e,h(c.fn(e)?e:f)},b.fn.fetch=function(b,d){return!c.string(b)||c.empty(b)?null:(d=c.object(d)?d:window,a.each(b.split("."),function(a,b){if(!d[b])return!1;d=d[b]}),c.fn(d)?d:null)},b.fn.enqueue=function(d,e,f,g){function h(a,b){try{return n.push(a),b.apply(a,i)}catch(a){return j.reject(a,n),j}}var i=b.fn.arg2arr(arguments),j=a.Deferred(),k=a.Deferred(),l=k.promise(),m=[],n=[],o=!0;return d=i.shift(),e=i.shift(),a.each(d,function(a,d){c.fn(d[e])&&(l=l.then(function(){if(!o){var a=b.fn.arg2arr(arguments);m.push(a)}return o=!1,h(d,d[e])}))}),l.then(function(){if(!o){var a=b.fn.arg2arr(arguments);m.push(a)}o=!1,j.resolve(m)}),l.fail(function(){var a=b.fn.arg2arr(arguments);a.push(n),j.reject.apply(j,a)}),k.resolve(),j.promise()},b.fn.when=function(b){function d(){--g||e.resolve(f)}if(!c.array(b)||c.empty(b))return a.when();for(var e=a.Deferred(),f=[],g=b.length,h=0;h<b.length;h++)c.promise(b[h])?b[h].then(function(a){f.push(a)}).always(d):d();return e.promise()},b.fn.rejectWith=function(c,d){var e=a.Deferred(),f=b.fn.arg2arr(arguments);return e.reject.apply(e,f).promise()},b.fn.resolveWith=function(c,d){var e=a.Deferred(),f=b.fn.arg2arr(arguments);return e.resolve.apply(e,f).promise()},b.fn.resolved=a.Deferred().resolve().promise(),b.fn.rejected=a.Deferred().reject().promise()}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b){if("0.2.2"===a.version){a.url={};var c=document.createElement("a");a.url.parts=function(a){c.href=a;var b=c.port?c.port:-1!==["http:","https:"].indexOf(c.protocol)?"https:"===c.protocol?"443":"80":"",d=c.hostname+(b?":"+b:""),e=c.origin?c.origin:c.protocol+"//"+d,f="/"===c.pathname.slice(0,1)?c.pathname:"/"+c.pathname;return{hash:c.hash,host:d,hostname:c.hostname,href:c.href,origin:e,pathname:f,port:b,protocol:c.protocol,search:c.search}},a.url.full=function(a){return!b.string(a)||b.empty(a)?null:(c.href=a,c.href)},a.url.param=function(a,c,d){if(!b.string(a)||!b.string(c)||b.empty(c))return a;var e,f,g,h;return b.undef(d)?(e=new RegExp("[?|&]"+c+"=([^&;]+?)(&|#|;|$)"),f=e.exec(a)||["",""],g=f[1].replace(/\+/g,"%20"),b.string(g)&&!b.empty(g)?decodeURIComponent(g):null):(b.empty(d)?(e=new RegExp("^([^#]*?)(([^#]*)&)?"+c+"(=[^&#]*)?(&|#|$)"),g=a.replace(e,"$1$3$5").replace(/^([^#]*)((\?)&|\?(#|$))/,"$1$3$4")):(e=new RegExp("([?&])"+c+"[^&]*"),h=c+"="+encodeURIComponent(d),(g=a.replace(e,"$1"+h))!==a||e.test(g)||(g+=(-1!==g.indexOf("?")?"&":"?")+h)),g)}}}(FooGallery.utils,FooGallery.utils.is),function(a,b,c){"0.2.2"===a.version&&(a.str={},a.str.camel=function(a){return b.empty(a)?a:a.toUpperCase()===a?a.toLowerCase():a.replace(/^([A-Z])|[-\s_]+(\w)/g,function(a,c,d){return b.string(d)?d.toUpperCase():c.toLowerCase()})},a.str.kebab=function(a){return b.empty(a)?a:a.match(/[A-Z]{2,}(?=[A-Z][a-z0-9]*|\b)|[A-Z]?[a-z0-9]*|[A-Z]|[0-9]+/g).filter(Boolean).map(function(a){return a.toLowerCase()}).join("-")},a.str.contains=function(a,c,d){return!(!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c))&&(c.length<=a.length&&-1!==(d?a.toUpperCase().indexOf(c.toUpperCase()):a.indexOf(c)))},a.str.containsWord=function(a,c,d){if(!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c)||a.length<c.length)return!1;for(var e=a.split(/\W/),f=0,g=e.length;f<g;f++)if(d?e[f].toUpperCase()===c.toUpperCase():e[f]===c)return!0;return!1},a.str.endsWith=function(a,c){return!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c)?a===c:a.slice(a.length-c.length)===c},a.str.escapeRegExp=function(a){return b.empty(a)?a:a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},a.str.fnv1a=function(a){if(!b.string(a)||b.empty(a))return null;var c,d,e=2166136261;for(c=0,d=a.length;c<d;c++)e^=a.charCodeAt(c),e+=(e<<1)+(e<<4)+(e<<7)+(e<<8)+(e<<24);return e>>>0},a.str.from=function(b,c){return a.str.contains(b,c)?b.substring(b.indexOf(c)+c.length):null},a.str.join=function(d,e,f){if(!b.string(d)||!b.string(e))return null;var g=c.arg2arr(arguments);d=g.shift();var h,i,j=g.shift();for(h=0,i=g.length;h<i;h++)e=g[h],b.empty(e)||(a.str.endsWith(j,d)&&(j=j.slice(0,j.length-d.length)),a.str.startsWith(e,d)&&(e=e.slice(d.length)),j+=d+e);return j},a.str.startsWith=function(a,c){return!b.empty(a)&&!b.empty(c)&&a.slice(0,c.length)===c},a.str.until=function(b,c){return a.str.contains(b,c)?b.substring(0,b.indexOf(c)):b},a.str.format=function(d,e,f){var g=c.arg2arr(arguments);return d=g.shift(),b.string(d)&&g.length>0&&(1===g.length&&(b.array(g[0])||b.object(g[0]))&&(g=g[0]),a.each(g,function(a,b){d=d.replace(new RegExp("\\{"+b+"\\}","gi"),a+"")})),d})}(FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d,e){if("0.2.2"===b.version){b.obj={};var f=function(){};b.obj.create=function(a){if(!c.object(a))throw TypeError("Argument must be an object");f.prototype=a;var b=new f;return f.prototype=null,b},b.obj.extend=function(e,f,g){e=c.object(e)?e:{};var h=d.arg2arr(arguments);return h.shift(),a.each(h,function(a,c){b.obj.merge(e,c)}),e},b.obj.merge=function(a,d){a=c.hash(a)?a:{},d=c.hash(d)?d:{};for(var e in d)d.hasOwnProperty(e)&&(c.hash(d[e])?(a[e]=c.hash(a[e])?a[e]:{},b.obj.merge(a[e],d[e])):c.array(d[e])?a[e]=d[e].slice():a[e]=d[e]);return a},b.obj.mergeValid=function(d,e,f,g){if(!c.hash(f)||!c.hash(e))return d;e=c.hash(e)?e:{},g=c.hash(g)?g:{};var h,i,j;for(h in e)e.hasOwnProperty(h)&&c.fn(e[h])&&(i=c.array(g[h])?g[h]:c.string(g[h])?[g[h]]:[h],a.each(i,function(a,g){if(j=b.obj.prop(f,g),!c.undef(j))return e[h](j)?(b.obj.prop(d,h,j),!1):void 0}));return d},b.obj.prop=function(b,d,f){if(c.object(b)&&!c.empty(d)){var g,h;if(c.undef(f))return e.contains(d,".")?(g=d.split("."),h=g.length-1,a.each(g,function(a,d){if(a===h)f=b[d];else{if(!c.hash(b[d]))return!1;b=b[d]}})):c.undef(b[d])||(f=b[d]),f;e.contains(d,".")?(g=d.split("."),h=g.length-1,a.each(g,function(a,d){a===h?b[d]=f:b=c.hash(b[d])?b[d]:b[d]={}})):c.undef(b[d])||(b[d]=f)}}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c){if("0.2.2"===b.version){b.ready=function(a){function c(){try{a.call(window,b.$)}catch(a){console.error(a)}}(Function("/*@cc_on return true@*/")()?"complete"===document.readyState:"loading"!==document.readyState)?c():document.addEventListener("DOMContentLoaded",c,!1)},b.find=function(a,b,d){if(c.fn(b)){d=c.undef(d)?b:d;var e,f;if(c.array(a)){for(e=0,f=a.length;e<f;e++)if(b.call(d,a[e],e,a))return a[e]}else if(c.object(a)){var g=Object.keys(a);for(e=0,f=g.length;e<f;e++)if(b.call(d,a[g[e]],g[e],a))return a[g[e]]}}},b.each=function(a,b,d){if(c.fn(b)){d=c.undef(d)?b:d;var e,f;if(c.array(a))for(e=0,f=a.length;e<f&&!1!==b.call(d,a[e],e,a);e++);else if(c.object(a)){var g=Object.keys(a);for(e=0,f=g.length;e<f&&!1!==b.call(d,a[g[e]],g[e],a);e++);}}},b.inArray=function(a,b){return c.array(b)?b.indexOf(a):-1},b.versionCompare=function(a,b){function c(a){for(var b=a.split("."),c=[],d=0,e=b.length;d<e;d++)c[d]=parseInt(b[d]),isNaN(c[d])&&(c[d]=0);return c}if(!/[\d.]/.test(a)||!/[\d.]/.test(b))return NaN;for(var d=c(a),e=c(b);d.length<e.length;)d.push(0);for(;e.length<d.length;)e.push(0);for(var f=0;f<d.length;++f){if(e.length===f)return 1;if(d[f]!==e[f])return d[f]>e[f]?1:-1}return d.length!==e.length?-1:0};var d=0;b.uniqueId=function(a,b){var e=a.attr("id");return c.empty(e)&&(b=c.string(b)&&!c.empty(b)?b:"uid-",e=b+ ++d,a.attr("id",e).data("__uniqueId__",!0)),e},b.removeUniqueId=function(a){a.data("__uniqueId__")&&a.removeAttr("id").removeData("__uniqueId__")},b.selectify=function(a){if(c.empty(a))return null;if(c.hash(a)){var d,e={};for(var f in a)a.hasOwnProperty(f)&&(d=b.selectify(a[f]))&&(e[f]=d);return e}return c.string(a)||c.array(a)?(c.string(a)&&(a=[a]),a.map(function(a){return c.string(a)?"."+a.split(/\s/g).join("."):null}).join(",")):null},b.src=function(a,b,d,e,f,g,h){if(!c.string(a))return null;if(!c.string(b))return a;var i=b.replace(/(\s[\d.]+[whx]),/g,"$1 @,@ ").split(" @,@ "),j=i.map(function(a){return{url:/^\s*(\S*)/.exec(a)[1],w:parseFloat((/\S\s+(\d+)w/.exec(a)||[0,1/0])[1]),h:parseFloat((/\S\s+(\d+)h/.exec(a)||[0,1/0])[1]),x:parseFloat((/\S\s+([\d.]+)x/.exec(a)||[0,1])[1])}});if(!j.length)return a;j.unshift({url:a,w:j[0].w!==1/0&&j[0].h===1/0?d:1/0,h:j[0].h!==1/0&&j[0].w===1/0?e:1/0,x:1});var k=c.number(h)?h:window.devicePixelRatio||1,l={w:f*k,h:g*k,x:k},m=["w","h","x"];return m.forEach(function(a){var b=Math.max.apply(null,j.map(function(b){return b[a]}));j=j.filter(function(c){return c[a]>=l[a]||c[a]===b})}),m.forEach(function(a){var b=Math.min.apply(null,j.map(function(b){return b[a]}));j=j.filter(function(c){return c[a]===b})}),j[0].url},b.scrollParent=function(b,d,e){b=c.jq(b)?b:a(b),d=c.string(d)&&/^(x|y|xy|yx)$/i.test(d)?d:"xy";var f=a(!!b.length&&b[0].ownerDocument||document);if(e=c.jq(e)?e:f,!b.length)return e;var g=b.css("position"),h="absolute"===g,i=/(auto|scroll)/i,j=/x/i,k=/y/i,l=b.parentsUntil(e).filter(function(b,c){var e=a(this);if(h&&"static"===e.css("position"))return!1;var f=k.test(d)&&c.scrollHeight>c.clientHeight&&i.test(e.css("overflow-y")),g=j.test(d)&&c.scrollWidth>c.clientWidth&&i.test(e.css("overflow-x"));return f||g}).eq(0);return l.is("html")&&(l=f),"fixed"!==g&&l.length?l:e}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c){function d(a){return setTimeout(a,1e3/60)}function e(a){clearTimeout(a)}if("0.2.2"===b.version){b.animation={},b.animation.requestFrame=(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||d).bind(window),b.animation.cancelFrame=(window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame||e).bind(window);var f=document.createElement("div");b.animation.supported=function(a){var b=a.style;return c.string(b.animation)||c.string(b.WebkitAnimation)||c.string(b.MozAnimation)||c.string(b.msAnimation)||c.string(b.OAnimation)}(f),b.animation.end=function(a){var b=a.style;return c.string(b.animation)?"animationend":c.string(b.WebkitAnimation)?"webkitAnimationEnd":c.string(b.MozAnimation)?"animationend":c.string(b.msAnimation)?"msAnimationEnd":c.string(b.OAnimation)?"oAnimationEnd":null}(f),b.animation.duration=function(a,b){if(b=c.number(b)?b:0,!c.jq(a))return b;var d=a.css("animation-duration");if(/^([\d.]*)+?(ms|s)/i.test(d)){var e=d.split(","),f=0;return e.forEach(function(a){var b=a.match(/^\s*?([\d.]*)+?(ms|s)\s*?$/i),c=parseFloat(b[1]);"s"===b[2].toLowerCase()&&(c*=1e3),c>f&&(f=c)}),f}return b},b.animation.iterations=function(a,b){if(b=c.number(b)?b:1,!c.jq(a))return b;var d=a.css("animation-iteration-count");if(/^(([\d.]+)|infinite)/i.test(d)){var e=d.split(","),f=0;return e.forEach(function(a){var b=parseFloat(a);isNaN(b)&&(b=1/0),b>f&&(f=b)}),f}return b},b.animation.start=function(d,e,f,g){var h=a.Deferred(),i=h.promise();if(d=d.first(),b.animation.supported){d.prop("offsetTop");var j=d.data("animation_safety");if(c.hash(j)&&c.number(j.timer)&&(clearTimeout(j.timer),d.removeData("animation_safety").off(b.animation.end+".utils"),j.deferred.reject()),!c.number(g)){var k=b.animation.iterations(d);if(k===1/0)return h.reject("No timeout supplied with an infinite animation."),i;g=b.animation.duration(d)*k+50}j={deferred:h,timer:setTimeout(function(){d.removeData("animation_safety").off(b.animation.end+".utils"),h.resolve()},g)},d.data("animation_safety",j),d.on(b.animation.end+".utils",function(a){d.is(a.target)&&(clearTimeout(j.timer),d.removeData("animation_safety").off(b.animation.end+".utils"),h.resolve())})}return b.animation.requestFrame(function(){c.fn(e)?e.apply(d.get(0),[d]):d.toggleClass(e,f),b.animation.supported||h.resolve()}),i}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){if("0.2.2"===b.version){b.transition={};var e=document.createElement("div");b.transition.supported=function(a){var b=a.style;return c.string(b.transition)||c.string(b.WebkitTransition)||c.string(b.MozTransition)||c.string(b.msTransition)||c.string(b.OTransition)}(e),b.transition.end=function(a){var b=a.style;return c.string(b.transition)?"transitionend":c.string(b.WebkitTransition)?"webkitTransitionEnd":c.string(b.MozTransition)?"transitionend":c.string(b.msTransition)?"msTransitionEnd":c.string(b.OTransition)?"oTransitionEnd":null}(e),b.transition.duration=function(a,b){if(b=c.number(b)?b:0,!c.jq(a))return b;var d=a.css("transition-duration");if(/^([\d.]*)+?(ms|s)/i.test(d)){var e=d.split(","),f=0;return e.forEach(function(a){var b=a.match(/^\s*?([\d.]*)+?(ms|s)\s*?$/i),c=parseFloat(b[1]);"s"===b[2].toLowerCase()&&(c*=1e3),c>f&&(f=c)}),f}return b},b.transition.start=function(e,f,g,h){var i=a.Deferred(),j=i.promise();if(e=e.first(),b.transition.supported){e.prop("offsetTop");var k=e.data("transition_safety");c.hash(k)&&c.number(k.timer)&&(clearTimeout(k.timer),e.removeData("transition_safety").off(b.transition.end+".utils"),k.deferred.reject()),h=c.number(h)?h:b.transition.duration(e)+50,k={deferred:i,timer:setTimeout(function(){e.removeData("transition_safety").off(b.transition.end+".utils"),i.resolve()},h)},e.data("transition_safety",k),e.on(b.transition.end+".utils",function(a){e.is(a.target)&&(clearTimeout(k.timer),e.removeData("transition_safety").off(b.transition.end+".utils"),i.resolve())})}return d.requestFrame(function(){c.fn(f)?f.apply(e.get(0),[e]):e.toggleClass(f,g),b.transition.supported||i.resolve()}),j}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.animation),function(a,b,c,d,e){"0.2.2"===b.version&&(b.Class=function(){},b.Class.extend=function(a){function f(){if(!c.fn(this.construct))throw new SyntaxError('FooGallery.utils.Class objects must be constructed with the "new" keyword.');this.construct.apply(this,arguments)}a=c.hash(a)?a:{};var g=d.create(this.prototype);for(var h in a)a.hasOwnProperty(h)&&e.addOrOverride(g,h,a[h]);return g.construct=c.fn(g.construct)?g.construct:function(){},f.prototype=g,f.prototype.constructor=c.fn(g.__ctor__)?g.__ctor__:f,f.extend=b.Class.extend,f.override=b.Class.override,f.bases=b.Class.bases,f.__base__=this,f},
10
- b.Class.override=function(a,b){e.addOrOverride(this.prototype,a,b)},b.Class.__base__=null,b.Class.bases=function(){function a(b,d){return c.array(d)||(d=[]),c.fn(b)&&null!==b.__base__?(d.unshift(b.__base__),a(b.__base__,d)):d}return a(this,[])})}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj,FooGallery.utils.fn),function(a,b,c){"0.2.2"===a.version&&(a.Event=a.Class.extend({construct:function(c){if(b.empty(c))throw new SyntaxError("FooGallery.utils.Event objects must be supplied a `type`.");var d=this,e=a.Event.parse(c);d.type=e.type,d.namespace=e.namespace,d.defaultPrevented=!1,d.target=null},preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return this.defaultPrevented}}),a.Event.parse=function(a){a=b.string(a)&&!b.empty(a)?a:null;var d=c.contains(a,".");return{namespaced:d,type:d?c.startsWith(a,".")?null:c.until(a,"."):a,namespace:d?c.from(a,"."):null}},a.EventClass=a.Class.extend({construct:function(){this.events={}},destroy:function(){this.events={}},on:function(a,c,d){var e=this;return b.object(a)?(d=c,Object.keys(a).forEach(function(c){b.fn(a[c])&&c.split(" ").forEach(function(b){e.addListener(b,a[c],d)})})):b.string(a)&&b.fn(c)&&a.split(" ").forEach(function(a){e.addListener(a,c,d)}),e},addListener:function(c,d,e){if(!b.string(c)||/\s/.test(c)||!b.fn(d))return!1;var f=this,g=a.Event.parse(c);return e=b.undef(e)?f:e,b.array(f.events[g.type])||(f.events[g.type]=[]),!f.events[g.type].some(function(a){return a.namespace===g.namespace&&a.fn===d&&a.thisArg===e})&&(f.events[g.type].push({namespace:g.namespace,fn:d,thisArg:e}),!0)},off:function(a,c,d){var e=this;return b.object(a)?(d=c,Object.keys(a).forEach(function(b){b.split(" ").forEach(function(c){e.removeListener(c,a[b],d)})})):b.string(a)&&a.split(" ").forEach(function(a){e.removeListener(a,c,d)}),e},removeListener:function(c,d,e){if(!b.string(c)||/\s/.test(c))return!1;var f=this,g=a.Event.parse(c),h=[];return e=b.undef(e)?f:e,b.empty(g.type)?b.empty(g.namespace)||h.push.apply(h,Object.keys(f.events)):h.push(g.type),h.forEach(function(a){b.array(f.events[a])&&(f.events[a]=f.events[a].filter(function(a){return null!=d?!(a.namespace===g.namespace&&a.fn===d&&a.thisArg===e):null!=g.namespace&&a.namespace!==g.namespace}),0===f.events[a].length&&delete f.events[a])}),!0},trigger:function(c,d){d=b.array(d)?d:[];var e=this,f=[];return c instanceof a.Event?(f.push(c),e.emit(c,d)):b.string(c)&&c.split(" ").forEach(function(b){var c=new a.Event(b);f.push(c),e.emit(c,d)}),b.empty(f)?null:1===f.length?f[0]:f},emit:function(a,c){if(a instanceof FooGallery.utils.Event){var d=this;c=b.array(c)?c:[],null===a.target&&(a.target=d),b.array(d.events[a.type])&&d.events[a.type].forEach(function(b){null!=a.namespace&&b.namespace!==a.namespace||b.fn.apply(b.thisArg,[a].concat(c))}),b.array(d.events.__all__)&&d.events.__all__.forEach(function(b){b.fn.apply(b.thisArg,[a].concat(c))})}}}))}(FooGallery.utils,FooGallery.utils.is,FooGallery.utils.str),function(a,b,c){if("0.2.2"===b.version){b.Bounds=b.Class.extend({construct:function(){var a=this;a.top=0,a.right=0,a.bottom=0,a.left=0,a.width=0,a.height=0},inflate:function(a){var b=this;return c.number(a)&&(b.top-=a,b.right+=a,b.bottom+=a,b.left-=a,b.width+=2*a,b.height+=2*a),b},intersects:function(a){var b=this;return b.left<=a.right&&a.left<=b.right&&b.top<=a.bottom&&a.top<=b.bottom}});var d;b.getViewportBounds=function(c){d||(d=a(window));var e=new b.Bounds;return e.top=d.scrollTop(),e.left=d.scrollLeft(),e.width=d.width(),e.height=d.height(),e.right=e.left+e.width,e.bottom=e.top+e.height,e.inflate(c),e},b.getElementBounds=function(d){c.jq(d)||(d=a(d));var e=new b.Bounds;if(0!==d.length){var f=d.offset();e.top=f.top,e.left=f.left,e.width=d.width(),e.height=d.height()}return e.right=e.left+e.width,e.bottom=e.top+e.height,e}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d,e){"0.2.2"===b.version&&(b.Timer=b.EventClass.extend({construct:function(a){this._super(),this.interval=c.number(a)?a:1e3,this.isRunning=!1,this.isPaused=!1,this.canResume=!1,this.canRestart=!1,this.__timeout=null,this.__decrement=!1,this.__time=0,this.__remaining=0,this.__current=0,this.__finish=0,this.__restart=[]},__reset:function(){clearTimeout(this.__timeout),this.__timeout=null,this.__decrement=!1,this.__time=0,this.__remaining=0,this.__current=0,this.__finish=0,this.isRunning=!1,this.isPaused=!1,this.canResume=!1},__eventArgs:function(a){return[this.__current,this.__time,this.__decrement].concat(d.arg2arr(arguments))},__tick:function(){var a=this;a.trigger("tick",a.__eventArgs()),a.__current===a.__finish?(a.trigger("complete",a.__eventArgs()),a.__reset()):(a.__decrement?a.__current--:a.__current++,a.__remaining--,a.canResume=a.__remaining>0,a.__timeout=setTimeout(function(){a.__tick()},a.interval))},start:function(a,b){var d=this;d.isRunning||(b=!!c.boolean(b)&&b,d.__restart=[a,b],d.__decrement=b,d.__time=a,d.__remaining=a,d.__current=b?a:0,d.__finish=b?0:a,d.canRestart=!0,d.isRunning=!0,d.isPaused=!1,d.trigger("start",d.__eventArgs()),d.__tick())},countdown:function(a){this.start(a,!0)},countup:function(a){this.start(a,!1)},restart:function(){this.stop(),this.canRestart&&this.start.apply(this,this.__restart)},stop:function(){(this.isRunning||this.isPaused)&&(this.__reset(),this.trigger("stop",this.__eventArgs()))},pause:function(){var a=this;return null!=a.__timeout&&(clearTimeout(a.__timeout),a.__timeout=null),a.isRunning&&(a.isRunning=!1,a.isPaused=!0,a.trigger("pause",a.__eventArgs())),a.__remaining},resume:function(){var a=this;a.canResume&&(a.isRunning=!0,a.isPaused=!1,a.trigger("resume",a.__eventArgs()),a.__tick())},reset:function(){this.__reset(),this.trigger("reset",this.__eventArgs())}}))}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d){"0.2.2"===b.version&&(b.Factory=b.Class.extend({construct:function(){this.registered={}},contains:function(a){return!c.undef(this.registered[a])},load:function(b,e,f){var g,h,i=this,j=d.arg2arr(arguments),k=[],l=[];b=j.shift()||{};for(g in i.registered)if(i.registered.hasOwnProperty(g)){var m=i.registered[g];b.hasOwnProperty(g)&&(h=b[g],c.string(h)&&(h=d.fetch(b[g])),c.fn(h)&&(m={name:g,klass:h,priority:i.registered[g].priority})),k.push(m)}for(g in b)b.hasOwnProperty(g)&&!i.registered.hasOwnProperty(g)&&(h=b[g],c.string(h)&&(h=d.fetch(b[g])),c.fn(h)&&k.push({name:g,klass:h,priority:0}));return k.sort(function(a,b){return b.priority-a.priority}),a.each(k,function(a,b){c.fn(b.klass)&&l.push(d.apply(b.klass,j))}),l},make:function(a,b,e){var f,g=this,h=d.arg2arr(arguments);return a=h.shift(),f=g.registered[a],c.hash(f)&&c.fn(f.klass)?d.apply(f.klass,h):null},names:function(b){b=!!c.boolean(b)&&b;var d,e=[];if(b){var f=[];for(d in this.registered)this.registered.hasOwnProperty(d)&&f.push(this.registered[d]);f.sort(function(a,b){return b.priority-a.priority}),a.each(f,function(a,b){e.push(b.name)})}else for(d in this.registered)this.registered.hasOwnProperty(d)&&e.push(d);return e},register:function(a,b,d){if(!c.string(a)||c.empty(a)||!c.fn(b))return!1;d=c.number(d)?d:0;var e=this.registered[a];return this.registered[a]={name:a,klass:b,priority:c.undef(e)?d:e.priority},!0}}))}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c){"0.2.2"===b.version&&(b.FullscreenAPI=b.EventClass.extend({construct:function(){this._super(),this.apis={w3:{enabled:"fullscreenEnabled",element:"fullscreenElement",request:"requestFullscreen",exit:"exitFullscreen",events:{change:"fullscreenchange",error:"fullscreenerror"}},webkit:{enabled:"webkitFullscreenEnabled",element:"webkitCurrentFullScreenElement",request:"webkitRequestFullscreen",exit:"webkitExitFullscreen",events:{change:"webkitfullscreenchange",error:"webkitfullscreenerror"}},moz:{enabled:"mozFullScreenEnabled",element:"mozFullScreenElement",request:"mozRequestFullScreen",exit:"mozCancelFullScreen",events:{change:"mozfullscreenchange",error:"mozfullscreenerror"}},ms:{enabled:"msFullscreenEnabled",element:"msFullscreenElement",request:"msRequestFullscreen",exit:"msExitFullscreen",events:{change:"MSFullscreenChange",error:"MSFullscreenError"}}},this.api=this.getAPI(),this.supported=null!=this.api,this.__listen()},destroy:function(){return this.__stopListening(),this._super()},getAPI:function(){for(var a in this.apis)if(this.apis.hasOwnProperty(a)&&this.apis[a].enabled in document)return this.apis[a];return null},element:function(){return this.supported?document[this.api.element]:null},request:function(b){if(this.supported&&b[this.api.request]){var d=b[this.api.request]();return d||a.Deferred(this.__resolver(this.api.request)).promise()}return c.rejected},exit:function(){if(this.supported&&this.element()){var b=document[this.api.exit]();return b||a.Deferred(this.__resolver(this.api.exit)).promise()}return c.rejected},toggle:function(a){return this.element()?this.exit():this.request(a)},__listen:function(){var b=this;b.supported&&a(document).on(b.api.events.change+".utils",function(){b.trigger("change")}).on(b.api.events.error+".utils",function(){b.trigger("error")})},__stopListening:function(){var b=this;b.supported&&a(document).off(b.api.events.change+".utils").off(b.api.events.error+".utils")},__resolver:function(b){var c=this;return function(d){function e(){d.resolve(),a(document).off(c.api.events.change,e).off(c.api.events.error,f)}function f(){d.reject(new TypeError),a(document).off(c.api.events.change,e).off(c.api.events.error,f)}if(b===c.api.exit&&c.element())return void setTimeout(function(){d.reject(new TypeError)},1);a(document).on(c.api.events.change,e).on(c.api.events.error,f)}}}))}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.fn),function(a,b,c,d,e){b.EMPTY_IMAGE="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",b.DATA_TEMPLATE="__FooGallery__",b.DATA_ITEM="__FooGalleryItem__",b.get=function(c){return a(c).data(b.DATA_TEMPLATE)},b.init=function(c,f){if(f=d.jq(f)?f:a(f),f.length>0){var g=f.data(b.DATA_TEMPLATE);if(g instanceof b.Template)return g.destroy(!0).then(function(){var a=b.template.make(c,f);return a instanceof b.Template?a.initialize():e.rejected})}var h=b.template.make(c,f);return h instanceof b.Template?h.initialize():e.rejected},b.initAll=function(c){return e.when(a(".foogallery").map(function(a,d){return b.init(c,d)}).get())},a.fn.foogallery=function(c,e){return e=d.fn(e)?e:a.noop,this.each(function(f,g){if(d.string(c)){var h=a.data(g,b.DATA_TEMPLATE);if(h instanceof b.Template)switch(c){case"layout":return void h.layout();case"destroy":return void h.destroy()}}else b.init(c,g).then(e)})},b.isCached=function(a){var b=new Image;b.src=a;var c=b.complete;return b.src="",b=null,c},b.supportedExifProperties=["camera","aperture","created_timestamp","shutter_speed","focal_length","iso","orientation"],d.exif=function(a){if(d.object(a)){var c=Object.keys(a);return c.length>0&&c.some(function(c){return-1!==b.supportedExifProperties.indexOf(c)&&!d.empty(a[c])})}return!1}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c,d,e){var f="__FooGallerySwipe__",g="ontouchstart"in window,h=window.navigator.msPointerEnabled&&!window.navigator.pointerEnabled&&!g,i=(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&!g,j=g||i;b.Swipe=c.Class.extend({construct:function(b,c){var d=this,f=".fgswipe";d.$el=a(b),d.opt=e.extend({threshold:20,allowPageScroll:!1,swipe:a.noop,data:{}},c),d.active=!1,d.startPoint=null,d.endPoint=null,d.events={start:(j?i?h?"MSPointerDown":"pointerdown":"touchstart":"mousedown")+f,move:(j?i?h?"MSPointerMove":"pointermove":"touchmove":"mousemove")+f,end:(j?i?h?"MSPointerUp":"pointerup":"touchend":"mouseup")+f,leave:(j?i?"mouseleave":null:"mouseleave")+f}},init:function(){var a=this;a.$el.on(a.events.start,{self:a},a.onStart),a.$el.on(a.events.move,{self:a},a.onMove),a.$el.on(a.events.end,{self:a},a.onEnd),d.string(a.events.leave)&&a.$el.on(a.events.leave,{self:a},a.onEnd),a.$el.data(f,a)},destroy:function(){var a=this;a.$el.off(a.events.start,a.onStart),a.$el.off(a.events.move,a.onMove),a.$el.off(a.events.end,a.onEnd),d.string(a.events.leave)&&a.$el.off(a.events.leave,a.onEnd),a.$el.removeData(f)},getAngle:function(a,b){var c=Math.atan2(a.x-b.x,a.y-b.y),d=Math.round(180*c/Math.PI);return 360-(d<0?360-Math.abs(d):d)},getDistance:function(a,b){var c=b.x-a.x,d=b.y-a.y;return c*=c,d*=d,Math.sqrt(c+d)},getDirection:function(a,b){var c=this,d=c.getAngle(a,b);return d>337.5||d<=22.5?"N":d>22.5&&d<=67.5?"NE":d>67.5&&d<=112.5?"E":d>112.5&&d<=157.5?"SE":d>157.5&&d<=202.5?"S":d>202.5&&d<=247.5?"SW":d>247.5&&d<=292.5?"W":d>292.5&&d<=337.5?"NW":"NONE"},getPoint:function(a){var b;return j&&!d.empty(b=a.originalEvent.touches||a.touches)?{x:b[0].pageX,y:b[0].pageY}:d.number(a.pageX)&&d.number(a.pageY)?{x:a.pageX,y:a.pageY}:null},getOffset:function(a){var b=this,c=b.$el.offset();return{left:a.x-c.left,top:a.y-c.top}},onStart:function(a){var b=a.data.self,c=b.getPoint(a);d.empty(c)||(b.active=!0,b.startPoint=b.endPoint=c)},onMove:function(a){var b=a.data.self,e=b.getPoint(a);if(b.active&&!d.empty(e))if(b.endPoint=e,b.opt.allowPageScroll){if(d.hash(b.opt.allowPageScroll)){var f=b.getDirection(b.startPoint,b.endPoint);b.opt.allowPageScroll.x||-1===c.inArray(f,["NE","E","SE","NW","W","SW"])||a.preventDefault(),b.opt.allowPageScroll.y||-1===c.inArray(f,["NW","N","NE","SW","S","SE"])||a.preventDefault()}}else a.preventDefault()},onEnd:function(a){var b=a.data.self;if(b.active){b.active=!1;var c={startPoint:b.startPoint,endPoint:b.endPoint,startOffset:b.getOffset(b.startPoint),endOffset:b.getOffset(b.endPoint),angle:b.getAngle(b.startPoint,b.endPoint),distance:b.getDistance(b.startPoint,b.endPoint),direction:b.getDirection(b.startPoint,b.endPoint)};if(b.opt.threshold>0&&c.distance<b.opt.threshold)return;b.opt.swipe.apply(this,[c,b.opt.data]),b.startPoint=null,b.endPoint=null}}}),a.fn.fgswipe=function(c){return this.each(function(){var e=a(this),g=e.data(f);if(g instanceof b.Swipe){if(d.string(c)&&d.fn(g[c]))return void g[c]();g.destroy()}d.hash(c)&&(g=new b.Swipe(this,c),g.init())})}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj),function(a,b,c,d,e,f){b.TemplateFactory=c.Factory.extend({construct:function(){this.registered={}},register:function(a,b,c,e,f,g){var h=this,i=h._super(a,b,g);if(i){var j=h.registered;j[a].opt=d.hash(c)?c:{},j[a].cls=d.hash(e)?e:{},j[a].il8n=d.hash(f)?f:{}}return i},make:function(b,c){c=d.jq(c)?c:a(c),b=f.extend({},b,c.data("foogallery"));var e=this,g=e.type(b,c);return e.contains(g)?(b=e.options(g,b),e._super(g,b,c)):null},type:function(b,e){e=d.jq(e)?e:a(e);var f=this,g=d.hash(b)&&d.hash(b)&&d.string(b.type)&&f.contains(b.type)?b.type:null;if(null===g&&e.length>0)for(var h=f.registered,i=f.names(!0),j=0,k=i.length;j<k;j++)if(h.hasOwnProperty(i[j])&&"core"!==i[j]){var l=i[j],m=h[l].cls;if(d.string(m.container)){var n=c.selectify(m.container);if(e.is(n)){g=i[j];break}}}return g},configure:function(a,b,c,d){var e=this;if(e.contains(a)){var g=e.registered;f.extend(g[a].opt,b),f.extend(g[a].cls,c),f.extend(g[a].il8n,d)}},options:function(a,c){c=f.extend({type:a},c);var e=this,g=e.registered,h=g.core.opt,i=g.core.cls,j=g.core.il8n;return d.hash(c.cls)||(c.cls={}),d.hash(c.il8n)||(c.il8n={}),d.undef(b.filtering)||(c=b.filtering.merge(c)),d.undef(b.paging)||(c=b.paging.merge(c)),"core"!==a&&e.contains(a)?(c=f.extend({},h,g[a].opt,c),c.cls=f.extend({},i,g[a].cls,c.cls),c.il8n=f.extend({},j,g[a].il8n,c.il8n)):(c=f.extend({},h,c),c.cls=f.extend({},i,c.cls),c.il8n=f.extend({},j,c.il8n)),c}}),b.template=new b.TemplateFactory}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e){a.PagingFactory=b.Factory.extend({construct:function(){this.registered={}},register:function(a,b,d,e,f,g,h){var i=this,j=i._super(a,b,h);if(j){var k=i.registered;k[a].ctrl=c.fn(d)?d:null,k[a].opt=c.hash(e)?e:{},k[a].cls=c.hash(f)?f:{},k[a].il8n=c.hash(g)?g:{}}return j},type:function(a){var b,d=this;return c.hash(a)&&c.hash(b=a.paging)&&c.string(b.type)&&d.contains(b.type)?b.type:null},merge:function(a){a=e.extend({},a);var b=this,d=b.type(a),f=b.registered,g=f.default.opt,h=f.default.cls,i=f.default.il8n,j=c.hash(a.paging)?a.paging:{},k=c.hash(a.cls)&&c.hash(a.cls.paging)?e.extend({},a.cls.paging):{},l=c.hash(a.il8n)&&c.hash(a.il8n.paging)?e.extend({},a.il8n.paging):{};return c.hash(a.cls)||(a.cls={}),c.hash(a.il8n)||(a.il8n={}),"default"!==d&&b.contains(d)?(a.paging=e.extend({},g,f[d].opt,j,{type:d}),a.cls=e.extend(a.cls,{paging:h},{paging:f[d].cls},{paging:k}),a.il8n=e.extend(a.il8n,{paging:i},{paging:f[d].il8n},{paging:l})):(a.paging=e.extend({},g,j,{type:d}),a.cls=e.extend(a.cls,{paging:h},{paging:k}),a.il8n=e.extend(a.il8n,{paging:i},{paging:l})),a},configure:function(a,b,c,d){var f=this;if(f.contains(a)){var g=f.registered;e.extend(g[a].opt,b),e.extend(g[a].cls,c),e.extend(g[a].il8n,d)}},hasCtrl:function(a){var b=this,d=b.registered[a];return c.hash(d)&&c.fn(d.ctrl)},makeCtrl:function(a,b,d,e){var f=this,g=f.registered[a];return c.hash(g)&&c.fn(g.ctrl)?new g.ctrl(b,d,e):null}}),a.paging=new a.PagingFactory}(FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e,f){var g=0;b.Template=c.EventClass.extend({construct:function(e,f){var h=this;h._super(),h.namespace=".foogallery-"+ ++g,h.$el=d.jq(f)?f:a(f),h.$scrollParent=null,h.opt=e,h.template=e.template,h.id=h.$el.prop("id")||e.id,h.cls=e.cls,h.il8n=e.il8n,h.sel=c.selectify(h.cls),h.items=b.components.make("items",h),h.pages=d.undef(b.paging)?null:b.paging.make(e.paging.type,h),h.filter=d.undef(b.filtering)?null:b.filtering.make(e.filtering.type,h),h.state=b.components.make("state",h),h._initialize=null,h._checkTimeout=null,h._layoutTimeout=null,h._layoutWidths=[],h.initializing=!1,h.initialized=!1,h.destroying=!1,h.destroyed=!1,h._undo={classes:"",style:"",create:!1,children:!1},h.robserver=new ResizeObserver(function(){h.$el.is(":visible")&&h.layout()})},initialize:function(b){var c=this;return d.promise(c._initialize)?c._initialize:c._initialize=a.Deferred(function(a){c.preInit(b)?c.init().then(function(){c.postInit()?c.firstLoad().then(function(){c.ready(),a.resolve(c)}).fail(a.reject):a.reject("post-init failed")}).fail(a.reject):a.reject("pre-init failed")}).fail(function(a){console.log("initialize failed",c,a),c.destroy()}).promise()},preInit:function(e){var f=this;if(f.destroying)return!1;if(e=d.jq(e)?e:a(e),f.initializing=!0,0===e.length&&0===f.$el.parent().length)return!1;0===f.$el.length&&(f.$el=f.create(),f._undo.create=!0),e.length>0&&f.$el.appendTo(e);var g;d.empty(f.opt.scrollParent)||0===(g=a(f.opt.scrollParent)).length?f.$scrollParent=a(document):f.$scrollParent=g.is("html")?a(document):g,f.$el.data(b.DATA_TEMPLATE,f),d.empty(f.opt.on)||f.$el.on(f.opt.on),f._undo.classes=f.$el.attr("class"),f._undo.style=f.$el.attr("style"),f.$el.is(f.sel.container)||f.$el.addClass(f.cls.container);var h=c.selectify(f.opt.classes);return null==h||f.$el.is(h)||f.$el.addClass(f.opt.classes),f.robserver.observe(f.$el.get(0)),0===f.$el.children().not(f.sel.item.elem).length&&(f.$el.append(f.createChildren()),f._undo.children=!0),!f.raise("pre-init").isDefaultPrevented()},init:function(){var a=this;return a.raise("init").isDefaultPrevented()?e.rejectWith("init default prevented"):a.items.fetch()},postInit:function(){var b=this;return!b.destroying&&(!b.raise("post-init").isDefaultPrevented()&&(b.state.init(),b.$scrollParent.on("scroll"+b.namespace,{self:b},e.throttle(function(){b.loadAvailable()},50)),a(window).on("popstate"+b.namespace,{self:b},b.onWindowPopState),!0))},firstLoad:function(){var a=this;return a.destroying?e.rejected:(a.raise("first-load"),a.loadAvailable())},ready:function(){var a=this;return!a.destroying&&(a.initializing=!1,a.initialized=!0,a._check(1e3),a.raise("ready"),!0)},create:function(){var b=this;return a("<div/>",{id:b.id,class:b.cls.container}).addClass(b.opt.classes)},createChildren:function(){return a()},destroy:function(b){var c=this,f=c._super.bind(c);return c.destroyed?e.resolved:(c.destroying=!0,a.Deferred(function(a){c.initializing&&d.promise(c._initialize)?c._initialize.always(function(){c.destroying=!1,c.doDestroy(b),a.resolve()}):(c.destroying=!1,c.doDestroy(b),a.resolve())}).then(function(){f()}).promise())},doDestroy:function(c){var e=this;e.destroyed||(e.raise("destroy"),e.robserver.disconnect(),e._checkTimeout&&clearTimeout(e._checkTimeout),e.$scrollParent.off(e.namespace),a(window).off(e.namespace),e.state.destroy(c),e.filter&&e.filter.destroy(),e.pages&&e.pages.destroy(),e.items.destroy(),d.empty(e.opt.on)||e.$el.off(e.opt.on),e.raise("destroyed"),e.$el.removeData(b.DATA_TEMPLATE),d.empty(e._undo.classes)?e.$el.removeAttr("class"):e.$el.attr("class",e._undo.classes),d.empty(e._undo.style)?e.$el.removeAttr("style"):e.$el.attr("style",e._undo.style),e._undo.children&&e.destroyChildren(),e._undo.create&&e.$el.remove(),e.$el=e.state=e.items=e.pages=null,e.destroyed=!0,e.initializing=!1,e.initialized=!1)},destroyChildren:function(){},getAvailable:function(){return this.pages?this.pages.available():this.items.available()},loadAvailable:function(){return this.items.load(this.getAvailable())},getItems:function(){return this.pages?this.pages.items():this.items.available()},_check:function(a){a=d.number(a)?a:0;var b=this;return b._checkTimeout&&clearTimeout(b._checkTimeout),b._checkTimeout=setTimeout(function(){b._checkTimeout=null,!b.initialized||b.destroying&&b.destroyed||b.loadAvailable()},a)},raise:function(b,c){if(this.destroying||this.destroyed||!d.string(b)||d.empty(b))return null;c=d.array(c)?c:[];var e=this,g=b.split(".")[0],h=f.camel("on-"+g),i=a.Event(g+".foogallery");return c.unshift(e),e.trigger(g,c).defaultPrevented&&i.preventDefault(),e.$el.trigger(i,c),d.fn(e[h])&&(c.unshift(i),e[h].apply(e.$el.get(0),c)),i},layout:function(){var a=this,b=a.getContainerWidth();null===a._initialize||a._checkWidth(b)||a.raise("layout",[b])},_checkWidth:function(a){var b,c=this;return(b=-1!==c._layoutWidths.indexOf(a))||(c._layoutWidths.unshift(a),c._layoutWidths.splice(2,c._layoutWidths.length-2),null!=c._layoutTimeout&&clearTimeout(c._layoutTimeout),c._layoutTimeout=setTimeout(function(){c._layoutWidths.splice(0,c._layoutWidths.length)},100)),b},getContainerWidth:function(){var a=this;return a.$el.is(":visible")?a.$el.width():a.$el.parents(":visible:first").innerWidth()},getCSSClass:function(a,b){b=d.empty(b)?"":b;var c=a instanceof RegExp?a:d.string(a)&&this.opt.regex.hasOwnProperty(a)?this.opt.regex[a]:null,e=this.$el.prop("className")||"",f=null!=c?e.match(c):null;return null!=f&&f.length>=2?f[1]:b},onWindowPopState:function(a){var b=a.data.self,c=a.originalEvent.state;d.empty(c)||c.id!==b.id||(b.state.set(c),b.loadAvailable())}}),b.template.register("core",b.Template,{id:null,type:"core",classes:"",on:{},lazy:!0,viewport:200,items:[],fixLayout:!0,scrollParent:null,delay:0,throttle:50,timeout:6e4,srcset:"data-srcset-fg",src:"data-src-fg",template:{},regex:{theme:/(?:\s|^)(fg-(?:light|dark|custom))(?:\s|$)/,loadingIcon:/(?:\s|^)(fg-loading-(?:default|bars|dots|partial|pulse|trail))(?:\s|$)/,hoverIcon:/(?:\s|^)(fg-hover-(?:zoom|zoom2|zoom3|plus|circle-plus|eye|external|tint))(?:\s|$)/,videoIcon:/(?:\s|^)(fg-video-(?:default|1|2|3|4))(?:\s|$)/,hoverColor:/(?:\s|^)(fg-hover-(?:colorize|grayscale))(?:\s|$)/,hoverScale:/(?:\s|^)(fg-hover-scale)(?:\s|$)/,stickyVideoIcon:/(?:\s|^)(fg-video-sticky)(?:\s|$)/,insetShadow:/(?:\s|^)(fg-shadow-inset-(?:small|medium|large))(?:\s|$)/,filter:/(?:\s|^)(fg-filter-(?:1977|amaro|brannan|clarendon|earlybird|lofi|poprocket|reyes|toaster|walden|xpro2|xtreme))(?:\s|$)/}},{container:"foogallery"},{},-100)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c){a.Component=b.Class.extend({construct:function(a){this.tmpl=a},destroy:function(){this.tmpl=null}}),a.EventComponent=b.EventClass.extend({construct:function(a,b){this._super(a),this.tmpl=a,this.tmplEventPrefix=b},destroy:function(){this._super(),this.tmpl=null},trigger:function(a,d){var e,f,g=this,h=g._super(a,d);return null!=g.tmpl&&(h instanceof b.Event&&!h.isDefaultPrevented()?(e=null!=h.namespace?[h.type,h.namespace].join("."):h.type,(f=g.tmpl.raise(g.tmplEventPrefix+e,d))&&f.isDefaultPrevented()&&h.preventDefault()):c.array(h)&&h.forEach(function(a){a.isDefaultPrevented()||(e=null!=a.namespace?[a.type,a.namespace].join("."):a.type,(f=g.tmpl.raise(g.tmplEventPrefix+e,d))&&f.isDefaultPrevented()&&a.preventDefault())})),c.empty(h)?null:1===h.length?h[0]:h}}),a.components=new b.Factory}(FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d,e,f){b.State=b.Component.extend({construct:function(a){var b=this;b._super(a),b.apiEnabled=!!window.history&&!!history.replaceState,b.opt=b.tmpl.opt.state,b.enabled=b.opt.enabled,b.current={filter:[],page:0,item:null},b.pushOrReplace=b.isPushOrReplace(b.opt.pushOrReplace)?b.opt.pushOrReplace:"replace",b.defaultMask="foogallery-gallery-{id}";var c=e.escapeRegExp(b.tmpl.id),d=e.escapeRegExp(b.getMasked()),f=e.escapeRegExp(b.opt.values),g=e.escapeRegExp(b.opt.pair);b.regex={exists:new RegExp("^#"+c+"\\"+f+".+?"),masked:new RegExp("^#"+d+"\\"+f+".+?"),values:new RegExp("(\\w+)"+g+"([^"+f+"]+)","g")}},destroy:function(a){var b=this;a||b.clear(),b.opt=b.regex={},b._super()},init:function(){this.set(this.initial())},getIdNumber:function(){return this.tmpl.id.match(/\d+/g)[0]},getMasked:function(){var a=this,b=e.contains(a.opt.mask,"{id}")?a.opt.mask:a.defaultMask;return e.format(b,{id:a.getIdNumber()})},isPushOrReplace:function(a){return-1!==c.inArray(a,["push","replace"])},exists:function(){return this.regex.values.lastIndex=0,(this.regex.exists.test(location.hash)||this.regex.masked.test(location.hash))&&this.regex.values.test(location.hash)},parse:function(){var b=this,c=b.tmpl,d={};if(b.exists())if(b.enabled){d.id=b.tmpl.id,b.regex.values.lastIndex=0;var e=location.hash.match(b.regex.values);a.each(e,function(a,e){var f,g=e.split(b.opt.pair);if(2===g.length)switch(g[0]){case b.opt.itemKey:f=c.items.fromHash(g[1]),null!==f&&(d.item=f);break;case b.opt.pageKey:c.pages&&null!==(f=c.pages.fromHash(g[1]))&&(d.page=f);break;case b.opt.filterKey:c.filter&&null!==(f=c.filter.fromHash(g[1]))&&(d.filter=f)}})}else b.apiEnabled?history.replaceState(null,"",location.pathname+location.search):location.hash="#";return d},hashify:function(a){var b=this,c=b.tmpl;if(d.hash(a)){var e=[],f=c.items.toHash(a.item);return null!==f&&e.push(b.opt.itemKey+b.opt.pair+f),c.filter&&null!==(f=c.filter.toHash(a.filter))&&e.push(b.opt.filterKey+b.opt.pair+f),c.pages&&null!==(f=c.pages.toHash(a.page))&&e.push(b.opt.pageKey+b.opt.pair+f),e.length>0&&e.unshift("#"+b.getMasked()),e.join(b.opt.values)}return""},replace:function(a){var c=this;if(c.enabled&&c.apiEnabled){a.id=c.tmpl.id;var e=c.hashify(a),g=d.empty(e),h=f.extend({},a,{item:a.item instanceof b.Item?a.item.id:a.item});history.replaceState(g?null:h,"",g?location.pathname+location.search:e)}},push:function(a){var c=this;if(c.enabled&&c.apiEnabled){a.id=c.tmpl.id;var e=c.hashify(a),g=d.empty(e),h=f.extend({},a,{item:a.item instanceof b.Item?a.item.id:a.item});history.pushState(g?null:h,"",g?location.pathname+location.search:e)}},update:function(a,b){var c=this;c.enabled&&c.apiEnabled&&(b=c.isPushOrReplace(b)?b:c.pushOrReplace,c[b](a))},clear:function(){this.exists()&&this.replace({})},initial:function(){var a=this,b=a.parse();return d.empty(b)?a.get():f.extend({filter:[],page:1,item:null},b)},get:function(a){var c,d=this,e=d.tmpl,g={};return a instanceof b.Item&&(g.item=a),e.filter&&null!==(c=e.filter.getState())&&(g.filter=c),e.pages&&null!==(c=e.pages.getState())&&(g.page=c),f.extend({filter:[],page:1,item:null},g)},set:function(a){var b=this,c=b.tmpl;if(d.hash(a)){var e=f.extend({filter:[],page:1,item:null},a);c.items.reset();c.raise("before-state",[e]).isDefaultPrevented()||(c.filter&&c.filter.setState(e),c.pages?c.pages.setState(e):(c.items.detach(c.items.all()),c.items.create(c.items.available(),!0)),e.item&&(b.opt.scrollTo&&e.item.scrollTo(),d.empty(a.item)||(a.item=null,b.replace(a))),b.current=e,c.raise("after-state",[e]))}}}),b.template.configure("core",{state:{enabled:!1,scrollTo:!0,pushOrReplace:"replace",mask:"foogallery-gallery-{id}",values:"/",pair:":",array:"+",arraySeparator:",",itemKey:"i",filterKey:"f",pageKey:"p"}}),b.components.register("state",b.State)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.str,FooGallery.utils.obj),function(a,b,c,d,e,f){b.Items=b.Component.extend({construct:function(a){var b=this;b.ALLOW_CREATE=!0,b.ALLOW_APPEND=!0,b.ALLOW_LOAD=!0,b._super(a),b.maps={},b._fetched=null,b._arr=[],b._available=[];var d=b.tmpl.cls.item.caption;b.tmpl.sel.item.caption.all=c.selectify([d.elem,d.inner,d.title,d.description])},fromHash:function(a){return this.get(a)},toHash:function(a){return a instanceof b.Item?a.id:null},destroy:function(){var b=this,c=b.all(),d=[];c.length>0&&(b.tmpl.raise("destroy-items",[c]),d=a.map(c,function(a){return a.destroy()?a:null}),d.length>0&&b.tmpl.raise("destroyed-items",[d])),b.maps={},b._fetched=null,b._arr=[],b._available=[],b._super()},fetch:function(b){var c=this;if(!b&&d.promise(c._fetched))return c._fetched;var e=c.tmpl,f=e.sel,g=e.opt.items,h=a.Deferred(),i=c.make(e.$el.find(f.item.elem));return d.empty(g)?(i.push.apply(i,c.make(window[e.id+"-items"])),h.resolve(i)):d.array(g)?(i.push.apply(i,c.make(g)),h.resolve(i)):d.string(g)?a.get(g).then(function(a){i.push.apply(i,c.make(a)),h.resolve(i)},function(a,b,c){console.log("FooGallery: GET items error.",g,a,b,c),h.resolve(i)}):h.resolve(i),h.then(function(a){c.setAll(a)}),c._fetched=h.promise()},toJSON:function(a){return(a?this.all():this.available()).map(function(a){return a.toJSON()})},all:function(){return this._arr.slice()},count:function(a){return a?this.all().length:this.available().length},available:function(a){return d.fn(a)?this._available.filter(a,this):this._available.slice()},get:function(a){var b=d.number(a)?"index":"id";return this.maps[b][a]?this.maps[b][a]:null},setAll:function(a){this._arr=d.array(a)?a:[],this.maps=this.createMaps(this._arr),this._available=this.all()},setAvailable:function(a){this.maps=this.createMaps(this._arr),this._available=d.array(a)?a:[]},reset:function(){this.setAvailable(this.all())},find:function(a,b){if(b=d.fn(b)?b:function(){return!0},d.array(a))for(var c=0,e=a.length;c<e;c++)if(!0===b.call(this,a[c]))return a[c];return null},first:function(a){return this.find(this._available,a)},last:function(a){return this.find(this._available.slice().reverse(),a)},next:function(a,c,e){if(!(a instanceof b.Item))return null;e=!!d.boolean(e)&&e;var f=this._available.slice(),g=f.indexOf(a);if(-1!==g){var h=f.slice(0,g);return f=f.slice(g+1),e&&(f=f.concat(h)),this.find(f,c)}return null},prev:function(a,c,e){if(!(a instanceof b.Item))return null;e=!!d.boolean(e)&&e;var f=this._available.slice().reverse(),g=f.indexOf(a);if(-1!==g){var h=f.slice(0,g);return f=f.slice(g+1),e&&(f=f.concat(h)),this.find(f,c)}return null},createMaps:function(b){b=d.array(b)?b:[];var c={id:{},index:{}};return a.each(b,function(a,b){d.empty(b.id)&&(b.id=""+(a+1)),b.index=a,c.id[b.id]=b,c.index[b.index]=b}),c},loadable:function(b){var e,f=this,g=f.tmpl.opt;return g.lazy&&(e=c.getViewportBounds(g.viewport)),f.ALLOW_LOAD&&d.array(b)?a.map(b,function(a){return a.isCreated&&a.isAttached&&!a.isLoading&&!a.isLoaded&&!a.isError&&(!g.lazy||g.lazy&&a.intersects(e))?a:null}):[]},creatable:function(c){return this.ALLOW_CREATE&&d.array(c)?a.map(c,function(a){return a instanceof b.Item&&!a.isCreated?a:null}):[]},appendable:function(c){return this.ALLOW_APPEND&&d.array(c)?a.map(c,function(a){return a instanceof b.Item&&a.isCreated&&!a.isAttached?a:null}):[]},
11
- detachable:function(c){return d.array(c)?a.map(c,function(a){return a instanceof b.Item&&a.isCreated&&a.isAttached?a:null}):[]},jquerify:function(b){return a(a.map(b,function(a){return a.$el.get()}))},make:function(c){var e=this,g=[];if(d.jq(c)||d.array(c)){var h=[],i=a.makeArray(c);if(0===i.length)return g;e.tmpl.raise("make-items",[i]).isDefaultPrevented()||(g=a.map(i,function(a){var c=e.type(a),g=f.extend(d.hash(a)?a:{},{type:c}),i=b.components.make(c,e.tmpl,g);return d.element(a)?i.parse(a)?(h.push(i),e.ALLOW_APPEND||i.detach(),i):null:i})),g.length>0&&e.tmpl.raise("made-items",[g]),h.length>0&&e.tmpl.raise("parsed-items",[h])}return g},type:function(c){var e;if(d.hash(c))e=c.type;else if(d.element(c)){var f=a(c),g=this.tmpl.sel.item;e=f.find(g.anchor).data("type")}return d.string(e)&&b.components.contains(e)?e:"image"},create:function(b,c){var e=this,f=[],g=e.creatable(b);if(g.length>0){e.tmpl.raise("create-items",[g]).isDefaultPrevented()||(f=a.map(g,function(a){return a.create()?a:null})),f.length>0&&e.tmpl.raise("created-items",[f])}return d.boolean(c)&&c?e.append(b):f},append:function(b){var c=this,d=[],e=c.appendable(b);if(e.length>0){c.tmpl.raise("append-items",[e]).isDefaultPrevented()||(d=a.map(e,function(a){return a.append()?a:null})),d.length>0&&c.tmpl.raise("appended-items",[d])}return d},detach:function(b){var c=this,d=[],e=c.detachable(b);if(e.length>0){c.tmpl.raise("detach-items",[e]).isDefaultPrevented()||(d=a.map(e,function(a){return a.detach()?a:null})),d.length>0&&c.tmpl.raise("detached-items",[d])}return d},load:function(b){var c=this;if(b=c.loadable(b),b.length>0){if(!c.tmpl.raise("load-items",[b]).isDefaultPrevented()){var d=a.map(b,function(a){return a.load()});return e.when(d).done(function(a){c.tmpl.raise("loaded-items",[a])})}}return e.resolveWith([])}}),b.components.register("items",b.Items)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e,f,g){b.Item=b.Component.extend({construct:function(a,b){var c=this;c._super(a),c.cls=a.cls.item,c.il8n=a.il8n.item,c.sel=a.sel.item,c.opt=f.extend({},a.opt.item,b),c.isAttached=!1,c.isCreated=!1,c.isDestroyed=!1,c.isLoading=!1,c.isLoaded=!1,c.isError=!1,c.isParsed=!1,c.$el=null,c.$inner=null,c.$anchor=null,c.$overlay=null,c.$wrap=null,c.$image=null,c.$caption=null,c.fixLayout=c.tmpl.opt.fixLayout,c.index=-1,c.type=c.opt.type,c.id=c.opt.id,c.productId=c.opt.productId,c.href=c.opt.href,c.src=c.opt.src,c.srcset=c.opt.srcset,c.width=c.opt.width,c.height=c.opt.height,c.title=c.opt.title,c.alt=c.opt.alt,c.caption=d.empty(c.opt.caption)?c.title:c.opt.caption,c.description=d.empty(c.opt.description)?c.alt:c.opt.description,c.attr=c.opt.attr,c.tags=c.opt.tags,c.maxWidth=c.opt.maxWidth,c.maxCaptionLength=c.opt.maxCaptionLength,c.maxDescriptionLength=c.opt.maxDescriptionLength,c.showCaptionTitle=c.opt.showCaptionTitle,c.showCaptionDescription=c.opt.showCaptionDescription,c.noLightbox=c.opt.noLightbox,c.panelHide=c.opt.panelHide,c.exif=c.opt.exif,c.hasExif=d.exif(c.exif),c._thumbUrl=null,c._load=null,c._undo={classes:"",style:"",loader:!1,wrap:!1,overlay:!1,placeholder:!1}},destroy:function(){var a=this;return a.tmpl.raise("destroy-item",[a]).isDefaultPrevented()||(a.isDestroyed=a.doDestroyItem()),a.isDestroyed&&(a.tmpl.raise("destroyed-item",[a]),a._super()),a.isDestroyed},doDestroyItem:function(){var a=this;return a.isParsed?(a.$anchor.add(a.$caption).off("click.foogallery"),a.append(),d.empty(a._undo.classes)?a.$el.removeAttr("class"):a.$el.attr("class",a._undo.classes),d.empty(a._undo.style)?a.$el.removeAttr("style"):a.$el.attr("style",a._undo.style),a._undo.overlay&&a.$overlay.remove(),a._undo.wrap&&(a.$anchor.append(a.$image),a.$wrap.remove()),a._undo.loader&&a.$el.find(a.sel.loader).remove(),a._undo.placeholder&&a.$image.prop("src")===b.EMPTY_IMAGE&&a.$image.removeAttr("src")):a.isCreated&&(a.detach(),a.$el.remove()),!0},parse:function(b){var c=this,d=a(b);return!c.tmpl.raise("parse-item",[c,d]).isDefaultPrevented()&&(c.isCreated=d.is(c.sel.elem))&&(c.isParsed=c.doParseItem(d),c.fixLayout&&c.fix()),c.isParsed&&c.tmpl.raise("parsed-item",[c]),c.isParsed},doParseItem:function(c){var e=this,g=e.tmpl.opt,h=e.cls,i=e.sel;if(e._undo.classes=c.attr("class")||"",e._undo.style=c.attr("style")||"",e.$el=c.data(b.DATA_ITEM,e),e.$inner=e.$el.children(i.inner),e.$anchor=e.$inner.children(i.anchor).on("click.foogallery",{self:e},e.onAnchorClick),e.$image=e.$anchor.find(i.image),e.$caption=e.$inner.children(i.caption.elem).on("click.foogallery",{self:e},e.onCaptionClick),!(e.$el.length&&e.$inner.length&&e.$anchor.length&&e.$image.length))return console.error("FooGallery Error: Invalid HTML markup. Check the item markup for additional elements or malformed HTML in the title or description.",e),e.isError=!0,e.tmpl.raise("error-item",[e]),0!==e.$el.length&&e.$el.remove(),!1;e.isAttached=e.$el.parent().length>0,e.isLoading=e.$el.is(i.loading),e.isLoaded=e.$el.is(i.loaded),e.isError=e.$el.is(i.error);var j=e.$anchor.attr("data-type",e.type).data();e.id=j.id||e.id,e.productId=j.productId||e.productId,e.tags=j.tags||e.tags,e.href=j.href||e.$anchor.attr("href")||e.href,e.src=e.$image.attr(g.src)||e.src,e.srcset=e.$image.attr(g.srcset)||e.srcset,e.width=parseInt(e.$image.attr("width"))||e.width,e.height=parseInt(e.$image.attr("height"))||e.height,e.title=e.$image.attr("title")||e.title,e.alt=e.$image.attr("alt")||e.alt,e.caption=j.title||j.captionTitle||e.caption,e.description=j.description||j.captionDesc||e.description,e.noLightbox=e.$anchor.hasClass(h.noLightbox),e.panelHide=e.$anchor.hasClass(h.panelHide),d.exif(j.exif)&&(e.exif=f.extend(e.exif,j.exif),e.hasExif=!0),d.empty(e.caption)&&(e.caption=a.trim(e.$caption.find(i.caption.title).html())),d.empty(e.description)&&(e.description=a.trim(e.$caption.find(i.caption.description).html())),d.number(e.maxCaptionLength)&&e.maxCaptionLength>0&&!d.empty(e.caption)&&d.string(e.caption)&&e.caption.length>e.maxCaptionLength&&e.$caption.find(i.caption.title).html(e.caption.substr(0,e.maxCaptionLength)+"&hellip;"),d.number(e.maxDescriptionLength)&&e.maxDescriptionLength>0&&!d.empty(e.description)&&d.string(e.description)&&e.description.length>e.maxDescriptionLength&&e.$caption.find(i.caption.description).html(e.description.substr(0,e.maxDescriptionLength)+"&hellip;"),e.$overlay=e.$anchor.children(i.overlay),0===e.$overlay.length&&(e.$overlay=a("<span/>",{class:h.overlay}),e.$anchor.append(e.$overlay),e._undo.overlay=!0),e.$wrap=e.$anchor.children(i.wrap),0===e.$wrap.length&&(e.$wrap=a("<span/>",{class:h.wrap}),e.$anchor.append(e.$wrap.append(e.$image)),e._undo.wrap=!0),0===e.$el.children(i.loader).length&&(e.$el.append(a("<div/>",{class:h.loader})),e._undo.loader=!0);var k=e.$image.get(0);return d.empty(k.src)&&(k.src=b.EMPTY_IMAGE,e._undo.placeholder=!0),e.$el.addClass(e.getTypeClass()),e.hasExif&&e.$el.addClass(h.exif),!e.isCreated||!e.isAttached||e.isLoading||e.isLoaded||e.isError||e.$el.addClass(h.idle),!0},create:function(){var a=this;if(!a.isCreated&&d.string(a.href)&&d.string(a.src)&&d.number(a.width)&&d.number(a.height)){a.tmpl.raise("create-item",[a]).isDefaultPrevented()||(a.isCreated=a.doCreateItem()),a.isCreated&&a.tmpl.raise("created-item",[a])}return a.isCreated},doCreateItem:function(){var c=this,e=c.tmpl.opt,f=c.cls,g=c.attr,h=c.getTypeClass(),i=c.hasExif?f.exif:"";g.elem.class=[f.elem,h,i,f.idle].join(" "),g.inner.class=f.inner;var j=[f.anchor];c.noLightbox&&j.push(f.noLightbox),c.panelHide&&j.push(f.panelHide),g.anchor.class=j.join(" "),g.anchor.href=c.href,g.anchor["data-type"]=c.type,g.anchor["data-id"]=c.id,g.anchor["data-title"]=c.caption,g.anchor["data-description"]=c.description,d.empty(c.tags)||(g.anchor["data-tags"]=JSON.stringify(c.tags)),d.empty(c.productId)||(g.anchor["data-product-id"]=c.productId),g.image.class=f.image,g.image[e.src]=c.src,g.image[e.srcset]=c.srcset,g.image.width=c.width,g.image.height=c.height,g.image.title=c.title,g.image.alt=c.alt,c.$el=a("<div/>").attr(g.elem).data(b.DATA_ITEM,c),c.$inner=a("<figure/>").attr(g.inner).appendTo(c.$el),c.$anchor=a("<a/>").attr(g.anchor).appendTo(c.$inner).on("click.foogallery",{self:c},c.onAnchorClick),c.$overlay=a("<span/>",{class:f.overlay}).appendTo(c.$anchor),c.$wrap=a("<span/>",{class:f.wrap}).appendTo(c.$anchor),c.$image=a("<img/>").attr(g.image).appendTo(c.$wrap),f=c.cls.caption,g=c.attr.caption,g.elem.class=f.elem,c.$caption=a("<figcaption/>").attr(g.elem).on("click.foogallery",{self:c},c.onCaptionClick),g.inner.class=f.inner;var k=a("<div/>").attr(g.inner).appendTo(c.$caption),l=c.showCaptionTitle&&!d.empty(c.caption),m=c.showCaptionDescription&&!d.empty(c.description);if(l||m){if(g.title.class=f.title,g.description.class=f.description,l){var n=a("<div/>").attr(g.title),o=c.caption;d.number(c.maxCaptionLength)&&c.maxCaptionLength>0&&d.string(c.caption)&&c.caption.length>c.maxCaptionLength&&(o=c.caption.substr(0,c.maxCaptionLength)+"&hellip;"),n.get(0).innerHTML=o,k.append(n)}if(m){var p=a("<div/>").attr(g.description),q=c.description;d.number(c.maxDescriptionLength)&&c.maxDescriptionLength>0&&d.string(c.description)&&c.description.length>c.maxDescriptionLength&&(q=c.description.substr(0,c.maxDescriptionLength)+"&hellip;"),p.get(0).innerHTML=q,k.append(p)}}return c.$caption.appendTo(c.$inner),0===c.$el.find(c.sel.loader).length&&c.$el.append(a("<div/>",{class:c.cls.loader})),!0},append:function(){var a=this;if(a.isCreated&&!a.isAttached){a.tmpl.raise("append-item",[a]).isDefaultPrevented()||(a.tmpl.$el.append(a.$el),!a.fixLayout&&a.isParsed||a.fix(),a.isAttached=!0),a.isAttached&&a.tmpl.raise("appended-item",[a])}return a.isAttached},detach:function(){var a=this;if(a.isCreated&&a.isAttached){a.tmpl.raise("detach-item",[a]).isDefaultPrevented()||(a.$el.detach(),!a.fixLayout&&a.isParsed||a.unfix(),a.isAttached=!1),a.isAttached||a.tmpl.raise("detached-item",[a])}return!a.isAttached},load:function(){var b=this;if(d.promise(b._load))return b._load;if(!b.isCreated||!b.isAttached)return e.rejectWith("not created or attached");if(b.tmpl.raise("load-item",[b]).isDefaultPrevented())return e.rejectWith("default prevented");var c=b.cls,f=b.$image.get(0),g=f.src;return b.isLoading=!0,b.$el.removeClass(c.idle).removeClass(c.loaded).removeClass(c.error).addClass(c.loading),b._load=a.Deferred(function(a){f.onload=function(){f.onload=f.onerror=null,b.isLoading=!1,b.isLoaded=!0,b.$el.removeClass(c.loading).addClass(c.loaded),!b.fixLayout&&b.isParsed||b.unfix(),b.tmpl.raise("loaded-item",[b]),a.resolve(b)},f.onerror=function(){f.onload=f.onerror=null,b.isLoading=!1,b.isError=!0,b.$el.removeClass(c.loading).addClass(c.error),d.string(g)&&b.$image.prop("src",g),b.tmpl.raise("error-item",[b]),a.reject(b)},f.src=b.getThumbUrl(),f.complete&&f.onload()}).promise()},fix:function(){var a=this;if(null==a.tmpl)return a;if(a.isCreated&&!a.isLoading&&!a.isLoaded&&!a.isError){var b=a.width,c=a.height,e=a.$image.get(0);if(!isNaN(b)&&!isNaN(c)&&e){var f=d.fn(a.maxWidth)?a.maxWidth(a):a.$image.width();f<=0&&(f=b);var g=f/b,h=c*g;a.$image.css({width:f,height:h})}}return a},unfix:function(){var a=this;return null==a.tmpl?a:(a.isCreated&&a.$image.css({width:"",height:""}),a)},getThumbSrc:function(a,b){return c.src(this.src,this.srcset,this.width,this.height,a,b)},getThumbUrl:function(a){a=!!d.boolean(a)&&a;var b=this;return!a&&d.string(b._thumbUrl)?b._thumbUrl:b._thumbUrl=b.getThumbSrc(b.$anchor.innerWidth(),b.$anchor.innerHeight())},getTypeClass:function(){return this.cls.types.hasOwnProperty(this.type)?this.cls.types[this.type]:""},scrollTo:function(a){var b=this;if(b.isAttached){var d=b.bounds(),e=c.getViewportBounds();switch(a){case"top":d.left+=d.width/2-e.width/2,d.top-=e.height/5;break;default:d.left+=d.width/2-e.width/2,d.top+=d.height/2-e.height/2}window.scrollTo(d.left,d.top)}return b},bounds:function(){return this.isAttached?c.getElementBounds(this.$el):null},intersects:function(a){return!!this.isAttached&&this.bounds().intersects(a)},updateState:function(){this.tmpl.state.update(this.tmpl.state.get(this))},toJSON:function(){return{type:this.type,id:this.id,productId:this.productId,href:this.href,src:this.src,srcset:this.srcset,width:this.width,height:this.height,alt:this.alt,title:this.title,caption:this.caption,description:this.description,tags:this.tags.slice(),maxCaptionLength:this.maxCaptionLength,maxDescriptionLength:this.maxDescriptionLength,showCaptionTitle:this.showCaptionTitle,showCaptionDescription:this.showCaptionDescription,noLightbox:this.noLightbox,panelHide:this.panelHide,attr:f.extend({},this.attr)}},onAnchorClick:function(a){var b=a.data.self;b.tmpl.raise("anchor-click-item",[b]).isDefaultPrevented()?a.preventDefault():b.updateState()},onCaptionClick:function(b){var c=b.data.self;!c.tmpl.raise("caption-click-item",[c]).isDefaultPrevented()&&c.$anchor.length>0&&!a(b.target).is("a,:input")&&c.$anchor.get(0).click()}}),b.template.configure("core",{item:{type:"item",id:"",href:"",src:"",srcset:"",width:0,height:0,title:"",alt:"",caption:"",description:"",tags:[],maxWidth:null,maxCaptionLength:0,maxDescriptionLength:0,showCaptionTitle:!0,showCaptionDescription:!0,noLightbox:!1,panelHide:!1,exif:{aperture:null,camera:null,created_timestamp:null,shutter_speed:null,focal_length:null,iso:null,orientation:null},attr:{elem:{},inner:{},anchor:{},image:{},caption:{elem:{},inner:{},title:{},description:{}}}}},{item:{elem:"fg-item",inner:"fg-item-inner",exif:"fg-item-exif",anchor:"fg-thumb",overlay:"fg-image-overlay",wrap:"fg-image-wrap",image:"fg-image",loader:"fg-loader",idle:"fg-idle",loading:"fg-loading",loaded:"fg-loaded",error:"fg-error",noLightbox:"fg-no-lightbox",panelHide:"fg-panel-hide",types:{item:"fg-type-unknown"},caption:{elem:"fg-caption",inner:"fg-caption-inner",title:"fg-caption-title",description:"fg-caption-desc"}}},{item:{exif:{aperture:"Aperture",camera:"Camera",created_timestamp:"Date",shutter_speed:"Exposure",focal_length:"Focal Length",iso:"ISO",orientation:"Orientation"}}}),b.components.register("item",b.Item)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj,FooGallery.utils.str),function(a,b,c,d){b.Image=b.Item.extend({}),b.template.configure("core",null,{item:{types:{image:"fg-type-image"}}}),b.components.register("image",b.Image)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){b.Paging=b.Component.extend({construct:function(a){var b=this;b._super(a),b.opt=b.tmpl.opt.paging,b.cls=b.tmpl.cls.paging,b.il8n=b.tmpl.il8n.paging,b.sel=b.tmpl.sel.paging,b.pushOrReplace=b.opt.pushOrReplace,b.type=b.opt.type,b.theme=b.opt.theme,b.size=b.opt.size,b.position=b.opt.position,b.scrollToTop=b.opt.scrollToTop,b.current=0,b.total=0,b.ctrls=[],b._arr=[]},fromHash:function(a){var b=parseInt(a);return isNaN(b)?null:b},toHash:function(a){return d.number(a)&&a>0?a.toString():null},getState:function(){return this.isValid(this.current)?this.current:null},setState:function(a){this.rebuild(),a.item&&!this.contains(a.page,a.item)&&(a.page=this.find(a.item),a.page=0!==a.page?a.page:1),this.set(a.page,!1,!1,!0)},destroy:function(){var b=this;b._arr.splice(0,b._arr.length),a.each(b.ctrls.splice(0,b.ctrls.length),function(a,b){b.destroy()}),b._super()},build:function(){var a=this,c=a.tmpl.items.available();a.total=a.size>0&&c.length>0?Math.ceil(c.length/a.size):1;for(var d=0;d<a.total;d++)a._arr.push(c.splice(0,a.size));if(a.total>1&&b.paging.hasCtrl(a.type)){var e,f,g=a.position;"both"!==g&&"top"!==g||(e=b.paging.makeCtrl(a.type,a.tmpl,a,"top"),e.create()&&(e.append(),a.ctrls.push(e))),"both"!==g&&"bottom"!==g||(f=b.paging.makeCtrl(a.type,a.tmpl,a,"bottom"),f.create()&&(f.append(),a.ctrls.push(f)))}},rebuild:function(){var b=this;b.current=0,b.total=0,b._arr.splice(0,b._arr.length),a.each(b.ctrls.splice(0,b.ctrls.length),function(a,b){b.destroy()}),b.build()},all:function(){return this._arr.slice()},available:function(){return this.get(this.current)},items:function(){return this.get(this.current)},controls:function(b){var c=this;c.isValid(b)&&a.each(c.ctrls,function(a,c){c.update(b)})},isValid:function(a){return d.number(a)&&a>0&&a<=this.total},number:function(a){return this.isValid(a)?a:0===this.current?1:this.current},create:function(a,b){var c=this;a=c.number(a);var d=a-1;c.tmpl.items.detach(c.tmpl.items.all()),c.current=a,c.tmpl.items.create(c._arr[d],!0)},get:function(a){var b=this;return b.isValid(a)?(a=b.number(a),b._arr[a-1]):[]},set:function(a,b,c,e){var f=this;if(f.isValid(a)){var g,h=f.number(a);if(h!==f.current){var i=f.current,j=function(){if(c=!d.boolean(c)||c,e=!!d.boolean(e)&&e,c&&1===f.current&&!f.tmpl.state.exists()&&(g=f.tmpl.state.get(),f.tmpl.state.update(g,f.pushOrReplace)),f.controls(a),f.create(h,e),c&&(g=f.tmpl.state.get(),f.tmpl.state.update(g,f.pushOrReplace)),f.scrollToTop&&d.boolean(b)&&b){var j=f.get(f.current);j.length>0&&j[0].scrollTo("top")}f.tmpl.raise("after-page-change",[f.current,i,e])};return!f.tmpl.raise("before-page-change",[f.current,h,j,e]).isDefaultPrevented()&&(j(),!0)}}return!1},find:function(a){for(var b=this,d=0,e=b._arr.length;d<e;d++)if(-1!==c.inArray(a,b._arr[d]))return d+1;return 0},contains:function(a,b){var d=this.get(a);return-1!==c.inArray(b,d)},first:function(){this.goto(1)},last:function(){this.goto(this._arr.length)},prev:function(){this.goto(this.current-1)},next:function(){this.goto(this.current+1)},goto:function(a){var b=this;b.set(a,!0)&&b.tmpl.loadAvailable()}}),b.PagingControl=b.Component.extend({construct:function(a,b,c){var d=this;d._super(a),d.pages=b,d.position=c,d.$container=null},create:function(){var b=this;return b.$container=a("<nav/>",{class:b.pages.cls.container}).addClass(b.pages.theme),!0},destroy:function(){var a=this;a.$container.remove(),a.$container=null},append:function(){var a=this;"top"===a.position?a.$container.insertBefore(a.tmpl.$el):a.$container.insertAfter(a.tmpl.$el)},update:function(a){}}),b.paging.register("default",b.Paging,null,{type:"none",theme:"fg-light",size:30,pushOrReplace:"push",position:"none",scrollToTop:!0},{container:"fg-paging-container"},null,-100)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){b.Dots=b.Paging.extend({}),b.DotsControl=b.PagingControl.extend({construct:function(b,c,d){this._super(b,c,d),this.$container=a(),this.$list=a(),this.$items=a()},create:function(){for(var b,c=this,d=c.pages.cls,e=c.pages.il8n,f=[],g=a("<ul/>",{class:d.list}),h=0,i=c.pages.total;h<i;h++)f.push(b=c.createItem(h+1,e.page)),g.append(b);return c.$list=g,c.$container=a("<nav/>",{class:d.container}).addClass(c.pages.theme).append(g),c.$items=a(a.map(f,function(a){return a.get()})),!0},append:function(){var a=this;"top"===a.position?a.$container.insertBefore(a.tmpl.$el):a.$container.insertAfter(a.tmpl.$el)},destroy:function(){var b=this,c=b.pages.sel;b.$list.find(c.link).off("click.foogallery",b.onLinkClick),b.$container.remove(),b.$container=a(),b.$list=a(),b.$items=a()},update:function(a){this.setSelected(a-1)},setSelected:function(b){var c=this,e=c.pages.cls,f=c.pages.il8n,g=c.pages.sel;c.$items.filter(g.selected).removeClass(e.selected).each(function(b,c){var e=a(c),f=e.data("label"),h=e.find(g.reader);d.string(f)&&0!==h.length&&h.html(f)}),c.$items.eq(b).addClass(e.selected).each(function(b,c){var e=a(c),h=e.find(g.reader),i=h.html();d.string(i)&&0!==h.length&&(e.data("label",i),h.html(f.current))})},createItem:function(b,c,e,f,g){e=d.string(e)?e:b,c=d.string(c)?c:"";var h=this,i=h.pages.opt,j=h.pages.cls,k=a("<a/>",{class:j.link,href:"#page-"+b}).html(e).on("click.foogallery",{self:h,page:b},h.onLinkClick);d.empty(c)||k.attr("title",c.replace(/\{PAGE}/g,b).replace(/\{LIMIT}/g,i.limit+"")),g=d.string(g)?g:c,d.empty(g)||k.prepend(a("<span/>",{class:j.reader,text:g.replace(/\{PAGE}/g,"").replace(/\{LIMIT}/g,i.limit+"")}));var l=a("<li/>",{class:j.item}).append(k);return f=d.string(f)?f:"",d.empty(f)||l.addClass(f),l},onLinkClick:function(b){b.preventDefault();var c=b.data.self,d=b.data.page,e=c.pages.sel;a(this).closest(e.item).is(e.disabled)||(c.pages.set(d,!0),c.tmpl.loadAvailable())}}),b.paging.register("dots",b.Dots,b.DotsControl,{type:"dots",position:"both",pushOrReplace:"push"},{list:"fg-dots",item:"fg-dot-item",link:"fg-dot-link",disabled:"fg-disabled",selected:"fg-selected",visible:"fg-visible",reader:"fg-sr-only"},{current:"Current page",page:"Page {PAGE}"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c){b.DefaultTemplate=b.Template.extend({}),b.template.register("default",b.DefaultTemplate,null,{container:"foogallery fg-default"})}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d){b.MasonryTemplate=b.Template.extend({construct:function(a,b){this._super(a,b),this.masonry=null,this.style=null,this.$columnWidth=null},getStylesheet:function(){var a=this;return null===a.style&&(a.style=document.createElement("style"),a.style.appendChild(document.createTextNode("")),document.head.appendChild(a.style)),a.style.sheet},delayedLayout:function(){var a=this;a._delayedLayout&&clearTimeout(a._delayedLayout),a._delayedLayout=setTimeout(function(){a._delayedLayout=null,a.masonry.layout()},20)},onPreInit:function(b,c){var e=c.sel,f=c.cls;f.layouts=a.map(f.layout,function(a){return a}).join(" ");for(var g=a.map(f.layout,function(a,b){return{key:b,value:a}}),h=0,i=g.length;h<i;h++)if(c.$el.hasClass(g[h].value)){c.template.layout=g[h].key;break}d.string(f.layout[c.template.layout])||(c.template.layout="col4");var j,k,l="fixed"===c.template.layout;if(c.template.isFitWidth=l,c.template.percentPosition=!l,c.template.transitionDuration=0,c.template.itemSelector=e.item.elem,c.$el.removeClass(f.layouts).addClass(f.layout[c.template.layout]),l||(0===c.$el.find(e.gutterWidth).length&&c.$el.prepend(a("<div/>").addClass(f.gutterWidth)),c.template.gutter=e.gutterWidth),0===c.$el.find(e.columnWidth).length&&c.$el.prepend(a("<div/>").addClass(f.columnWidth)),l&&d.number(c.template.columnWidth)){var m=c.$el.find(e.columnWidth).width(c.template.columnWidth);j=c.getStylesheet(),k="#"+c.id+e.container+" "+e.item.elem+" { width: "+m.outerWidth()+"px; }",j.insertRule(k,0)}c.template.columnWidth=e.columnWidth,l&&d.number(c.template.gutter)&&(j=c.getStylesheet(),k="#"+c.id+e.container+" "+e.item.elem+" { margin-bottom: "+c.template.gutter+"px; }",j.insertRule(k,0)),c.masonry=new Masonry(c.$el.get(0),c.template)},onPostInit:function(a,b){b.masonry.layout()},onFirstLoad:function(a,b){b.masonry.layout()},onReady:function(a,b){b.delayedLayout()},onDestroy:function(a,b){b._delayedLayout&&clearTimeout(b._delayedLayout),b.$el.find(b.sel.columnWidth).remove(),b.$el.find(b.sel.gutterWidth).remove(),b.style&&b.style.parentNode&&b.style.parentNode.removeChild(b.style)},onDestroyed:function(a,b){b.masonry instanceof Masonry&&b.masonry.destroy()},onLayout:function(a,b){b.masonry.layout()},onParsedItems:function(a,b,c){b.masonry.layout()},onAppendedItems:function(a,b,c){c=b.items.jquerify(c),c=b.masonry.addItems(c),b.masonry.layoutItems(c,!0)},onDetachItem:function(a,b,c){a.isDefaultPrevented()||(a.preventDefault(),b.masonry.remove(c.$el),c.isAttached=!1,c.unfix())},onDetachedItems:function(a,b,c){b.masonry.layout()},onLoadedItems:function(a,b,c){b.masonry.layout()}}),b.template.register("masonry",b.MasonryTemplate,{fixLayout:!0,template:{initLayout:!1,isInitLayout:!1,layout:"col4"}},{container:"foogallery fg-masonry",columnWidth:"fg-column-width",gutterWidth:"fg-gutter-width",layout:{fixed:"fg-masonry-fixed",col2:"fg-masonry-2col",col3:"fg-masonry-3col",col4:"fg-masonry-4col",col5:"fg-masonry-5col"}})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){b.Justified=c.Class.extend({construct:function(c,d){this.tmpl=c,this.$el=c.$el,this.options=a.extend(!0,{},b.Justified.defaults,d),this._items=[]},init:function(){var a=this;d.string(a.options.maxRowHeight)&&(a.options.maxRowHeight.indexOf("%")?a.options.maxRowHeight=a.options.rowHeight*(parseInt(a.options.maxRowHeight)/100):a.options.maxRowHeight=parseInt(a.options.maxRowHeight))},destroy:function(){this.$el.removeAttr("style")},parse:function(){var b=this;return b._items=a.map(b.tmpl.getItems(),function(a,b){return{index:b,width:a.width,height:a.height,top:0,left:0,$item:a.$el}})},getMaxRowHeight:function(){var a=this;return d.string(a.options.maxRowHeight)&&(a.options.maxRowHeight.indexOf("%")?a.options.maxRowHeight=a.options.rowHeight*(parseInt(a.options.maxRowHeight)/100):a.options.maxRowHeight=parseInt(a.options.maxRowHeight)),d.number(a.options.maxRowHeight)?a.options.maxRowHeight:a.options.rowHeight},getContainerWidth:function(){var a=this;return a.$el.is(":visible")?a.$el.width():a.$el.parents(":visible:first").innerWidth()},layout:function(){this.parse();var b=this,c=0,d=b.getContainerWidth(),e=b.getMaxRowHeight(),f=b.rows(d,e);a.each(f,function(a,d){d.visible&&(a>0&&(c+=b.options.margins),c+=d.height),b.render(d)}),b.$el.height(c)},render:function(a){for(var b,c=0,d=a.items.length;c<d;c++)b=a.items[c],a.visible?b.$item.css({width:b.width,height:b.height,top:b.top,left:b.left,display:"",maxHeight:this.options.maxRowHeight>0?this.options.maxRowHeight:""}).addClass("fg-positioned"):b.$item.css("display","none")},justify:function(a,b,c,d){var e=this,f=e.options.margins*(a.items.length-1),g=c-f,h=g/a.width;a.width=a.width*h,a.height=a.height*h,a.top=b,a.height>d&&(a.height=d),a.left=0,a.width<g&&(a.left=(g-a.width)/2),a.width+=f;for(var i,j=a.left,k=0,l=a.items.length;k<l;k++)k>0&&(j+=e.options.margins),i=a.items[k],i.left=j,i.top=b,i.width=i.width*h,i.height=i.height*h,i.height>d&&(i.height=d),j+=i.width;return a.height},position:function(a,b,c,d){var e=this,f=e.options.margins*(a.items.length-1),g=c-f;if(a.top=b,a.left=0,a.width<g)switch(d){case"center":a.left=(g-a.width)/2;break;case"right":a.left=g-a.width}a.width+=f;for(var h,i=a.left,j=0,k=a.items.length;j<k;j++)j>0&&(i+=e.options.margins),h=a.items[j],h.left=i,h.top=b,i+=h.width;return a.height},lastRow:function(a,b,c,d){var e=this,f=e.options.margins*(a.items.length-1),g=c-f,h=a.width/g>e.options.justifyThreshold;switch(e.options.lastRow){case"hide":h?e.justify(a,b,c,d):a.visible=!1;break;case"justify":e.justify(a,b,c,d);break;case"nojustify":h?e.justify(a,b,c,d):e.position(a,b,c,"left");break;case"left":case"center":case"right":h?e.justify(a,b,c,d):e.position(a,b,c,e.options.lastRow)}},items:function(){return a.map(this._items,function(a){return{index:a.index,width:a.width,height:a.height,$item:a.$item,top:a.top,left:a.left}})},rows:function(a,b){function c(){var a={index:++h,visible:!0,width:0,height:e.options.rowHeight,top:0,left:0,items:[]};return g.push(a),a}for(var d,e=this,f=e.items(),g=[],h=-1,i=c(),j=0,k=0,l=0,m=f.length;l<m;l++){if(d=f[l],d.height!=e.options.rowHeight){var n=e.options.rowHeight/d.height;d.height=d.height*n,d.width=d.width*n}k+d.width>a&&l>0&&(g.length>1&&(j+=e.options.margins),j+=e.justify(i,j,a,b),i=c(),k=0),i.items.length>0&&(k+=e.options.margins),k+=d.width,i.width+=d.width,i.items.push(d)}return g.length>1&&(j+=e.options.margins),e.lastRow(i,j,a,b),g}}),b.Justified.defaults={itemSelector:".fg-item",rowHeight:150,maxRowHeight:"200%",margins:0,lastRow:"center",justifyThreshold:1,refreshInterval:250}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c){b.JustifiedTemplate=b.Template.extend({onPreInit:function(a,c){c.justified=new b.Justified(c,c.template)},onInit:function(a,b){b.justified.init()},onFirstLoad:function(a,b){b.justified.layout()},onReady:function(a,b){b.justified.layout()},onDestroy:function(a,b){b.justified.destroy()},onLayout:function(a,b){b.justified.layout()},onAfterPageChange:function(a,b,c,d,e){e||b.justified.layout()},onAfterFilterChange:function(a,b){b.justified.layout()}}),b.template.register("justified",b.JustifiedTemplate,null,{container:"foogallery fg-justified"})}(FooGallery.$,FooGallery,FooGallery.utils.is),function(a,b,c,d,e){b.PortfolioTemplate=b.Template.extend({construct:function(a,b){this._super(a,b),this.style=null,this.fullWidth=!1},getStylesheet:function(){var a=this;return null===a.style&&(a.style=document.createElement("style"),a.style.appendChild(document.createTextNode("")),document.head.appendChild(a.style)),a.style.sheet},onPreInit:function(a,b){b.appendCSS()},onPostInit:function(a,b){b.checkCSS()},onDestroy:function(a,b){b.removeCSS()},onLayout:function(a,b){b.checkCSS()},checkCSS:function(){var a=this,b=a.getContainerWidth();b<a.template.columnWidth!==a.fullWidth&&a.appendCSS(b)},appendCSS:function(a){var b=this;a=d.number(a)?a:b.getContainerWidth(),b.removeCSS();var c,e=b.getStylesheet(),f="#"+b.id+b.sel.container,g=f+" "+b.sel.item.elem,h=b.template.columnWidth,i=Math.ceil(b.template.gutter/2);switch(b.template.align){case"center":c=f+" { justify-content: center; }",e.insertRule(c,0);break;case"left":c=f+" { justify-content: flex-start; }",e.insertRule(c,0);break;case"right":c=f+" { justify-content: flex-end; }",e.insertRule(c,0)}b.fullWidth=a<h,b.fullWidth?(c=g+" { max-width: 100%; min-width: 100%; margin: "+i+"px; }",e.insertRule(c,0)):(c=g+" { max-width: "+h+"px; min-width: "+h+"px; margin: "+i+"px; }",e.insertRule(c,0))},removeCSS:function(){var a=this;a.style&&a.style.parentNode&&(a.style.parentNode.removeChild(a.style),a.style=null,a.fullWidth=!1)}}),b.template.register("simple_portfolio",b.PortfolioTemplate,{template:{gutter:40,align:"center",columnWidth:250}},{container:"foogallery fg-simple_portfolio"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d){b.ImageViewerTemplate=b.Template.extend({construct:function(b,c){this._super(d.extend({},b,{paging:{pushOrReplace:"replace",theme:"fg-light",type:"default",size:1,position:"none",scrollToTop:!1}}),c),this.$inner=a(),this.$current=a(),this.$total=a(),this.$prev=a(),this.$next=a()},createChildren:function(){var b=this;return a("<div/>",{class:b.cls.inner}).append(a("<div/>",{class:b.cls.innerContainer}),a("<div/>",{class:b.cls.controls}).append(a("<div/>",{class:b.cls.prev}).append(a("<span/>",{text:b.il8n.prev})),a("<label/>",{class:b.cls.count,text:b.il8n.count}).prepend(a("<span/>",{class:b.cls.countCurrent,text:"0"})).append(a("<span/>",{class:b.cls.countTotal,text:"0"})),a("<div/>",{class:b.cls.next}).append(a("<span/>",{text:b.il8n.next}))))},destroyChildren:function(){var a=this;a.$el.find(a.sel.inner).remove()},onPreInit:function(a,b){b.$inner=b.$el.find(b.sel.innerContainer),b.$current=b.$el.find(b.sel.countCurrent),b.$total=b.$el.find(b.sel.countTotal),b.$prev=b.$el.find(b.sel.prev),b.$next=b.$el.find(b.sel.next)},onInit:function(a,b){b.template.attachFooBox&&b.$el.on("foobox.previous",{self:b},b.onFooBoxPrev).on("foobox.next",{self:b},b.onFooBoxNext),b.$prev.on("click",{self:b},b.onPrevClick),b.$next.on("click",{self:b},b.onNextClick)},onFirstLoad:function(a,b){b.update()},onDestroy:function(a,b){b.template.attachFooBox&&b.$el.off({"foobox.previous":b.onFooBoxPrev,"foobox.next":b.onFooBoxNext}),b.$prev.off("click",b.onPrevClick),b.$next.off("click",b.onNextClick)},onAppendItem:function(a,b,c){a.preventDefault(),b.$inner.append(c.$el),c.fix(),c.isAttached=!0},onAfterPageChange:function(a,b,c,d,e){e||b.update()},onAfterFilterChange:function(a,b){b.update()},update:function(){this.pages&&(this.$current.text(this.pages.current),this.$total.text(this.pages.total))},prev:function(){this.pages&&(this.template.loop&&1===this.pages.current?this.pages.last():this.pages.prev(),this.update())},next:function(){this.pages&&(this.template.loop&&this.pages.current===this.pages.total?this.pages.first():this.pages.next(),this.update())},onFooBoxPrev:function(a){a.data.self.prev()},onFooBoxNext:function(a){a.data.self.next()},onPrevClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.prev()},onNextClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.next()}}),b.template.register("image-viewer",b.ImageViewerTemplate,{template:{attachFooBox:!1,loop:!1}},{
12
- container:"foogallery fg-image-viewer",inner:"fiv-inner",innerContainer:"fiv-inner-container",controls:"fiv-ctrls",prev:"fiv-prev",next:"fiv-next",count:"fiv-count",countCurrent:"fiv-count-current",countTotal:"fiv-count-total"},{prev:"Prev",next:"Next",count:"of"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.obj),function(a,b,c){b.ThumbnailTemplate=b.Template.extend({construct:function(a,b){this._super(c.extend({},a,{filtering:{type:"none"},paging:{pushOrReplace:"replace",theme:"fg-light",type:"default",size:1,position:"none",scrollToTop:!1}}),b)}}),b.template.register("thumbnail",b.ThumbnailTemplate,null,{container:"foogallery fg-thumbnail"})}(FooGallery.$,FooGallery,FooGallery.utils.obj),function(a,b,c,d,e,f){b.StackAlbum=c.Class.extend({construct:function(c,f){var g=this;g.$el=d.jq(c)?c:a(c),g.el=g.$el.get(0),g.opt=e.extend({},b.StackAlbum.defaults,f,g.$el.data("foogallery")),g.$back=g.$el.find(".fg-header-back"),g.$active=g.$el.find(".fg-header-active"),g.$piles=g.$el.find(".fg-piles"),g.piles=g.$piles.find(".fg-pile").map(function(a,c){return new b.StackAlbum.Pile(g,c,{index:a})}).get(),g.ignoreResize=!1,g.robserver=new ResizeObserver(function(){!g.ignoreResize&&g.$el.is(":visible")&&g.layout(!0)})},init:function(){var a=this;a.piles.forEach(function(a){a.init()}),a.$back.on("click.foogallery",{self:a},a.onBackClick),a.robserver.observe(a.el)},destroy:function(){var a=this;a.robserver.disconnect(),a.$back.off(".foogallery"),a.piles.forEach(function(a){a.destroy()})},getLayoutInfo:function(){var a=this,b=a.opt.gutter+2*a.opt.border;return{maxWidth:a.$el.width(),space:b,halfSpace:b/2,itemWidth:a.opt.itemWidth,itemHeight:a.opt.itemHeight,itemOuterWidth:a.opt.itemWidth+2*a.opt.border,itemOuterHeight:a.opt.itemHeight+2*a.opt.border,blockWidth:a.opt.itemWidth+b,blockHeight:a.opt.itemHeight+b,border:a.opt.border,doubleBorder:2*a.opt.border,gutter:a.opt.gutter,halfGutter:a.opt.gutter/2}},layout:function(a){var b,c=this;a&&(c.$el.addClass("fg-disable-transitions"),c.$el.prop("offsetWidth")),c.hasActive?(b=c.activePile.layout(),c.activePile.setPosition(0,0,b.width,b.height),c.$piles.css({width:b.width+"px",height:b.height+"px"})):(b=c.layoutPiles(),c.$piles.css({width:b.width+"px",height:b.height+"px"})),a&&c.$el.removeClass("fg-disable-transitions")},layoutPiles:function(a){var b=this,c=b.getLayoutInfo(),e=0,f=1,g=0;return a=d.fn(a)?a:function(){},b.piles.forEach(function(b){var d=e;(e+=c.blockWidth)>c.maxWidth&&(d=0,e=c.blockWidth,f++);var h=c.blockHeight*(f-1);a(b,h,d,c.blockWidth,c.blockHeight),b.setPosition(h,d,c.blockWidth,c.blockHeight),e>g&&(g=e)}),{width:g,height:c.blockHeight*f}},setActive:function(a){var c,d=this,e=d.activePile,g=e instanceof b.StackAlbum.Pile;a=a instanceof b.StackAlbum.Pile?a:null,d.activePile=a,d.hasActive=null!==a,g&&e.collapse(),d.ignoreResize=!0,d.hasActive?(d.piles.forEach(function(b){b!==a&&b.hide(d.activePile)}),c=d.activePile.expand(),d.$active.text(a.title),d.$el.addClass("fg-has-active")):(c=d.layoutPiles(function(a){a.show()}),d.$el.removeClass("fg-has-active")),f.start(d.$piles,function(a){a.css({width:c.width+"px",height:c.height+"px"})},!1,350).then(function(){d.ignoreResize=!1})},onBackClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.setActive(null)}}),b.StackAlbum.defaults={gutter:50,itemWidth:150,itemHeight:150,border:10,angleStep:1,randomAngle:!1}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj,FooGallery.utils.transition),function(a,b,c,d,e){b.StackAlbum.Pile=c.Class.extend({construct:function(c,f,g){var h=this;h.album=c,h.$el=d.jq(f)?f:a(f),h.opt=e.extend({},b.StackAlbum.Pile.defaults,g,h.$el.data()),h.title=h.opt.title,h.items=h.$el.find(".fg-pile-item").map(function(a,c){return new b.StackAlbum.Item(h,c,{index:a})}).get(),h.$cover=a("<div/>",{class:"fg-pile-cover"}).append(a("<div/>",{class:"fg-pile-cover-content"}).append(a("<span/>",{class:"fg-pile-cover-title",text:h.opt.title}),a("<span/>",{class:"fg-pile-cover-count",text:h.items.length}))),h.top=0,h.left=0,h.isExpanded=!1},init:function(){var a=this,b=a.album.opt,c=a.getAngles(b.angleStep),d=b.randomAngle?a.randomAngle(c):b.angleStep;a.$cover.on("click.foogallery",{self:a},a.onCoverClick),a.items.forEach(function(e,f){e.init(),f>3||(0===f?(e.$el.addClass("fg-has-cover").append(a.$cover),e.load()):(f%2==0?e.setAngle(-d):e.setAngle(d),b.randomAngle?d=a.randomAngle(c):d+=b.angleStep))})},destroy:function(){var a=this;a.$cover.remove(),a.items.forEach(function(a,b){0===b&&a.$el.removeClass("fg-has-cover"),a.destroy()})},getAngles:function(a){for(var b=[],c=1;c<=3;c++)b.push(c*a);return b},randomAngle:function(a){var b=a.length,c=Math.floor(Math.random()*(b-0)+0),d=a.splice(c,1);return 1===d.length?d[0]:0},setPosition:function(a,b,c,e){var f=this;f.top=a,f.left=b,d.number(c)&&d.number(e)?f.$el.css({top:a+"px",left:b+"px",width:c+"px",height:e+"px"}):f.$el.css({top:a+"px",left:b+"px"})},layout:function(){var a=this,b=a.album.getLayoutInfo(),c=0,d=1,e=!1,f=0;return a.items.forEach(function(a){(c+=b.halfGutter)>b.maxWidth&&(c=b.halfGutter,d++,e=!0);var g=c;c+=b.itemOuterWidth+b.halfGutter,!e&&c>b.maxWidth&&(g=b.halfGutter,c=b.blockWidth,d++);var h=b.blockHeight*(d-1)+b.halfGutter;e=!1,a.setPosition(h,g,b.itemOuterWidth,b.itemOuterHeight),a.isLoaded||a.load(),c>f&&(f=c)}),{width:f,height:b.blockHeight*d}},expand:function(){var a,b=this;return b.$el.removeClass("fg-collapsed").addClass("fg-expanded"),a=b.layout(),b.setPosition(0,0,a.width,a.height),b.isExpanded=!0,a},collapse:function(){var a=this,b=a.album.getLayoutInfo();a.$el.removeClass("fg-expanded").addClass("fg-collapsed"),a.items.forEach(function(a){a.setPosition(b.halfGutter,b.halfGutter,b.itemOuterWidth,b.itemOuterHeight)});var c={width:b.blockWidth,height:b.blockHeight};return a.setPosition(0,0,c.width,c.height),a.isExpanded=!1,c},show:function(){this.$el.removeClass("fg-hidden fg-expanded fg-collapsed")},hide:function(a){var c=this;a instanceof b.StackAlbum.Pile&&c.setPosition(a.top,a.left),c.$el.addClass("fg-hidden")},onCoverClick:function(a){a.preventDefault(),a.stopPropagation();var b=a.data.self;b.album.setActive(b)}}),b.StackAlbum.Pile.defaults={index:-1,title:null}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj),function(a,b,c,d,e){b.StackAlbum.Item=c.Class.extend({construct:function(c,f,g){var h=this;h.$el=d.jq(f)?f:a(f),h.opt=e.extend({},b.StackAlbum.Item.defaults,g,h.$el.data()),h.$thumb=h.$el.find(".fg-pile-item-thumb"),h.$image=h.$el.find(".fg-pile-item-image"),h.isLoaded=!1,h.isLoading=!1,h._loading=null},init:function(){},destroy:function(){},setAngle:function(a){this.$el.css({transform:"rotate("+a+"deg)"})},setPosition:function(a,b,c,d){this.$el.css({top:a+"px",left:b+"px",width:c+"px",height:d+"px"})},load:function(){var b=this;return d.promise(b._loading)?b._loading:b._loading=a.Deferred(function(a){b.$el.addClass("fg-loading"),b.isLoading=!0,b.$image.on({"load.foogallery":function(){b.$image.off(".foogallery"),b.$el.removeClass("fg-loading"),b.isLoading=!1,b.isLoaded=!0,a.resolve()},"error.foogallery":function(){b.$image.off(".foogallery"),b.$el.removeClass("fg-loading"),b.isLoading=!1,b.isLoaded=!0,a.reject()}}),b.$image.prop("src",b.$image.attr(b.opt.src))}).promise()}}),b.StackAlbum.Item.defaults={index:-1,src:"data-src-fg"}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj),function(a,b,c){a.fn.foogalleryStackAlbum=function(c){return this.each(function(c,d){var e=a(d),f=e.data("__FooGalleryAlbum__");f instanceof b.StackAlbum&&f.destroy(),f=new b.StackAlbum(e),f.init(),e.data("__FooGalleryAlbum__",f)})},b.loadStackAlbums=b.reloadStackAlbums=function(){a(function(){a(".foogallery-stack-album:not(.fg-ready)").foogalleryStackAlbum()}),c.ready(function(){a(".foogallery-stack-album.fg-ready").foogalleryStackAlbum()})},b.loadStackAlbums()}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d,e){b.triggerPostLoad=function(b,c,d,e,f){if("first-load"===b.type||c.initialized&&("after-page-change"===b.type&&!f||"after-filter-change"===b.type))try{if(c.$el.parents(".fbx-item").length>0)return;c.$el.hasClass("fbx-instance")&&window.FOOBOX&&a.fn.foobox?c.$el.foobox(window.FOOBOX.o):a("body").trigger("post-load")}catch(a){console.error(a)}},b.autoDefaults={on:{"first-load.foogallery after-page-change.foogallery after-filter-change.foogallery":b.triggerPostLoad}},b.autoEnabled=!0,b.auto=function(a){b.autoDefaults=d.merge(b.autoDefaults,a)},b.globalsMerged=!1,b.mergeGlobals=function(){if(!0!==b.globalsMerged&&window.FooGallery_il8n&&e.object(window.FooGallery_il8n)){var a=window.FooGallery_il8n;for(var d in a)if(a.hasOwnProperty(d)&&b[d]instanceof c.Factory&&e.object(a[d]))for(var f in a[d])a[d].hasOwnProperty(f)&&b[d].configure(f,null,null,a[d][f]);b.globalsMerged=!0}},b.load=b.reload=function(){a(function(){b.mergeGlobals(),b.autoEnabled&&a('[id^="foogallery-gallery-"]:not(.fg-ready)').foogallery(b.autoDefaults)}),c.ready(function(){b.mergeGlobals(),b.autoEnabled&&a('[id^="foogallery-gallery-"].fg-ready').foogallery(b.autoDefaults)})},b.load()}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.obj,FooGallery.utils.is);
1
  /*
2
  * FooGallery - The Most Intuitive and Extensible Gallery Creation and Management Tool Ever Created for WordPress
3
+ * @version 2.0.11
4
  * @link
5
  * @copyright Steven Usher & Brad Vincent 2015
6
  * @license Released under the GPLv3 license.
7
  */
8
 
9
+ function _typeof(a){"@babel/helpers - typeof";return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a})(a)}!function(){"use strict";function a(a){this.time=a.time,this.target=a.target,this.rootBounds=a.rootBounds,this.boundingClientRect=a.boundingClientRect,this.intersectionRect=a.intersectionRect||i(),this.isIntersecting=!!a.intersectionRect;var b=this.boundingClientRect,c=b.width*b.height,d=this.intersectionRect,e=d.width*d.height;this.intersectionRatio=c?Number((e/c).toFixed(4)):this.isIntersecting?1:0}function b(a,b){var c=b||{};if("function"!=typeof a)throw new Error("callback must be a function");if(c.root&&1!=c.root.nodeType)throw new Error("root must be an Element");this._checkForIntersections=d(this._checkForIntersections.bind(this),this.THROTTLE_TIMEOUT),this._callback=a,this._observationTargets=[],this._queuedEntries=[],this._rootMarginValues=this._parseRootMargin(c.rootMargin),this.thresholds=this._initThresholds(c.threshold),this.root=c.root||null,this.rootMargin=this._rootMarginValues.map(function(a){return a.value+a.unit}).join(" ")}function c(){return window.performance&&performance.now&&performance.now()}function d(a,b){var c=null;return function(){c||(c=setTimeout(function(){a(),c=null},b))}}function e(a,b,c,d){"function"==typeof a.addEventListener?a.addEventListener(b,c,d||!1):"function"==typeof a.attachEvent&&a.attachEvent("on"+b,c)}function f(a,b,c,d){"function"==typeof a.removeEventListener?a.removeEventListener(b,c,d||!1):"function"==typeof a.detatchEvent&&a.detatchEvent("on"+b,c)}function g(a,b){var c=Math.max(a.top,b.top),d=Math.min(a.bottom,b.bottom),e=Math.max(a.left,b.left),f=Math.min(a.right,b.right),g=f-e,h=d-c;return g>=0&&h>=0&&{top:c,bottom:d,left:e,right:f,width:g,height:h}}function h(a){var b;try{b=a.getBoundingClientRect()}catch(a){}return b?(b.width&&b.height||(b={top:b.top,right:b.right,bottom:b.bottom,left:b.left,width:b.right-b.left,height:b.bottom-b.top}),b):i()}function i(){return{top:0,bottom:0,left:0,right:0,width:0,height:0}}function j(a,b){for(var c=b;c;){if(c==a)return!0;c=k(c)}return!1}function k(a){var b=a.parentNode;return b&&11==b.nodeType&&b.host?b.host:b&&b.assignedSlot?b.assignedSlot.parentNode:b}if("object"==typeof window){if("IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype)return void("isIntersecting"in window.IntersectionObserverEntry.prototype||Object.defineProperty(window.IntersectionObserverEntry.prototype,"isIntersecting",{get:function(){return this.intersectionRatio>0}}));var l=window.document,m=[];b.prototype.THROTTLE_TIMEOUT=100,b.prototype.POLL_INTERVAL=null,b.prototype.USE_MUTATION_OBSERVER=!0,b.prototype.observe=function(a){if(!this._observationTargets.some(function(b){return b.element==a})){if(!a||1!=a.nodeType)throw new Error("target must be an Element");this._registerInstance(),this._observationTargets.push({element:a,entry:null}),this._monitorIntersections(),this._checkForIntersections()}},b.prototype.unobserve=function(a){this._observationTargets=this._observationTargets.filter(function(b){return b.element!=a}),this._observationTargets.length||(this._unmonitorIntersections(),this._unregisterInstance())},b.prototype.disconnect=function(){this._observationTargets=[],this._unmonitorIntersections(),this._unregisterInstance()},b.prototype.takeRecords=function(){var a=this._queuedEntries.slice();return this._queuedEntries=[],a},b.prototype._initThresholds=function(a){var b=a||[0];return Array.isArray(b)||(b=[b]),b.sort().filter(function(a,b,c){if("number"!=typeof a||isNaN(a)||a<0||a>1)throw new Error("threshold must be a number between 0 and 1 inclusively");return a!==c[b-1]})},b.prototype._parseRootMargin=function(a){var b=a||"0px",c=b.split(/\s+/).map(function(a){var b=/^(-?\d*\.?\d+)(px|%)$/.exec(a);if(!b)throw new Error("rootMargin must be specified in pixels or percent");return{value:parseFloat(b[1]),unit:b[2]}});return c[1]=c[1]||c[0],c[2]=c[2]||c[0],c[3]=c[3]||c[1],c},b.prototype._monitorIntersections=function(){this._monitoringIntersections||(this._monitoringIntersections=!0,this.POLL_INTERVAL?this._monitoringInterval=setInterval(this._checkForIntersections,this.POLL_INTERVAL):(e(window,"resize",this._checkForIntersections,!0),e(l,"scroll",this._checkForIntersections,!0),this.USE_MUTATION_OBSERVER&&"MutationObserver"in window&&(this._domObserver=new MutationObserver(this._checkForIntersections),this._domObserver.observe(l,{attributes:!0,childList:!0,characterData:!0,subtree:!0}))))},b.prototype._unmonitorIntersections=function(){this._monitoringIntersections&&(this._monitoringIntersections=!1,clearInterval(this._monitoringInterval),this._monitoringInterval=null,f(window,"resize",this._checkForIntersections,!0),f(l,"scroll",this._checkForIntersections,!0),this._domObserver&&(this._domObserver.disconnect(),this._domObserver=null))},b.prototype._checkForIntersections=function(){var b=this._rootIsInDom(),d=b?this._getRootRect():i();this._observationTargets.forEach(function(e){var f=e.element,g=h(f),i=this._rootContainsTarget(f),j=e.entry,k=b&&i&&this._computeTargetAndRootIntersection(f,d),l=e.entry=new a({time:c(),target:f,boundingClientRect:g,rootBounds:d,intersectionRect:k});j?b&&i?this._hasCrossedThreshold(j,l)&&this._queuedEntries.push(l):j&&j.isIntersecting&&this._queuedEntries.push(l):this._queuedEntries.push(l)},this),this._queuedEntries.length&&this._callback(this.takeRecords(),this)},b.prototype._computeTargetAndRootIntersection=function(a,b){if("none"!=window.getComputedStyle(a).display){for(var c=h(a),d=c,e=k(a),f=!1;!f;){var i=null,j=1==e.nodeType?window.getComputedStyle(e):{};if("none"==j.display)return;if(e==this.root||e==l?(f=!0,i=b):e!=l.body&&e!=l.documentElement&&"visible"!=j.overflow&&(i=h(e)),i&&!(d=g(i,d)))break;e=k(e)}return d}},b.prototype._getRootRect=function(){var a;if(this.root)a=h(this.root);else{var b=l.documentElement,c=l.body;a={top:0,left:0,right:b.clientWidth||c.clientWidth,width:b.clientWidth||c.clientWidth,bottom:b.clientHeight||c.clientHeight,height:b.clientHeight||c.clientHeight}}return this._expandRectByRootMargin(a)},b.prototype._expandRectByRootMargin=function(a){var b=this._rootMarginValues.map(function(b,c){return"px"==b.unit?b.value:b.value*(c%2?a.width:a.height)/100}),c={top:a.top-b[0],right:a.right+b[1],bottom:a.bottom+b[2],left:a.left-b[3]};return c.width=c.right-c.left,c.height=c.bottom-c.top,c},b.prototype._hasCrossedThreshold=function(a,b){var c=a&&a.isIntersecting?a.intersectionRatio||0:-1,d=b.isIntersecting?b.intersectionRatio||0:-1;if(c!==d)for(var e=0;e<this.thresholds.length;e++){var f=this.thresholds[e];if(f==c||f==d||f<c!=f<d)return!0}},b.prototype._rootIsInDom=function(){return!this.root||j(l,this.root)},b.prototype._rootContainsTarget=function(a){return j(this.root||l,a)},b.prototype._registerInstance=function(){m.indexOf(this)<0&&m.push(this)},b.prototype._unregisterInstance=function(){var a=m.indexOf(this);-1!=a&&m.splice(a,1)},window.IntersectionObserver=b,window.IntersectionObserverEntry=a}}(),function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.ResizeObserver=b()}(this,function(){"use strict";function a(a,b){function c(){f&&(f=!1,a()),g&&e()}function d(){n(c)}function e(){var a=Date.now();if(f){if(a-h<o)return;g=!0}else f=!0,g=!1,setTimeout(d,b);h=a}var f=!1,g=!1,h=0;return e}function b(a){return parseFloat(a)||0}function c(a){for(var c=[],d=1;d<arguments.length;d++)c[d-1]=arguments[d];return c.reduce(function(c,d){return c+b(a["border-"+d+"-width"])},0)}function d(a){for(var c=["top","right","bottom","left"],d={},e=0,f=c;e<f.length;e++){var g=f[e],h=a["padding-"+g];d[g]=b(h)}return d}function e(a){var b=a.getBBox();return j(0,0,b.width,b.height)}function f(a){var e=a.clientWidth,f=a.clientHeight;if(!e&&!f)return v;var h=u(a).getComputedStyle(a),i=d(h),k=i.left+i.right,l=i.top+i.bottom,m=b(h.width),n=b(h.height);if("border-box"===h.boxSizing&&(Math.round(m+k)!==e&&(m-=c(h,"left","right")+k),Math.round(n+l)!==f&&(n-=c(h,"top","bottom")+l)),!g(a)){var o=Math.round(m+k)-e,p=Math.round(n+l)-f;1!==Math.abs(o)&&(m-=o),1!==Math.abs(p)&&(n-=p)}return j(i.left,i.top,m,n)}function g(a){return a===u(a).document.documentElement}function h(a){return l?w(a)?e(a):f(a):v}function i(a){var b=a.x,c=a.y,d=a.width,e=a.height,f="undefined"!=typeof DOMRectReadOnly?DOMRectReadOnly:Object,g=Object.create(f.prototype);return t(g,{x:b,y:c,width:d,height:e,top:c,right:b+d,bottom:e+c,left:b}),g}function j(a,b,c,d){return{x:a,y:b,width:c,height:d}}var k=function(){function a(a,b){var c=-1;return a.some(function(a,d){return a[0]===b&&(c=d,!0)}),c}return"undefined"!=typeof Map?Map:function(){function b(){this.__entries__=[]}return Object.defineProperty(b.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),b.prototype.get=function(b){var c=a(this.__entries__,b),d=this.__entries__[c];return d&&d[1]},b.prototype.set=function(b,c){var d=a(this.__entries__,b);~d?this.__entries__[d][1]=c:this.__entries__.push([b,c])},b.prototype.delete=function(b){var c=this.__entries__,d=a(c,b);~d&&c.splice(d,1)},b.prototype.has=function(b){return!!~a(this.__entries__,b)},b.prototype.clear=function(){this.__entries__.splice(0)},b.prototype.forEach=function(a,b){void 0===b&&(b=null);for(var c=0,d=this.__entries__;c<d.length;c++){var e=d[c];a.call(b,e[1],e[0])}},b}()}(),l="undefined"!=typeof window&&"undefined"!=typeof document&&window.document===document,m=function(){return"undefined"!=typeof global&&global.Math===Math?global:"undefined"!=typeof self&&self.Math===Math?self:"undefined"!=typeof window&&window.Math===Math?window:Function("return this")()}(),n=function(){return"function"==typeof requestAnimationFrame?requestAnimationFrame.bind(m):function(a){return setTimeout(function(){return a(Date.now())},1e3/60)}}(),o=2,p=20,q=["top","right","bottom","left","width","height","size","weight"],r="undefined"!=typeof MutationObserver,s=function(){function b(){this.connected_=!1,this.mutationEventsAdded_=!1,this.mutationsObserver_=null,this.observers_=[],this.onTransitionEnd_=this.onTransitionEnd_.bind(this),this.refresh=a(this.refresh.bind(this),p)}return b.prototype.addObserver=function(a){~this.observers_.indexOf(a)||this.observers_.push(a),this.connected_||this.connect_()},b.prototype.removeObserver=function(a){var b=this.observers_,c=b.indexOf(a);~c&&b.splice(c,1),!b.length&&this.connected_&&this.disconnect_()},b.prototype.refresh=function(){this.updateObservers_()&&this.refresh()},b.prototype.updateObservers_=function(){var a=this.observers_.filter(function(a){return a.gatherActive(),a.hasActive()});return a.forEach(function(a){return a.broadcastActive()}),a.length>0},b.prototype.connect_=function(){l&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),r?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},b.prototype.disconnect_=function(){l&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},b.prototype.onTransitionEnd_=function(a){var b=a.propertyName,c=void 0===b?"":b;q.some(function(a){return!!~c.indexOf(a)})&&this.refresh()},b.getInstance=function(){return this.instance_||(this.instance_=new b),this.instance_},b.instance_=null,b}(),t=function(a,b){for(var c=0,d=Object.keys(b);c<d.length;c++){var e=d[c];Object.defineProperty(a,e,{value:b[e],enumerable:!1,writable:!1,configurable:!0})}return a},u=function(a){return a&&a.ownerDocument&&a.ownerDocument.defaultView||m},v=j(0,0,0,0),w=function(){return"undefined"!=typeof SVGGraphicsElement?function(a){return a instanceof u(a).SVGGraphicsElement}:function(a){return a instanceof u(a).SVGElement&&"function"==typeof a.getBBox}}(),x=function(){function a(a){this.broadcastWidth=0,this.broadcastHeight=0,this.contentRect_=j(0,0,0,0),this.target=a}return a.prototype.isActive=function(){var a=h(this.target);return this.contentRect_=a,a.width!==this.broadcastWidth||a.height!==this.broadcastHeight},a.prototype.broadcastRect=function(){var a=this.contentRect_;return this.broadcastWidth=a.width,this.broadcastHeight=a.height,a},a}(),y=function(){function a(a,b){var c=i(b);t(this,{target:a,contentRect:c})}return a}(),z=function(){function a(a,b,c){if(this.activeObservations_=[],this.observations_=new k,"function"!=typeof a)throw new TypeError("The callback provided as parameter 1 is not a function.");this.callback_=a,this.controller_=b,this.callbackCtx_=c}return a.prototype.observe=function(a){if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");if("undefined"!=typeof Element&&Element instanceof Object){if(!(a instanceof u(a).Element))throw new TypeError('parameter 1 is not of type "Element".');var b=this.observations_;b.has(a)||(b.set(a,new x(a)),this.controller_.addObserver(this),this.controller_.refresh())}},a.prototype.unobserve=function(a){if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");if("undefined"!=typeof Element&&Element instanceof Object){if(!(a instanceof u(a).Element))throw new TypeError('parameter 1 is not of type "Element".');var b=this.observations_;b.has(a)&&(b.delete(a),b.size||this.controller_.removeObserver(this))}},a.prototype.disconnect=function(){this.clearActive(),this.observations_.clear(),this.controller_.removeObserver(this)},a.prototype.gatherActive=function(){var a=this;this.clearActive(),this.observations_.forEach(function(b){b.isActive()&&a.activeObservations_.push(b)})},a.prototype.broadcastActive=function(){if(this.hasActive()){var a=this.callbackCtx_,b=this.activeObservations_.map(function(a){return new y(a.target,a.broadcastRect())});this.callback_.call(a,b,a),this.clearActive()}},a.prototype.clearActive=function(){this.activeObservations_.splice(0)},a.prototype.hasActive=function(){return this.activeObservations_.length>0},a}(),A="undefined"!=typeof WeakMap?new WeakMap:new k,B=function(){function a(b){if(!(this instanceof a))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var c=s.getInstance(),d=new z(b,c,this);A.set(this,d)}return a}();return["observe","unobserve","disconnect"].forEach(function(a){B.prototype[a]=function(){var b;return(b=A.get(this))[a].apply(b,arguments)}}),function(){return void 0!==m.ResizeObserver?m.ResizeObserver:B}()}),function(a,b){b.$=a}(jQuery,window.FooGallery=window.FooGallery||{}),function(a){if(!a)return void console.warn("jQuery must be included in the page prior to the FooGallery.utils library.");(function(){try{return!!window.FooGallery.utils}catch(a){return!1}})()||(window.FooGallery.utils={$:a,version:"1.0.0"})}(jQuery),function(a,b){"1.0.0"===b.version&&(b.is={},b.is.array=function(a){return"[object Array]"===Object.prototype.toString.call(a)},b.is.boolean=function(a){return"[object Boolean]"===Object.prototype.toString.call(a)},b.is.element=function(a){return"object"===("undefined"==typeof HTMLElement?"undefined":_typeof(HTMLElement))?a instanceof HTMLElement:!!a&&"object"===_typeof(a)&&1===a.nodeType&&"string"==typeof a.nodeName},b.is.empty=function(a){if(b.is.undef(a)||null===a)return!0;if(b.is.number(a)&&0===a)return!0;if(b.is.boolean(a)&&!1===a)return!0;if(b.is.string(a)&&0===a.length)return!0;if(b.is.array(a)&&0===a.length)return!0;if(b.is.jq(a)&&0===a.length)return!0;if(b.is.hash(a)){for(var c in a)if(a.hasOwnProperty(c))return!1;return!0}return!1},b.is.error=function(a){return"[object Error]"===Object.prototype.toString.call(a)},b.is.fn=function(a){return a===window.alert||"[object Function]"===Object.prototype.toString.call(a)},b.is.hash=function(a){return b.is.object(a)&&a.constructor===Object&&!a.nodeType&&!a.setInterval},b.is.jq=function(c){return!b.is.undef(a)&&c instanceof a},b.is.number=function(a){return"[object Number]"===Object.prototype.toString.call(a)&&!isNaN(a)},b.is.object=function(a){return"[object Object]"===Object.prototype.toString.call(a)&&!b.is.undef(a)&&null!==a},b.is.promise=function(a){return b.is.object(a)&&b.is.fn(a.then)&&b.is.fn(a.promise)},b.is.size=function(a){return!!(b.is.string(a)&&!b.is.empty(a)||b.is.number(a))&&/^(auto|none|(?:[\d.]*)+?(?:%|px|mm|q|cm|in|pt|pc|em|ex|ch|rem|vh|vw|vmin|vmax)?)$/.test(a)},b.is.string=function(a){return"[object String]"===Object.prototype.toString.call(a)},b.is.undef=function(a){return void 0===a})}(FooGallery.utils.$,FooGallery.utils),function(a,b,c){if("1.0.0"===b.version){b.fn={};var d=Function.prototype.toString;b.fn.CONTAINS_SUPER=/xyz/.test(d.call(function(){xyz}))?/\b_super\b/:/.*/,b.fn.noop=function(){},b.fn.addOrOverride=function(a,e,f){if(c.object(a)&&c.string(e)&&!c.empty(e)&&c.fn(f)){var g=a[e],h=c.fn(g)&&b.fn.CONTAINS_SUPER.test(d.call(f));a[e]=h?function(a,b){return function(){var c=this._super;this._super=a;var d=b.apply(this,arguments);return this._super=c,d}}(g,f):f}},b.fn.expose=function(a,b,d,e){c.object(a)&&c.object(b)&&c.array(d)&&(e=c.undef(e)?a:e,d.forEach(function(d){c.string(d)&&c.fn(a[d])&&(b[d]=a[d].bind(e))}))},b.fn.apply=function(a,b){return b.unshift(a),new(Function.prototype.bind.apply(a,b))},b.fn.arg2arr=function(a){return Array.prototype.slice.call(a)},b.fn.debounce=function(a,c){var d;return function(){var e=this,f=b.fn.arg2arr(arguments);clearTimeout(d),d=setTimeout(function(){a.apply(e,f)},c)}},b.fn.throttle=function(a,c){var d,e;return function(){var f=this,g=b.fn.arg2arr(arguments);d?(clearTimeout(e),e=setTimeout(function(){Date.now()-d>=c&&(a.apply(f,g),d=Date.now())},c-(Date.now()-d))):(a.apply(f,g),d=Date.now())}},b.fn.resolved=a.Deferred().resolve().promise(),b.fn.rejected=a.Deferred().reject().promise(),b.fn.reject=function(c,d){var e=a.Deferred(),f=b.fn.arg2arr(arguments);return e.reject.apply(e,f).promise()},b.fn.resolve=function(c,d){var e=a.Deferred(),f=b.fn.arg2arr(arguments);return e.resolve.apply(e,f).promise()},b.fn.rejectWith=function(c,d,e){var f=a.Deferred(),g=b.fn.arg2arr(arguments);return g.shift(),f.rejectWith(c,g).promise()},b.fn.resolveWith=function(c,d,e){var f=a.Deferred(),g=b.fn.arg2arr(arguments);return g.shift(),f.resolveWith(c,g).promise()},b.fn.all=function(d){var e=a.Deferred(),f=[];return c.array(d)&&d.length>0?function(){for(var a=function(a,b){h||(f[a]=0===b.length?void 0:1===b.length?b[0]:b,--g||e.resolve(f))},g=d.length,h=!1,i=0,j=d.length;i<j;i++){if("break"===function(){if(h)return"break";var f=i;c.promise(d[f])?d[f].then(function(){a(f,b.fn.arg2arr(arguments))},function(){h||(h=!0,e.reject.apply(e,b.fn.arg2arr(arguments)))}):a(f,[d[f]])}())break}}():e.resolve(f),e.promise()},b.fn.allSettled=function(d){var e=a.Deferred(),f=[];return c.array(d)&&d.length>0?function(){for(var a=function(a,b,c){if(f[a]={status:b},c.length>0){var d="rejected"===b?"reason":"value";f[a][d]=1===c.length?c[0]:c}--g||e.resolve(f)},g=d.length,h=0,i=d.length;h<i;h++)!function(){var e=h;c.promise(d[e])?d[e].then(function(){a(e,"fulfilled",b.fn.arg2arr(arguments))},function(){a(e,"rejected",b.fn.arg2arr(arguments))}):a(e,"fulfilled",[d[e]])}()}():e.resolve(f),e.promise()}}}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b){if("1.0.0"===a.version){a.url={};var c=document.createElement("a");a.url.parts=function(a){c.href=a;var b=c.port?c.port:-1!==["http:","https:"].indexOf(c.protocol)?"https:"===c.protocol?"443":"80":"",d=c.hostname+(b?":"+b:""),e=c.origin?c.origin:c.protocol+"//"+d,f="/"===c.pathname.slice(0,1)?c.pathname:"/"+c.pathname;return{hash:c.hash,host:d,hostname:c.hostname,href:c.href,origin:e,pathname:f,port:b,protocol:c.protocol,search:c.search}},a.url.full=function(a){return!b.string(a)||b.empty(a)?null:(c.href=a,c.href)},a.url.param=function(a,c,d){if(!b.string(a)||!b.string(c)||b.empty(c))return a;var e,f,g,h;return b.undef(d)?(e=new RegExp("[?|&]"+c+"=([^&;]+?)(&|#|;|$)"),f=e.exec(a)||["",""],g=f[1].replace(/\+/g,"%20"),b.string(g)&&!b.empty(g)?decodeURIComponent(g):null):(b.empty(d)?(e=new RegExp("^([^#]*?)(([^#]*)&)?"+c+"(=[^&#]*)?(&|#|$)"),g=a.replace(e,"$1$3$5").replace(/^([^#]*)((\?)&|\?(#|$))/,"$1$3$4")):(e=new RegExp("([?&])"+c+"[^&]*"),h=c+"="+encodeURIComponent(d),(g=a.replace(e,"$1"+h))!==a||e.test(g)||(g+=(-1!==g.indexOf("?")?"&":"?")+h)),g)}}}(FooGallery.utils,FooGallery.utils.is),function(a,b,c){"1.0.0"===a.version&&(a.str={},a.str.trim=function(a){return b.string(a)?a.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,""):null},a.str.camel=function(a){return b.string(a)?a.toUpperCase()===a?a.toLowerCase():a.replace(/^([A-Z])|[-\s_]+(\w)/g,function(a,c,d){return b.string(d)?d.toUpperCase():c.toLowerCase()}):a},a.str.kebab=function(a){return b.string(a)?a.match(/[A-Z]{2,}(?=[A-Z][a-z0-9]*|\b)|[A-Z]?[a-z0-9]*|[A-Z]|[0-9]+/g).filter(Boolean).map(function(a){return a.toLowerCase()}).join("-"):a},a.str.contains=function(a,c,d){return!(!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c))&&(c.length<=a.length&&-1!==(d?a.toUpperCase().indexOf(c.toUpperCase()):a.indexOf(c)))},a.str.containsWord=function(a,c,d){if(!b.string(a)||b.empty(a)||!b.string(c)||b.empty(c)||a.length<c.length)return!1;for(var e=a.split(/\W/),f=0,g=e.length;f<g;f++)if(d?e[f].toUpperCase()===c.toUpperCase():e[f]===c)return!0;return!1},a.str.endsWith=function(a,c){return!(!b.string(a)||!b.string(c)||c.length>a.length)&&a.slice(a.length-c.length)===c},a.str.startsWith=function(a,c){return!b.empty(a)&&!b.empty(c)&&a.slice(0,c.length)===c},a.str.escapeRegExp=function(a){return b.string(a)?a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"):a},a.str.fnv1a=function(a){if(!b.string(a)||b.empty(a))return null;var c,d,e=2166136261;for(c=0,d=a.length;c<d;c++)e^=a.charCodeAt(c),e+=(e<<1)+(e<<4)+(e<<7)+(e<<8)+(e<<24);return e>>>0},a.str.from=function(b,c){return a.str.contains(b,c)?b.substring(b.indexOf(c)+c.length):null},a.str.join=function(d,e,f){if(!b.string(d)||!b.string(e))return null;var g=c.arg2arr(arguments);d=g.shift();var h,i,j=g.shift();for(h=0,i=g.length;h<i;h++)e=g[h],b.empty(e)||(a.str.endsWith(j,d)&&(j=j.slice(0,j.length-d.length)),a.str.startsWith(e,d)&&(e=e.slice(d.length)),j+=d+e);return j},a.str.until=function(b,c){return a.str.contains(b,c)?b.substring(0,b.indexOf(c)):b},a.str.format=function(d,e,f){var g=c.arg2arr(arguments);return d=g.shift(),b.string(d)&&g.length>0&&(1===g.length&&(b.array(g[0])||b.object(g[0]))&&(g=g[0]),a.each(g,function(a,b){d=d.replace(new RegExp("\\{"+b+"\\}","gi"),a+"")})),d})}(FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d,e){"1.0.0"===b.version&&(b.obj={},b.obj.create=function(a){function b(){}if(!c.object(a))throw TypeError("Argument must be an object");return b.prototype=a,new b},b.obj.extend=function(a,e,f){a=c.object(a)?a:{};var g=d.arg2arr(arguments);return g.shift(),b.each(g,function(c){b.obj.merge(a,c)}),a},b.obj.merge=function(a,d){a=c.hash(a)?a:{},d=c.hash(d)?d:{};for(var e in d)d.hasOwnProperty(e)&&(c.hash(d[e])?(a[e]=c.hash(a[e])?a[e]:{},b.obj.merge(a[e],d[e])):c.array(d[e])?a[e]=d[e].slice():a[e]=d[e]);return a},b.obj.mergeValid=function(a,d,e,f){if(!c.hash(e)||!c.hash(d))return a;d=c.hash(d)?d:{},f=c.hash(f)?f:{};var g,h,i;for(g in d)d.hasOwnProperty(g)&&c.fn(d[g])&&(h=c.array(f[g])?f[g]:c.string(f[g])?[f[g]]:[g],b.each(h,function(f){if(i=b.obj.prop(e,f),!c.undef(i))return d[g](i)?(b.obj.prop(a,g,i),!1):void 0}));return a},b.obj.prop=function(a,d,f){if(c.object(a)&&!c.empty(d)){var g,h;if(c.undef(f))return e.contains(d,".")?(g=d.split("."),h=g.length-1,b.each(g,function(b,d){if(d===h)f=a[b];else{if(!c.hash(a[b]))return!1;a=a[b]}})):c.undef(a[d])||(f=a[d]),f;e.contains(d,".")?(g=d.split("."),h=g.length-1,b.each(g,function(b,d){d===h?a[b]=f:a=c.hash(a[b])?a[b]:a[b]={}})):c.undef(a[d])||(a[d]=f)}})}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c){function d(a){return setTimeout(a,1e3/60)}function e(a){clearTimeout(a)}"1.0.0"===b.version&&(b.ready=function(a){function c(){try{a.call(window,b.$)}catch(a){console.error(a)}}(Function("/*@cc_on return true@*/")()?"complete"===document.readyState:"loading"!==document.readyState)?c():document.addEventListener("DOMContentLoaded",c,!1)},b.find=function(a,b,d){if(c.fn(b)){d=c.undef(d)?b:d;var e,f;if(c.array(a)){for(e=0,f=a.length;e<f;e++)if(b.call(d,a[e],e,a))return a[e]}else if(c.object(a)){var g=Object.keys(a);for(e=0,f=g.length;e<f;e++)if(b.call(d,a[g[e]],g[e],a))return a[g[e]]}}},b.each=function(a,b,d){if(c.fn(b)){d=c.undef(d)?b:d;var e,f;if(c.array(a))for(e=0,f=a.length;e<f&&!1!==b.call(d,a[e],e,a);e++);else if(c.object(a)){var g=Object.keys(a);for(e=0,f=g.length;e<f&&!1!==b.call(d,a[g[e]],g[e],a);e++);}}},b.inArray=function(a,b){return c.array(b)?b.indexOf(a):-1},b.selectify=function(a){if(c.empty(a))return null;if(c.hash(a)){var d,e={};for(var f in a)a.hasOwnProperty(f)&&(d=b.selectify(a[f]))&&(e[f]=d);return e}return c.string(a)||c.array(a)?(c.string(a)&&(a=[a]),a.map(function(a){return c.string(a)?"."+a.split(/\s/g).join("."):null}).join(",")):null},b.requestFrame=(window.requestAnimationFrame||window.webkitRequestAnimationFrame||d).bind(window),b.cancelFrame=(window.cancelAnimationFrame||window.webkitCancelAnimationFrame||e).bind(window),b.nextFrame=function(d,e){return a.Deferred(function(a){c.fn(d)?(e=c.undef(e)?d:e,b.requestFrame(function(){try{a.resolve(d.call(e))}catch(b){a.reject(b)}})):a.reject(new Error("Provided callback is not a function."))}).promise()})}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d,e){function f(a,b){return c.array(b)||(b=[]),c.fn(a)&&null!==a.__baseClass__?(b.unshift(a.__baseClass__),f(a.__baseClass__,b)):b}"1.0.0"===b.version&&(b.Class=function(){},b.Class.extend=function(a){function f(){if(!c.fn(this.construct))throw new SyntaxError('FooGallery.utils.Class objects must be constructed with the "new" keyword.');this.construct.apply(this,arguments)}a=c.hash(a)?a:{};var g=d.create(this.prototype);for(var h in a)a.hasOwnProperty(h)&&e.addOrOverride(g,h,a[h]);return g.construct=c.fn(g.construct)?g.construct:function(){},f.prototype=g,f.prototype.constructor=c.fn(g.__ctor__)?g.__ctor__:f,f.extend=b.Class.extend,f.override=b.Class.override,f.getBaseClasses=b.Class.getBaseClasses,f.__baseClass__=this,f},b.Class.override=function(a,b){e.addOrOverride(this.prototype,a,b)},b.Class.__baseClass__=null,b.Class.getBaseClasses=function(){return f(this,[])})}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj,FooGallery.utils.fn),function(a,b,c,d,e){b.ClassRegistry=b.Class.extend({construct:function(a){var b=this;b.opt=e.extend({allowBase:!0,beforeCreate:null},a),b.registered={}},register:function(a,b,d,e){var f=this;if(c.string(a)&&!c.empty(a)&&c.fn(b)){e=c.number(e)?e:0;var g=f.registered[a];return f.registered[a]={name:a,ctor:b,config:c.hash(d)?d:{},priority:c.undef(g)?e:g.priority},!0}return!1},each:function(a,b,d){b=!!c.boolean(b)&&b,d=c.undef(d)?a:d;var e=this,f=Object.keys(e.registered),g=f.map(function(a){return e.registered[a]});b&&g.sort(function(a,b){return b.priority-a.priority});for(var h=0,i=g.length;h<i;h++){if(!1===a.call(d,g[h],h))break}},find:function(a,b,d){b=!!c.boolean(b)&&b,d=c.undef(d)?a:d;var e=this,f=Object.keys(e.registered),g=f.map(function(a){return e.registered[a]});b&&g.sort(function(a,b){return b.priority-a.priority});for(var h=0,i=g.length;h<i;h++)if(a.call(d,g[h],h))return g[h];return null},create:function(a,b,e){var f=this,g=d.arg2arr(arguments);if(a=g.shift(),c.string(a)&&f.registered.hasOwnProperty(a)){var h=f.registered[a],i=!0;if(h.priority<0&&!f.opt.allowBase&&(i=!1),i&&c.fn(h.ctor))return b=g.shift(),b=f.mergeConfigurations(h.name,b),g.unshift.apply(g,[h.name,b]),d.apply(h.ctor,f.onBeforeCreate(h,g))}return null},onBeforeCreate:function(a,b){var d=this;return null!==d.opt.beforeCreate&&c.fn(d.opt.beforeCreate)?d.opt.beforeCreate.call(d,a,b):b},mergeConfigurations:function(a,b){var d=this;if(c.string(a)&&d.registered.hasOwnProperty(a)){b=c.hash(b)?b:{};var f=d.getBaseClasses(a),g=[{}];return f.push(d.registered[a]),f.forEach(function(a){g.push(a.config)}),g.push(b),e.extend.apply(e,g)}return{}},getBaseClass:function(){return this.find(function(a){return a.priority<0},!0)},getBaseClasses:function(a){var b=this,d=b.registered[a],e=[];return c.undef(d)||d.ctor.getBaseClasses().forEach(function(a){var d=b.fromType(a);c.hash(d)&&e.push(d)}),e},fromType:function(a){if(c.fn(a))return this.find(function(b){return b.ctor===a})}})}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c){"1.0.0"===a.version&&(a.Event=a.Class.extend({construct:function(c){if(b.empty(c))throw new SyntaxError("FooGallery.utils.Event objects must be supplied a `type`.");var d=this,e=a.Event.parse(c);d.type=e.type,d.namespace=e.namespace,d.defaultPrevented=!1,d.target=null},preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return this.defaultPrevented}}),a.Event.parse=function(a){a=b.string(a)&&!b.empty(a)?a:null;var d=c.contains(a,".");return{namespaced:d,type:d?c.startsWith(a,".")?null:c.until(a,"."):a,namespace:d?c.from(a,"."):null}},a.EventClass=a.Class.extend({construct:function(){this.events={}},destroy:function(){this.events={}},on:function(a,c,d){var e=this;return b.object(a)?(d=c,Object.keys(a).forEach(function(c){b.fn(a[c])&&c.split(" ").forEach(function(b){e.addListener(b,a[c],d)})})):b.string(a)&&b.fn(c)&&a.split(" ").forEach(function(a){e.addListener(a,c,d)}),e},addListener:function(c,d,e){if(!b.string(c)||/\s/.test(c)||!b.fn(d))return!1;var f=this,g=a.Event.parse(c);return e=b.undef(e)?f:e,b.array(f.events[g.type])||(f.events[g.type]=[]),!f.events[g.type].some(function(a){return a.namespace===g.namespace&&a.fn===d&&a.thisArg===e})&&(f.events[g.type].push({namespace:g.namespace,fn:d,thisArg:e}),!0)},off:function(a,c,d){var e=this;return b.object(a)?(d=c,Object.keys(a).forEach(function(b){b.split(" ").forEach(function(c){e.removeListener(c,a[b],d)})})):b.string(a)&&a.split(" ").forEach(function(a){e.removeListener(a,c,d)}),e},removeListener:function(c,d,e){if(!b.string(c)||/\s/.test(c))return!1;var f=this,g=a.Event.parse(c),h=[];return e=b.undef(e)?f:e,b.empty(g.type)?b.empty(g.namespace)||h.push.apply(h,Object.keys(f.events)):h.push(g.type),h.forEach(function(a){b.array(f.events[a])&&(f.events[a]=f.events[a].filter(function(a){return null!=d?!(a.namespace===g.namespace&&a.fn===d&&a.thisArg===e):null!=g.namespace&&a.namespace!==g.namespace}),0===f.events[a].length&&delete f.events[a])}),!0},trigger:function(c,d){d=b.array(d)?d:[];var e=this,f=[];return c instanceof a.Event?(f.push(c),e.emit(c,d)):b.string(c)&&c.split(" ").forEach(function(b){var c=new a.Event(b);f.push(c),e.emit(c,d)}),b.empty(f)?null:1===f.length?f[0]:f},emit:function(a,c){if(a instanceof FooGallery.utils.Event){var d=this;c=b.array(c)?c:[],null===a.target&&(a.target=d),b.array(d.events[a.type])&&d.events[a.type].forEach(function(b){null!=a.namespace&&b.namespace!==a.namespace||b.fn.apply(b.thisArg,[a].concat(c))}),b.array(d.events.__all__)&&d.events.__all__.forEach(function(b){b.fn.apply(b.thisArg,[a].concat(c))})}}}))}(FooGallery.utils,FooGallery.utils.is,FooGallery.utils.str),function(a,b,c,d,e){"1.0.0"===b.version&&(b.Timer=b.EventClass.extend({construct:function(a){var b=this;b._super(),b.interval=c.number(a)?a:1e3,
10
+ b.isRunning=!1,b.isPaused=!1,b.canResume=!1,b.canRestart=!1,b.__timeout=null,b.__decrement=!1,b.__time=0,b.__remaining=0,b.__current=0,b.__finish=0,b.__restart=[]},__reset:function(){var a=this;clearTimeout(a.__timeout),a.__timeout=null,a.__decrement=!1,a.__time=0,a.__remaining=0,a.__current=0,a.__finish=0,a.isRunning=!1,a.isPaused=!1,a.canResume=!1},__eventArgs:function(a){var b=this;return[b.__current,b.__time,b.__decrement].concat(d.arg2arr(arguments))},__tick:function(){var a=this;a.trigger("tick",a.__eventArgs()),a.__current===a.__finish?(a.trigger("complete",a.__eventArgs()),a.__reset()):(a.__decrement?a.__current--:a.__current++,a.__remaining--,a.canResume=a.__remaining>0,a.__timeout=setTimeout(function(){a.__tick()},a.interval))},start:function(a,b){var d=this;d.isRunning||(b=!!c.boolean(b)&&b,d.__restart=[a,b],d.__decrement=b,d.__time=a,d.__remaining=a,d.__current=b?a:0,d.__finish=b?0:a,d.canRestart=!0,d.isRunning=!0,d.isPaused=!1,d.trigger("start",d.__eventArgs()),d.__tick())},countdown:function(a){this.start(a,!0)},countup:function(a){this.start(a,!1)},restart:function(){var a=this;a.stop(),a.canRestart&&a.start.apply(a,a.__restart)},stop:function(){var a=this;(a.isRunning||a.isPaused)&&(a.__reset(),a.trigger("stop",a.__eventArgs()))},pause:function(){var a=this;return null!=a.__timeout&&(clearTimeout(a.__timeout),a.__timeout=null),a.isRunning&&(a.isRunning=!1,a.isPaused=!0,a.trigger("pause",a.__eventArgs())),a.__remaining},resume:function(){var a=this;a.canResume&&(a.isRunning=!0,a.isPaused=!1,a.trigger("resume",a.__eventArgs()),a.__tick())},reset:function(){var a=this;a.__reset(),a.trigger("reset",this.__eventArgs())}}))}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c){"1.0.0"===b.version&&(b.FullscreenAPI=b.EventClass.extend({construct:function(){this._super(),this.apis={w3:{enabled:"fullscreenEnabled",element:"fullscreenElement",request:"requestFullscreen",exit:"exitFullscreen",events:{change:"fullscreenchange",error:"fullscreenerror"}},webkit:{enabled:"webkitFullscreenEnabled",element:"webkitCurrentFullScreenElement",request:"webkitRequestFullscreen",exit:"webkitExitFullscreen",events:{change:"webkitfullscreenchange",error:"webkitfullscreenerror"}},moz:{enabled:"mozFullScreenEnabled",element:"mozFullScreenElement",request:"mozRequestFullScreen",exit:"mozCancelFullScreen",events:{change:"mozfullscreenchange",error:"mozfullscreenerror"}},ms:{enabled:"msFullscreenEnabled",element:"msFullscreenElement",request:"msRequestFullscreen",exit:"msExitFullscreen",events:{change:"MSFullscreenChange",error:"MSFullscreenError"}}},this.api=this.getAPI(),this.supported=null!=this.api,this.__listen()},destroy:function(){return this.__stopListening(),this._super()},getAPI:function(){for(var a in this.apis)if(this.apis.hasOwnProperty(a)&&this.apis[a].enabled in document)return this.apis[a];return null},element:function(){return this.supported?document[this.api.element]:null},request:function(b){if(this.supported&&b[this.api.request]){var d=b[this.api.request]();return d||a.Deferred(this.__resolver(this.api.request)).promise()}return c.rejected},exit:function(){if(this.supported&&this.element()){var b=document[this.api.exit]();return b||a.Deferred(this.__resolver(this.api.exit)).promise()}return c.rejected},toggle:function(a){return this.element()?this.exit():this.request(a)},__listen:function(){var b=this;b.supported&&a(document).on(b.api.events.change+".utils",function(){b.trigger("change")}).on(b.api.events.error+".utils",function(){b.trigger("error")})},__stopListening:function(){var b=this;b.supported&&a(document).off(b.api.events.change+".utils").off(b.api.events.error+".utils")},__resolver:function(b){var c=this;return function(d){function e(){d.resolve(),a(document).off(c.api.events.change,e).off(c.api.events.error,f)}function f(){d.reject(new TypeError),a(document).off(c.api.events.change,e).off(c.api.events.error,f)}if(b===c.api.exit&&c.element())return void setTimeout(function(){d.reject(new TypeError)},1);a(document).on(c.api.events.change,e).on(c.api.events.error,f)}}}))}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.fn),function(a,b,c,d){"1.0.0"===b.version&&(b.transition={},b.transition.dataName="__foo-transition__",b.transition.disableClassName=null,b.transition.timeout=3e3,b.transition.disable=function(d,e){var f=c.jq(d)?d:a(d);if(f.length>0&&c.fn(e)){var g=f.get(0),h=c.string(b.transition.disableClassName),i=null;h?f.addClass(b.transition.disableClassName):(i={value:g.style.getPropertyValue("transition"),priority:g.style.getPropertyPriority("transition")},g.style.setProperty("transition","none","important")),e.call(e,f),f.prop("offsetWidth"),h?f.removeClass(b.transition.disableClassName):(g.style.removeProperty("transition"),c.string(i.value)&&i.value.length>0&&g.style.setProperty("transition",i.value,i.priority))}},b.transition.stop=function(d){var e=a.Deferred(),f=c.jq(d)?d:a(d);if(f.length>0){var g=f.data(b.transition.dataName);c.promise(g)?g.always(function(){b.requestFrame(function(){e.resolve(f)})}).reject(new Error("Transition cancelled.")):e.resolve(f)}else e.reject(new Error("Unable to stop transition. Make sure the element exists."));return e.promise()},b.transition.createListener=function(a,b,e){var f=a,g=b,h=e,i=c.string(e);return function(a){var b=a.originalEvent instanceof TransitionEvent?a.originalEvent:a,c=!1;b.target===f&&(c=!i||b.propertyName===h),c&&g.apply(g,d.arg2arr(arguments))}},b.transition.start=function(d,e,f,g){var h=a.Deferred(),i=c.jq(d)?d:a(d);if(i.length>0&&c.fn(e)){var j=i.get(0);b.transition.stop(i).always(function(){var a=b.transition.createListener(j,function(){h.resolve(i)},f);i.data(b.transition.dataName,h).on("transitionend.foo-utils",a).prop("offsetWidth"),b.requestFrame(function(){var d=setTimeout(function(){h.reject(new Error("Transition safety timeout triggered."))},c.number(g)?g:b.transition.timeout);h.always(function(){clearTimeout(d),i.removeData(b.transition.dataName).off("transitionend.foo-utils",a)}),e.call(e,i)})})}else h.reject(new Error("Unable to perform transition. Make sure the element exists and a trigger function is supplied."));return h.promise()},b.transition.modify=function(e,f,g,h){var i=c.jq(e)?e:a(e);return i.length>0&&c.fn(f)?g?(b.transition.disable(i,f),d.resolve()):b.transition.start(i,f,h):d.reject(new Error("Unable to perform modification. Make sure the element exists and a modify function is supplied."))})}(FooGallery.utils.$,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d,e,f){b.DATA_TEMPLATE="__FooGallery__",b.DATA_ITEM="__FooGalleryItem__",b.get=function(c){return a(c).data(b.DATA_TEMPLATE)},b.init=function(c,f){if(f=d.jq(f)?f:a(f),f.length>0){var g=f.data(b.DATA_TEMPLATE);if(g instanceof b.Template)return g.destroy(!0).then(function(){var a=b.template.make(c,f);return a instanceof b.Template?a.initialize():e.rejected})}var h=b.template.make(c,f);return h instanceof b.Template?h.initialize():e.rejected},a.fn.foogallery=function(c,e){return e=d.fn(e)?e:a.noop,this.each(function(f,g){if(d.string(c)){var h=a.data(g,b.DATA_TEMPLATE);if(h instanceof b.Template)switch(c){case"layout":return void h.layout();case"destroy":return void h.destroy()}}else b.init(c,g).then(e)})},b.isCached=function(a){var b=new Image;b.src=a;var c=b.complete;return b.src="",b=null,c},b.supportedExifProperties=["camera","aperture","created_timestamp","shutter_speed","focal_length","iso","orientation"],d.exif=function(a){if(d.object(a)){var c=Object.keys(a);return c.length>0&&c.some(function(c){return-1!==b.supportedExifProperties.indexOf(c)&&!d.empty(a[c])})}return!1},f.trimTo=function(a,b,c){return d.string(a)&&d.number(b)&&b>0&&a.length>b?a.substr(0,b)+(d.string(c)?c:"&hellip;"):a},c.getResizeObserverSize=function(a){var b,c;return a.contentBoxSize?a.contentBoxSize[0]?(b=a.contentBoxSize[0].inlineSize,c=a.contentBoxSize[0].blockSize):(b=a.contentBoxSize.inlineSize,c=a.contentBoxSize.blockSize):(b=a.contentRect.width,c=a.contentRect.height),{width:b,height:c}},b.supportsWebP=!1;var g=new Image;g.onload=function(){b.supportsWebP=0<g.width&&0<g.height},g.onerror=function(){b.supportsWebP=!1},g.src="data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA=="}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c,d,e){b.Icons=c.Class.extend({construct:function(){this.className="fg-icon",this.registered={default:{close:'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.957 3.457l-1.414-1.414-4.543 4.543-4.543-4.543-1.414 1.414 4.543 4.543-4.543 4.543 1.414 1.414 4.543-4.543 4.543 4.543 1.414-1.414-4.543-4.543z"></path></svg>',"arrow-left":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M10.5 16l1.5-1.5-6.5-6.5 6.5-6.5-1.5-1.5-8 8 8 8z"></path></svg>',"arrow-right":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M5.5 0l-1.5 1.5 6.5 6.5-6.5 6.5 1.5 1.5 8-8-8-8z"></path></svg>',maximize:'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M2 2v4h-2v-5c0-0.552 0.448-1 1-1h14c0.552 0 1 0.448 1 1v14c0 0.552-0.448 1-1 1h-14c-0.552 0-1-0.448-1-1v-9h9c0.552 0 1 0.448 1 1v7h4v-12h-12z"/></svg>',expand:'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M2 5h-2v-4c0-0.552 0.448-1 1-1h4v2h-3v3z"></path><path d="M16 5h-2v-3h-3v-2h4c0.552 0 1 0.448 1 1v4z"></path><path d="M15 16h-4v-2h3v-3h2v4c0 0.552-0.448 1-1 1z"></path><path d="M5 16h-4c-0.552 0-1-0.448-1-1v-4h2v3h3v2z"></path></svg>',shrink:'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 0h2v4c0 0.552-0.448 1-1 1h-4v-2h3v-3z"></path><path d="M11 0h2v3h3v2h-4c-0.552 0-1-0.448-1-1v-4z"></path><path d="M12 11h4v2h-3v3h-2v-4c0-0.552 0.448-1 1-1z"></path><path d="M0 11h4c0.552 0 1 0.448 1 1v4h-2v-3h-3v-2z"></path></svg>',info:'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M7 4.75c0-0.412 0.338-0.75 0.75-0.75h0.5c0.412 0 0.75 0.338 0.75 0.75v0.5c0 0.412-0.338 0.75-0.75 0.75h-0.5c-0.412 0-0.75-0.338-0.75-0.75v-0.5z"></path><path d="M10 12h-4v-1h1v-3h-1v-1h3v4h1z"></path><path d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM8 14.5c-3.59 0-6.5-2.91-6.5-6.5s2.91-6.5 6.5-6.5 6.5 2.91 6.5 6.5-2.91 6.5-6.5 6.5z"></path></svg>',comment:'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 4h10v1h-10zM3 6h8v1h-8zM3 8h4v1h-4zM14.5 1h-13c-0.825 0-1.5 0.675-1.5 1.5v8c0 0.825 0.675 1.5 1.5 1.5h2.5v4l4.8-4h5.7c0.825 0 1.5-0.675 1.5-1.5v-8c0-0.825-0.675-1.5-1.5-1.5zM14 10h-5.924l-3.076 2.73v-2.73h-3v-7h12v7z"></path></svg>',thumbs:'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 3v10h-2v-11c0-0.552 0.448-1 1-1h12c0.552 0 1 0.448 1 1v12c0 0.552-0.448 1-1 1h-12c-0.552 0-1-0.448-1-1v-1h4v-2h-2v-2h2v-2h-2v-2h2v-2h2v10h6v-10h-10z"></path></svg>',cart:'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.238 9c0.55 0 1.124-0.433 1.275-0.962l1.451-5.077c0.151-0.529-0.175-0.962-0.725-0.962h-10.238c0-1.105-0.895-2-2-2h-3v2h3v8.5c0 0.828 0.672 1.5 1.5 1.5h9.5c0.552 0 1-0.448 1-1s-0.448-1-1-1h-9v-1h8.238zM5 4h9.044l-0.857 3h-8.187v-3z"></path><path d="M6 14.5c0 0.828-0.672 1.5-1.5 1.5s-1.5-0.672-1.5-1.5c0-0.828 0.672-1.5 1.5-1.5s1.5 0.672 1.5 1.5z"></path><path d="M15 14.5c0 0.828-0.672 1.5-1.5 1.5s-1.5-0.672-1.5-1.5c0-0.828 0.672-1.5 1.5-1.5s1.5 0.672 1.5 1.5z"></path></svg>',"circle-close":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 0c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zM8 14.5c-3.59 0-6.5-2.91-6.5-6.5s2.91-6.5 6.5-6.5 6.5 2.91 6.5 6.5-2.91 6.5-6.5 6.5z"></path><path d="M10.5 4l-2.5 2.5-2.5-2.5-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 2.5-2.5 2.5 2.5 1.5-1.5-2.5-2.5 2.5-2.5z"></path></svg>',"auto-progress":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path class="[ICON_CLASS]-idle" d="M11.39 8c2.152-1.365 3.61-3.988 3.61-7 0-0.339-0.019-0.672-0.054-1h-13.891c-0.036 0.328-0.054 0.661-0.054 1 0 3.012 1.457 5.635 3.609 7-2.152 1.365-3.609 3.988-3.609 7 0 0.339 0.019 0.672 0.054 1h13.891c0.036-0.328 0.054-0.661 0.054-1 0-3.012-1.457-5.635-3.609-7zM2.5 15c0-2.921 1.253-5.397 3.5-6.214v-1.572c-2.247-0.817-3.5-3.294-3.5-6.214v0h11c0 2.921-1.253 5.397-3.5 6.214v1.572c2.247 0.817 3.5 3.294 3.5 6.214h-11zM9.462 10.462c-1.12-0.635-1.181-1.459-1.182-1.959v-1.004c0-0.5 0.059-1.327 1.184-1.963 0.602-0.349 1.122-0.88 1.516-1.537h-6.4c0.395 0.657 0.916 1.188 1.518 1.538 1.12 0.635 1.181 1.459 1.182 1.959v1.004c0 0.5-0.059 1.327-1.184 1.963-1.135 0.659-1.98 1.964-2.236 3.537h7.839c-0.256-1.574-1.102-2.879-2.238-3.538z"/><circle class="[ICON_CLASS]-circle" r="4" cx="8" cy="8"/><path class="[ICON_CLASS]-play" d="M3 2l10 6-10 6z"/><path class="[ICON_CLASS]-pause" d="M2 2h5v12h-5zM9 2h5v12h-5z"/></svg>',"exif-aperture":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 8,0 C 3.5876443,0 0,3.5876443 0,8 c 0,4.412356 3.5876443,8 8,8 4.412356,0 8,-3.587644 8,-8 C 16,3.5876443 12.412356,0 8,0 Z m 0,1 c 3.871916,0 7,3.1280844 7,7 0,3.871916 -3.128084,7 -7,7 C 4.1280844,15 1,11.871916 1,8 1,4.1280844 4.1280844,1 8,1 Z M 7.53125,2.0214844 A 6,6 0 0 0 3.1835938,4.4335938 H 8.9257812 Z M 8.6132812,2.03125 C 9.5587451,3.6702105 10.504247,5.3091484 11.451172,6.9472656 L 12.863281,4.5 A 6,6 0 0 0 8.6132812,2.03125 Z M 2.5957031,5.4101562 A 6,6 0 0 0 2,8 6,6 0 0 0 2.5273438,10.439453 L 5.4296875,5.4101562 Z m 10.8261719,0.033203 -2.855469,4.9433598 h 2.935547 A 6,6 0 0 0 14,8 6,6 0 0 0 13.421875,5.4433592 Z M 4.5722656,8.8945312 3.0996094,11.449219 a 6,6 0 0 0 4.40625,2.527343 z m 2.5820313,2.4707028 1.4960937,2.591797 a 6,6 0 0 0 4.3144534,-2.591797 z"></path></svg>',"exif-camera":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="m 8.0000002,5 a 4,4 0 0 0 -4,4 4,4 0 0 0 4,4 A 4,4 0 0 0 12,9 4,4 0 0 0 8.0000002,5 Z m 0.019531,1.015625 a 3,2.9814477 0 0 1 2.9804688,3 l -1,-0.00586 a 2,2 0 0 0 0,-0.00976 2,2 0 0 0 -1.9863279,-2 z M 5.125,1 C 4.5,1 4,1.5 4,2.125 V 3.0000004 L 1.125,3 C 0.5,2.9999999 0,3.5 0,4.125 v 9.75 C 0,14.5 0.5,15 1.125,15 h 13.75 C 15.5,15 16,14.5 16,13.875 V 4.125 C 16,3.5 15.5,3 14.875,3 H 12 V 2.125 C 12,1.5 11.5,1 10.875,1 Z M 5.25,2.0000004 h 5.5 c 0.125,0 0.25,0.1249996 0.25,0.25 v 1.75 h 3.75 c 0.125,0 0.25,0.1249996 0.25,0.25 V 13.75 C 15,13.875 14.875,14 14.75,14 H 1.25 C 1.125,14 1,13.875 1,13.75 V 4.25 C 1,4.125 1.125,4 1.25,4 l 3.75,4e-7 v -1.75 c 0,-0.1250004 0.125,-0.25 0.25,-0.25 z"></path></svg>',"exif-created-timestamp":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 3,1 V 2 H 1 V 15 H 16 V 2 H 14 V 1 H 13 V 2 H 4 V 1 Z M 2,4 H 15 V 14 H 2 Z M 6,5 V 7 H 8 V 5 Z m 3,0 v 2 h 2 V 5 Z m 3,0 v 2 h 2 V 5 Z M 3,8 v 2 H 5 V 8 Z m 3,0 v 2 H 8 V 8 Z m 3,0 v 2 h 2 V 8 Z m 3,0 v 2 h 2 V 8 Z m -9,3 v 2 h 2 v -2 z m 3,0 v 2 h 2 v -2 z m 3,0 v 2 h 2 v -2 z"></path></svg>',"exif-shutter-speed":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 8,0 C 3.5876443,0 -2.9415707e-8,3.5876443 0,8 c 2.3532563e-7,4.412356 3.5876445,8 8,8 4.412356,0 8,-3.587644 8,-8 C 16,3.5876443 12.412356,0 8,0 Z m 0,1 c 3.871916,0 7,3.1280844 7,7 0,3.871915 -3.128085,7 -7,7 -3.8719154,0 -6.9999998,-3.128085 -7,-7 -3e-8,-3.8719156 3.1280844,-7 7,-7 z M 11.646484,3.6464844 8.6445312,6.6484375 A 1.5,1.5 0 0 0 8,6.5 1.5,1.5 0 0 0 6.5,8 1.5,1.5 0 0 0 8,9.5 1.5,1.5 0 0 0 9.5,8 1.5,1.5 0 0 0 9.3515625,7.3554688 L 12.353516,4.3535156 Z M 2,7.5 v 1 h 2 v -1 z M 7.5,12 v 2 h 1 V 12 Z M 12,7.5 v 1 h 2 v -1 z M 7.5,2 v 2 h 1 V 2 Z"></path></svg>',"exif-focal-length":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="m 1,4.125 -1,0.25 v 7.25 l 1,0.25 z M 5,1 2,4 v 8 l 3,3 h 6.875 C 12.500003,15 13,14.5 13,13.875 V 2.125 C 13,1.4999986 12.5,1 11.875,1 9.576807,0.99914375 7.1414067,0.96597644 5,1 Z M 5.5,2 H 6 V 14 H 5.5 L 3,11.5 v -7 z M 7,2 h 4.75 C 11.875,2 12,2.1249997 12,2.25 v 11.5 c 0,0.125 -0.125,0.250622 -0.25,0.25 H 7 Z m 7,0 c 1,2.2 1.5,4.35 1.5,6 0,1.65 -0.5,3.8 -1.5,6"></path></svg>',"exif-iso":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 7.5,0 V 1.6015625 C 6.0969201,1.7146076 4.8392502,2.256185 3.828125,3.1210938 L 2.6035156,1.8964844 1.8964844,2.6035156 3.1210938,3.828125 C 2.256185,4.8392502 1.7146076,6.0969201 1.6015625,7.5 H 0 v 1 h 1.6015625 c 0.1130451,1.4030799 0.6546225,2.66075 1.5195313,3.671875 l -1.2246094,1.224609 0.7070312,0.707032 1.2246094,-1.22461 C 4.8392502,13.743815 6.0969201,14.285392 7.5,14.398438 V 16 h 1 v -1.601562 c 1.4030799,-0.113046 2.66075,-0.654623 3.671875,-1.519532 l 1.224609,1.22461 0.707032,-0.707032 -1.22461,-1.224609 C 13.743815,11.16075 14.285392,9.9030799 14.398438,8.5 H 16 v -1 H 14.398438 C 14.285392,6.0969201 13.743815,4.8392502 12.878906,3.828125 L 14.103516,2.6035156 13.396484,1.8964844 12.171875,3.1210938 C 11.16075,2.256185 9.9030799,1.7146076 8.5,1.6015625 V 0 Z M 8,2.5 c 3.043488,0 5.5,2.4565116 5.5,5.5 0,3.043488 -2.456512,5.5 -5.5,5.5 C 4.9565116,13.5 2.5,11.043488 2.5,8 2.5,4.9565116 4.9565116,2.5 8,2.5 Z"></path></svg>',"exif-orientation":'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M 1.25,0 C 0.625,0 0,0.625 0,1.25 V 5 H 1 V 3 h 8 v 2 h 1 V 1.25 C 10,0.625 9.375,0 8.75,0 Z m 0,1 h 7.5 C 8.875,1 9,1.125 9,1.25 V 2 H 1 V 1.25 C 1,1.125 1.125,1 1.25,1 Z m 0,5 C 0.625,6 0,6.625 0,7.25 v 7.5 C 0,15.375 0.625,16 1.25,16 h 13.5 C 15.375,16 16,15.375 16,14.75 V 7.25 C 16,6.625 15.375,6 14.75,6 Z m 0,1 H 2 v 3 H 1 V 7.25 C 1,7.125 1.125,7 1.25,7 Z M 3,7 h 10 v 8 H 3 Z m 11,0 h 0.75 C 14.875,7 15,7.125 15,7.25 v 7.5 C 15,14.875 14.875,15 14.75,15 H 14 Z M 1,12 h 1 v 3 H 1.25 C 1.125,15 1,14.875 1,14.75 Z"></path></svg>'}}},register:function(a,b){return!(d.empty(a)||d.empty(b)||!d.string(a)||!d.hash(b))&&(this.registered[a]=e.extend({},this.registered.default,b),!0)},get:function(b,c){var f=this,g="default",h=e.extend({},f.registered.default);d.string(c)&&"default"!==c?(g=c,h=e.extend(h,f.registered[c])):d.hash(c)&&(g="custom",h=e.extend(h,c));var i=d.string(b)&&h.hasOwnProperty(b)?h[b].replace(/\[ICON_CLASS]/g,f.className+"-"+b):null,j=[!1,b,g].map(function(a){return!1===a?f.className:f.className+"-"+a}).join(" ");return a(i).addClass(j)}}),b.icons=new b.Icons}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj),function(a,b,c,d,e){var f="__FooGallerySwipe__",g="ontouchstart"in window,h=window.navigator.msPointerEnabled&&!window.navigator.pointerEnabled&&!g,i=(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&!g,j=g||i;b.Swipe=c.Class.extend({construct:function(b,c){var d=this,f=".fgswipe";d.$el=a(b),d.opt=e.extend({threshold:20,allowPageScroll:!1,swipe:a.noop,data:{}},c),d.active=!1,d.startPoint=null,d.endPoint=null,d.events={start:(j?i?h?"MSPointerDown":"pointerdown":"touchstart":"mousedown")+f,move:(j?i?h?"MSPointerMove":"pointermove":"touchmove":"mousemove")+f,end:(j?i?h?"MSPointerUp":"pointerup":"touchend":"mouseup")+f,leave:(j?i?"mouseleave":null:"mouseleave")+f}},init:function(){var a=this;a.$el.on(a.events.start,{self:a},a.onStart),a.$el.on(a.events.move,{self:a},a.onMove),a.$el.on(a.events.end,{self:a},a.onEnd),d.string(a.events.leave)&&a.$el.on(a.events.leave,{self:a},a.onEnd),a.$el.data(f,a)},destroy:function(){var a=this;a.$el.off(a.events.start,a.onStart),a.$el.off(a.events.move,a.onMove),a.$el.off(a.events.end,a.onEnd),d.string(a.events.leave)&&a.$el.off(a.events.leave,a.onEnd),a.$el.removeData(f)},getAngle:function(a,b){var c=Math.atan2(a.x-b.x,a.y-b.y),d=Math.round(180*c/Math.PI);return 360-(d<0?360-Math.abs(d):d)},getDistance:function(a,b){var c=b.x-a.x,d=b.y-a.y;return c*=c,d*=d,Math.sqrt(c+d)},getDirection:function(a,b){var c=this,d=c.getAngle(a,b);return d>337.5||d<=22.5?"N":d>22.5&&d<=67.5?"NE":d>67.5&&d<=112.5?"E":d>112.5&&d<=157.5?"SE":d>157.5&&d<=202.5?"S":d>202.5&&d<=247.5?"SW":d>247.5&&d<=292.5?"W":d>292.5&&d<=337.5?"NW":"NONE"},getPoint:function(a){var b;return j&&!d.empty(b=a.originalEvent.touches||a.touches)?{x:b[0].pageX,y:b[0].pageY}:d.number(a.pageX)&&d.number(a.pageY)?{x:a.pageX,y:a.pageY}:null},getOffset:function(a){var b=this,c=b.$el.offset();return{left:a.x-c.left,top:a.y-c.top}},onStart:function(a){var b=a.data.self,c=b.getPoint(a);d.empty(c)||(b.active=!0,b.startPoint=b.endPoint=c)},onMove:function(a){var b=a.data.self,e=b.getPoint(a);if(b.active&&!d.empty(e))if(b.endPoint=e,b.opt.allowPageScroll){if(d.hash(b.opt.allowPageScroll)){var f=b.getDirection(b.startPoint,b.endPoint);b.opt.allowPageScroll.x||-1===c.inArray(f,["NE","E","SE","NW","W","SW"])||a.preventDefault(),b.opt.allowPageScroll.y||-1===c.inArray(f,["NW","N","NE","SW","S","SE"])||a.preventDefault()}}else a.preventDefault()},onEnd:function(a){var b=a.data.self;if(b.active){b.active=!1;var c={startPoint:b.startPoint,endPoint:b.endPoint,startOffset:b.getOffset(b.startPoint),endOffset:b.getOffset(b.endPoint),angle:b.getAngle(b.startPoint,b.endPoint),distance:b.getDistance(b.startPoint,b.endPoint),direction:b.getDirection(b.startPoint,b.endPoint)};if(b.opt.threshold>0&&c.distance<b.opt.threshold)return;b.opt.swipe.apply(this,[c,b.opt.data]),b.startPoint=null,b.endPoint=null}}}),a.fn.fgswipe=function(c){return this.each(function(){var e=a(this),g=e.data(f);if(g instanceof b.Swipe){if(d.string(c)&&d.fn(g[c]))return void g[c]();g.destroy()}d.hash(c)&&(g=new b.Swipe(this,c),g.init())})}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj),function(a,b,c,d,e){b.Factory=c.Class.extend({construct:function(){this.registered={}},contains:function(a){return!d.undef(this.registered[a])},make:function(a,b,c){var f,g=this,h=e.arg2arr(arguments);return a=h.shift(),f=g.registered[a],d.hash(f)&&d.fn(f.klass)?e.apply(f.klass,h):null},names:function(b){b=!!d.boolean(b)&&b;var c,e=[];if(b){var f=[];for(c in this.registered)this.registered.hasOwnProperty(c)&&f.push(this.registered[c]);f.sort(function(a,b){return b.priority-a.priority}),a.each(f,function(a,b){e.push(b.name)})}else for(c in this.registered)this.registered.hasOwnProperty(c)&&e.push(c);return e},register:function(a,b,c){if(!d.string(a)||d.empty(a)||!d.fn(b))return!1;c=d.number(c)?c:0;var e=this.registered[a];return this.registered[a]={name:a,klass:b,priority:d.undef(e)?c:e.priority},!0},load:function(){var b,c=this,d=[],e=[];for(b in c.registered)c.registered.hasOwnProperty(b)&&e.push(c.registered[b]);return e.sort(function(a,b){return b.priority-a.priority}),a.each(e,function(a,b){d.push(c.make(b.name))}),d}})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d,e,f){b.TemplateFactory=b.Factory.extend({construct:function(){this.registered={}},register:function(a,b,c,e,f,g){var h=this,i=h._super(a,b,g);if(i){var j=h.registered;j[a].opt=d.hash(c)?c:{},j[a].cls=d.hash(e)?e:{},j[a].il8n=d.hash(f)?f:{}}return i},make:function(b,c){c=d.jq(c)?c:a(c),b=f.extend({},b,c.data("foogallery"));var e=this,g=e.type(b,c);return e.contains(g)?(b=e.options(g,b),e._super(g,b,c)):null},type:function(b,e){e=d.jq(e)?e:a(e);var f=this,g=d.hash(b)&&d.hash(b)&&d.string(b.type)&&f.contains(b.type)?b.type:null;if(null===g&&e.length>0)for(var h=f.registered,i=f.names(!0),j=0,k=i.length;j<k;j++)if(h.hasOwnProperty(i[j])&&"core"!==i[j]){var l=i[j],m=h[l].cls;if(d.string(m.container)){var n=c.selectify(m.container);if(e.is(n)){g=i[j];break}}}return g},configure:function(a,b,c,d){var e=this;if(e.contains(a)){var g=e.registered;f.extend(g[a].opt,b),f.extend(g[a].cls,c),f.extend(g[a].il8n,d)}},options:function(a,c){c=f.extend({type:a},c);var e=this,g=e.registered,h=g.core.opt,i=g.core.cls,j=g.core.il8n;return d.hash(c.cls)||(c.cls={}),d.hash(c.il8n)||(c.il8n={}),d.undef(b.filtering)||(c=b.filtering.merge(c)),d.undef(b.paging)||(c=b.paging.merge(c)),"core"!==a&&e.contains(a)?(c=f.extend({},h,g[a].opt,c),c.cls=f.extend({},i,g[a].cls,c.cls),c.il8n=f.extend({},j,g[a].il8n,c.il8n)):(c=f.extend({},h,c),c.cls=f.extend({},i,c.cls),c.il8n=f.extend({},j,c.il8n)),c}}),b.template=new b.TemplateFactory}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e,f){var g=0;b.Template=c.EventClass.extend({construct:function(f,h){var i=this;i._super(),i.namespace=".foogallery-"+ ++g,i.$el=d.jq(h)?h:a(h),i.el=i.$el.get(0)||null,i.$scrollParent=null,i.opt=f,i.template=f.template,i.id=i.$el.prop("id")||f.id,i.cls=f.cls,i.il8n=f.il8n,i.sel=c.selectify(i.cls),i.items=b.components.make("items",i),i.pages=d.undef(b.paging)?null:b.paging.make(f.paging.type,i),i.filter=d.undef(b.filtering)?null:b.filtering.make(f.filtering.type,i),i.state=b.components.make("state",i),i._initialize=null,i._layoutTimeout=null,i._layoutWidths=[],i.lastWidth=0,i.initializing=!1,i.initialized=!1,i.destroying=!1,i.destroyed=!1,i._undo={classes:"",style:"",create:!1,children:!1},i.robserver=new ResizeObserver(e.throttle(function(a){if(!i.destroying&&!i.destroyed&&1===a.length&&a[0].target===i.el){var b=c.getResizeObserverSize(a[0]);i.layout(b.width)}},50))},initialize:function(b){var c=this;return d.promise(c._initialize)?c._initialize:c._initialize=a.Deferred(function(a){c.preInit(b)?c.init().then(function(){c.postInit()?(c.ready(),a.resolve(c)):a.reject("post-init failed")}).fail(a.reject):a.reject("pre-init failed")}).fail(function(a){return console.log("initialize failed",c,a),c.destroy()}).promise()},preInit:function(e){var f=this;if(f.destroying)return!1;if(e=d.jq(e)?e:a(e),f.initializing=!0,0===e.length&&0===f.$el.parent().length)return!1;0===f.$el.length&&(f.$el=f.create(),f.el=f.$el.get(0),f._undo.create=!0),e.length>0&&f.$el.appendTo(e);var g;d.empty(f.opt.scrollParent)||0===(g=a(f.opt.scrollParent)).length?f.$scrollParent=a(document):f.$scrollParent=g.is("html")?a(document):g,f.$el.data(b.DATA_TEMPLATE,f),d.empty(f.opt.on)||f.on(f.opt.on),f._undo.classes=f.$el.attr("class"),f._undo.style=f.$el.attr("style"),f.$el.is(f.sel.container)||f.$el.addClass(f.cls.container);var h=c.selectify(f.opt.classes);return null==h||f.$el.is(h)||f.$el.addClass(f.opt.classes),0===f.$el.children().not(f.sel.item.elem).length&&(f.$el.append(f.createChildren()),f._undo.children=!0),!f.trigger("pre-init").isDefaultPrevented()},init:function(){var a=this;return a.trigger("init").isDefaultPrevented()?e.reject("init default prevented"):a.items.fetch()},postInit:function(){var b=this;return!b.destroying&&(!b.trigger("post-init").isDefaultPrevented()&&(b.state.init(),b.pages&&b.pages.init(),a(window).on("popstate"+b.namespace,{self:b},b.onWindowPopState),b.robserver.observe(b.el),!0))},ready:function(){var a=this;return!a.destroying&&(a.initializing=!1,a.initialized=!0,a.trigger("ready"),!0)},create:function(){var b=this;return a("<div/>",{id:b.id,class:b.cls.container}).addClass(b.opt.classes)},createChildren:function(){return a()},destroy:function(b){var c=this,f=c._super.bind(c);return c.destroyed?e.resolved:(c.destroying=!0,a.Deferred(function(a){c.initializing&&d.promise(c._initialize)?c._initialize.always(function(){c.destroying=!1,c.doDestroy(b),a.resolve()}):(c.destroying=!1,c.doDestroy(b),a.resolve())}).then(function(){f()}).promise())},doDestroy:function(c){var e=this;e.destroyed||(e.trigger("destroy"),e.robserver.disconnect(),a(window).off(e.namespace),e.state.destroy(c),e.filter&&e.filter.destroy(),e.pages&&e.pages.destroy(),e.items.destroy(),d.empty(e.opt.on)||e.$el.off(e.opt.on),e.trigger("destroyed"),e.$el.removeData(b.DATA_TEMPLATE),d.empty(e._undo.classes)?e.$el.removeAttr("class"):e.$el.attr("class",e._undo.classes),d.empty(e._undo.style)?e.$el.removeAttr("style"):e.$el.attr("style",e._undo.style),e._undo.children&&e.destroyChildren(),e._undo.create&&e.$el.remove(),e.$el=e.state=e.items=e.pages=null,e.destroyed=!0,e.initializing=!1,e.initialized=!1)},destroyChildren:function(){},getAvailable:function(){return this.pages?this.pages.available():this.items.available()},layout:function(a){var b=this;if(null!==b._initialize){if(!d.number(a)){a=b.el.getBoundingClientRect().width}0===a||b._checkWidth(a)||(b.lastWidth=a,b.trigger("layout",[a]))}},_checkWidth:function(a){var b,c=this;return(b=-1!==c._layoutWidths.indexOf(a))||(c._layoutWidths.unshift(a),c._layoutWidths.splice(2,c._layoutWidths.length-2),null!=c._layoutTimeout&&clearTimeout(c._layoutTimeout),c._layoutTimeout=setTimeout(function(){c._layoutWidths.splice(0,c._layoutWidths.length)},100)),b},getCSSClass:function(a,b){b=d.empty(b)?"":b;var c=a instanceof RegExp?a:d.string(a)&&this.opt.regex.hasOwnProperty(a)?this.opt.regex[a]:null,e=this.$el.prop("className")||"",f=null!=c?e.match(c):null;return null!=f&&f.length>=2?f[1]:b},onWindowPopState:function(a){var b=a.data.self,c=a.originalEvent.state;d.empty(c)||c.id!==b.id||b.state.set(c)}}),b.template.register("core",b.Template,{id:null,type:"core",classes:"",on:{},lazy:!0,items:[],scrollParent:null,delay:0,throttle:50,shortpixel:!1,srcset:"data-srcset-fg",src:"data-src-fg",template:{},regex:{theme:/(?:\s|^)(fg-(?:light|dark|custom))(?:\s|$)/,loadingIcon:/(?:\s|^)(fg-loading-(?:default|bars|dots|partial|pulse|trail))(?:\s|$)/,hoverIcon:/(?:\s|^)(fg-hover-(?:zoom|zoom2|zoom3|plus|circle-plus|eye|external|tint))(?:\s|$)/,videoIcon:/(?:\s|^)(fg-video-(?:default|1|2|3|4))(?:\s|$)/,border:/(?:\s|^)(fg-border-(?:thin|medium|thick))(?:\s|$)/,hoverColor:/(?:\s|^)(fg-hover-(?:colorize|grayscale))(?:\s|$)/,hoverScale:/(?:\s|^)(fg-hover-scale)(?:\s|$)/,stickyVideoIcon:/(?:\s|^)(fg-video-sticky)(?:\s|$)/,insetShadow:/(?:\s|^)(fg-shadow-inset-(?:small|medium|large))(?:\s|$)/,filter:/(?:\s|^)(fg-filter-(?:1977|amaro|brannan|clarendon|earlybird|lofi|poprocket|reyes|toaster|walden|xpro2|xtreme))(?:\s|$)/}},{container:"foogallery"},{},-100)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.str),function(a,b,c){a.Component=b.EventClass.extend({construct:function(a){this._super(),this.tmpl=a},destroy:function(){this.tmpl=null,this._super()}}),a.components=new a.Factory}(FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d,e,f){b.State=b.Component.extend({construct:function(a){var b=this;b._super(a),b.apiEnabled=!!window.history&&!!history.replaceState,b.opt=b.tmpl.opt.state,b.enabled=b.opt.enabled,b.current={filter:[],page:0,item:null},b.pushOrReplace=b.isPushOrReplace(b.opt.pushOrReplace)?b.opt.pushOrReplace:"replace",b.defaultMask="foogallery-gallery-{id}";var c=e.escapeRegExp(b.tmpl.id),d=e.escapeRegExp(b.getMasked()),f=e.escapeRegExp(b.opt.values),g=e.escapeRegExp(b.opt.pair);b.regex={exists:new RegExp("^#"+c+"\\"+f+".+?"),masked:new RegExp("^#"+d+"\\"+f+".+?"),values:new RegExp("(\\w+)"+g+"([^"+f+"]+)","g")}},destroy:function(a){var b=this;a||b.clear(),b.opt=b.regex={},b._super()},init:function(){this.set(this.initial())},getIdNumber:function(){return this.tmpl.id.match(/\d+/g)[0]},getMasked:function(){var a=this,b=e.contains(a.opt.mask,"{id}")?a.opt.mask:a.defaultMask;return e.format(b,{id:a.getIdNumber()})},isPushOrReplace:function(a){return-1!==c.inArray(a,["push","replace"])},exists:function(){return this.regex.values.lastIndex=0,(this.regex.exists.test(location.hash)||this.regex.masked.test(location.hash))&&this.regex.values.test(location.hash)},parse:function(){var b=this,c=b.tmpl,d={};if(b.exists())if(b.enabled){
11
+ d.id=b.tmpl.id,b.regex.values.lastIndex=0;var e=location.hash.match(b.regex.values);a.each(e,function(a,e){var f,g=e.split(b.opt.pair);if(2===g.length)switch(g[0]){case b.opt.itemKey:f=c.items.fromHash(g[1]),null!==f&&(d.item=f);break;case b.opt.pageKey:c.pages&&null!==(f=c.pages.fromHash(g[1]))&&(d.page=f);break;case b.opt.filterKey:c.filter&&null!==(f=c.filter.fromHash(g[1]))&&(d.filter=f)}})}else b.apiEnabled?history.replaceState(null,"",location.pathname+location.search):location.hash="#";return d},hashify:function(a){var b=this,c=b.tmpl;if(d.hash(a)){var e=[],f=c.items.toHash(a.item);return null!==f&&e.push(b.opt.itemKey+b.opt.pair+f),c.filter&&null!==(f=c.filter.toHash(a.filter))&&e.push(b.opt.filterKey+b.opt.pair+f),c.pages&&null!==(f=c.pages.toHash(a.page))&&e.push(b.opt.pageKey+b.opt.pair+f),e.length>0&&e.unshift("#"+b.getMasked()),e.join(b.opt.values)}return""},replace:function(a){var c=this;if(c.enabled&&c.apiEnabled){a.id=c.tmpl.id;var e=c.hashify(a),g=d.empty(e),h=f.extend({},a,{item:a.item instanceof b.Item?a.item.id:a.item});history.replaceState(g?null:h,"",g?location.pathname+location.search:e)}},push:function(a){var c=this;if(c.enabled&&c.apiEnabled){a.id=c.tmpl.id;var e=c.hashify(a),g=d.empty(e),h=f.extend({},a,{item:a.item instanceof b.Item?a.item.id:a.item});history.pushState(g?null:h,"",g?location.pathname+location.search:e)}},update:function(a,b){var c=this;c.enabled&&c.apiEnabled&&(b=c.isPushOrReplace(b)?b:c.pushOrReplace,c[b](a))},clear:function(){this.exists()&&this.replace({})},initial:function(){var a=this,b=a.parse();return d.empty(b)?a.get():f.extend({filter:[],page:1,item:null},b)},get:function(a){var c,d=this,e=d.tmpl,g={};return a instanceof b.Item&&(g.item=a),e.filter&&null!==(c=e.filter.getState())&&(g.filter=c),e.pages&&null!==(c=e.pages.getState())&&(g.page=c),f.extend({filter:[],page:1,item:null},g)},set:function(a){var c=this,e=c.tmpl;if(d.hash(a)){var g=f.extend({filter:[],page:1,item:null},a);e.items.reset();if(!e.trigger("before-state",[g]).isDefaultPrevented()){if(e.filter&&e.filter.setState(g),e.pages)e.pages.setState(g);else{var h=e.items.available();if(!e.items.isAll(h)){var i=e.items.not(h);e.items.detach(i)}e.items.create(h,!0)}g.item instanceof b.Item&&(c.opt.scrollTo&&g.item.scrollTo(),d.empty(a.item)||(a.item=null,c.replace(a))),c.current=g,e.trigger("after-state",[g])}}}}),b.template.configure("core",{state:{enabled:!1,scrollTo:!0,pushOrReplace:"replace",mask:"foogallery-gallery-{id}",values:"/",pair:":",array:"+",arraySeparator:",",itemKey:"i",filterKey:"f",pageKey:"p"}}),b.components.register("state",b.State)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.str,FooGallery.utils.obj),function(a,b,c,d,e,f){b.Items=b.Component.extend({construct:function(a){var d=this;d.ALLOW_CREATE=!0,d.ALLOW_APPEND=!0,d._super(a),d._typeRegex=/(?:^|\s)?fg-type-(.*?)(?:$|\s)/,d._fetched=null,d._all=[],d._available=[],d._unavailable=[],d._observed=new Map;var e=d.tmpl.cls.item.caption;d.tmpl.sel.item.caption.all=c.selectify([e.elem,e.inner,e.title,e.description]),d.iobserver=new IntersectionObserver(function(a){d.tmpl.destroying||d.tmpl.destroyed||a.forEach(function(a){if(a.isIntersecting){var c=d._observed.get(a.target);c instanceof b.Item&&c.load()}})})},fromHash:function(a){return this.find(this._all,function(b){return b.id===a})},toHash:function(a){return a instanceof b.Item?a.id:null},destroy:function(){var b=this,c=b.all(),d=[];b.iobserver.disconnect(),c.length>0&&(b.tmpl.trigger("destroy-items",[c]),d=a.map(c,function(a){return a.destroy()?a:null}),d.length>0&&b.tmpl.trigger("destroyed-items",[d])),b._fetched=null,b._all=[],b._available=[],b._unavailable=[],b._observed.clear(),b._super()},fetch:function(b){var c=this;if(!b&&d.promise(c._fetched))return c._fetched;var e=c.tmpl.id+"_items",f=c.tmpl.sel,g=c.tmpl.opt.items,h=a.Deferred(),i=c.make(c.tmpl.$el.find(f.item.elem));return d.empty(g)?(d.array(window[e])&&i.push.apply(i,c.make(window[e])),h.resolve(i)):d.array(g)?(i.push.apply(i,c.make(g)),h.resolve(i)):d.string(g)?a.get(g).then(function(a){i.push.apply(i,c.make(a)),h.resolve(i)},function(a,b,c){console.log("FooGallery: GET items error.",g,a,b,c),h.resolve(i)}):h.resolve(i),h.then(function(a){c.setAll(a)}),c._fetched=h.promise()},toJSON:function(a){return(a?this.all():this.available()).map(function(a){return a.toJSON()})},all:function(){return this._all.slice()},count:function(a){return a?this.all().length:this.available().length},available:function(a){return d.fn(a)?this._available.filter(a,this):this._available.slice()},unavailable:function(a){return d.fn(a)?this._unavailable.filter(a,this):this._unavailable.slice()},setAll:function(a){this._all=d.array(a)?a:[],this._all.forEach(function(a,b){a.index=b,d.empty(a.id)&&(a.id=b+1+"")}),this._available=this.all(),this._unavailable=[]},setAvailable:function(a){var b=this;b._available=d.array(a)?a:[],b._all.length!==b._available.length?b._unavailable=b._all.filter(function(a){return-1===b._available.indexOf(a)}):b._unavailable=[]},reset:function(){this.setAvailable(this.all())},find:function(a,b){if(b=d.fn(b)?b:function(){return!0},d.array(a))for(var c=0,e=a.length;c<e;c++)if(!0===b.call(this,a[c]))return a[c];return null},not:function(a){var b=this.all();return d.array(a)?b.filter(function(b){return-1===a.indexOf(b)}):b},isAll:function(a){return!!d.array(a)&&this._all.length===a.length},first:function(a){return this.find(this._available,a)},last:function(a){return this.find(this._available.slice().reverse(),a)},next:function(a,c,e){if(!(a instanceof b.Item))return null;e=!!d.boolean(e)&&e;var f=this._available.slice(),g=f.indexOf(a);if(-1!==g){var h=f.slice(0,g);return f=f.slice(g+1),e&&(f=f.concat(h)),this.find(f,c)}return null},prev:function(a,c,e){if(!(a instanceof b.Item))return null;e=!!d.boolean(e)&&e;var f=this._available.slice().reverse(),g=f.indexOf(a);if(-1!==g){var h=f.slice(0,g);return f=f.slice(g+1),e&&(f=f.concat(h)),this.find(f,c)}return null},creatable:function(c){return this.ALLOW_CREATE&&d.array(c)?a.map(c,function(a){return a instanceof b.Item&&!a.isCreated?a:null}):[]},appendable:function(c){return this.ALLOW_APPEND&&d.array(c)?a.map(c,function(a){return a instanceof b.Item&&a.isCreated&&!a.isAttached?a:null}):[]},detachable:function(c){return d.array(c)?a.map(c,function(a){return a instanceof b.Item&&a.isCreated&&a.isAttached?a:null}):[]},jquerify:function(b){return a(a.map(b,function(a){return a.$el.get()}))},make:function(c){var e=this,g=[];if(d.jq(c)||d.array(c)){var h=[],i=a.makeArray(c);if(0===i.length)return g;e.tmpl.trigger("make-items",[i]).isDefaultPrevented()||(g=a.map(i,function(a){var c=e.type(a),g=f.extend(d.hash(a)?a:{},{type:c}),i=b.components.make(c,e.tmpl,g);return d.element(a)?i.parse(a)?(h.push(i),e.ALLOW_APPEND||i.detach(),i):null:i})),g.length>0&&e.tmpl.trigger("made-items",[g]),h.length>0&&e.tmpl.trigger("parsed-items",[h])}return g},type:function(a){var c,e=this;if(d.hash(a))c=a.type;else if(d.element(a)){var f=a.className.match(e._typeRegex);null!==f&&2===f.length&&(c=f[1])}return d.string(c)&&b.components.contains(c)?c:"image"},create:function(b,c){var e=this,f=[],g=e.creatable(b);if(g.length>0){e.tmpl.trigger("create-items",[g]).isDefaultPrevented()||(f=a.map(g,function(a){return a.create()?a:null})),f.length>0&&e.tmpl.trigger("created-items",[f])}return d.boolean(c)&&c?e.append(b):f},append:function(b){var c=this,d=[],e=c.appendable(b);if(e.length>0){c.tmpl.trigger("append-items",[e]).isDefaultPrevented()||(d=a.map(e,function(a){return a.append()?a:null})),d.length>0&&c.tmpl.trigger("appended-items",[d])}return d},detach:function(b){var c=this,d=[],e=c.detachable(b);if(e.length>0){c.tmpl.trigger("detach-items",[e]).isDefaultPrevented()||(d=a.map(e,function(a){return a.detach()?a:null})),d.length>0&&c.tmpl.trigger("detached-items",[d])}return d},observe:function(a){var b=this;!(b.iobserver&&a.isCreated&&a.isAttached)||a.isLoading&&a.isLoaded||(b.iobserver.observe(a.el),b._observed.set(a.el,a))},unobserve:function(a){var b=this;b.iobserver&&(b.iobserver.unobserve(a.el),b._observed.delete(a.el))}}),b.components.register("items",b.Items)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d,e,f,g){b.Item=b.Component.extend({construct:function(a,b){var c=this;c._super(a),c.cls=a.cls.item,c.il8n=a.il8n.item,c.sel=a.sel.item,c.opt=f.extend({},a.opt.item,b),c.isAttached=!1,c.isCreated=!1,c.isDestroyed=!1,c.isLoading=!1,c.isLoaded=!1,c.isError=!1,c.isParsed=!1,c.$el=null,c.el=null,c.$inner=null,c.$anchor=null,c.$overlay=null,c.$wrap=null,c.$image=null,c.$caption=null,c.$loader=null,c.index=-1,c.type=c.opt.type,c.id=c.opt.id,c.productId=c.opt.productId,c.href=c.opt.href,c.placeholder=c.opt.placeholder,c.src=c.opt.src,c.srcset=c.opt.srcset,c.width=c.opt.width,c.height=c.opt.height,c.title=c.opt.title,c.alt=c.opt.alt,c.caption=d.empty(c.opt.caption)?c.title:c.opt.caption,c.description=d.empty(c.opt.description)?c.alt:c.opt.description,c.attr=c.opt.attr,c.tags=c.opt.tags,c.maxCaptionLength=c.opt.maxCaptionLength,c.maxDescriptionLength=c.opt.maxDescriptionLength,c.showCaptionTitle=c.opt.showCaptionTitle,c.showCaptionDescription=c.opt.showCaptionDescription,c.noLightbox=c.opt.noLightbox,c.panelHide=c.opt.panelHide,c.exif=c.opt.exif,c.hasExif=d.exif(c.exif),c._load=null,c._undo={classes:"",style:"",placeholder:!1}},destroy:function(){var a=this;return a.tmpl.trigger("destroy-item",[a]).isDefaultPrevented()||(a.isDestroyed=a.doDestroyItem()),a.isDestroyed&&(a.tmpl.trigger("destroyed-item",[a]),a._super()),a.isDestroyed},doDestroyItem:function(){var a=this;return a.isParsed?(a.$anchor.add(a.$caption).off("click.foogallery"),a.append(),a.tmpl.items.unobserve(a),d.empty(a._undo.classes)?a.$el.removeAttr("class"):a.$el.attr("class",a._undo.classes),d.empty(a._undo.style)?a.$el.removeAttr("style"):a.$el.attr("style",a._undo.style),a._undo.placeholder&&a.$image.prop("src")===a.placeholder&&a.$image.removeAttr("src")):a.isCreated&&(a.detach(),a.$el.remove()),!0},parse:function(b){var c=this,d=a(b);return!c.tmpl.trigger("parse-item",[c,d]).isDefaultPrevented()&&(c.isCreated=d.is(c.sel.elem))&&(c.isParsed=c.doParseItem(d)),c.isParsed&&(c.tmpl.items.observe(c),c.tmpl.trigger("parsed-item",[c])),c.isParsed},doParseItem:function(c){var e=this,h=e.cls,i=e.sel,j=c.get(0);if(e._undo.classes=c.attr("class")||"",e._undo.style=c.attr("style")||"",e.$el=c.data(b.DATA_ITEM,e),e.el=j,e.$inner=a(j.querySelector(i.inner)),e.$anchor=a(j.querySelector(i.anchor)).on("click.foogallery",{self:e},e.onAnchorClick),e.$image=a(j.querySelector(i.image)),e.$caption=a(j.querySelector(i.caption.elem)).on("click.foogallery",{self:e},e.onCaptionClick),e.$overlay=a(j.querySelector(i.overlay)),e.$wrap=a(j.querySelector(i.wrap)),e.$loader=a(j.querySelector(i.loader)),!(e.$el.length&&e.$inner.length&&e.$anchor.length&&e.$image.length))return console.error("FooGallery Error: Invalid HTML markup. Check the item markup for additional elements or malformed HTML in the title or description.",e),e.isError=!0,e.tmpl.trigger("error-item",[e]),0!==e.$el.length&&e.$el.remove(),!1;e.isAttached=null!==j.parentNode,e.isLoading=e.$el.hasClass(h.loading),e.isLoaded=e.$el.hasClass(h.loaded),e.isError=e.$el.hasClass(h.error);var k=e.$anchor.data();if(e.id=k.id||e.id,e.productId=k.productId||e.productId,e.tags=k.tags||e.tags,e.href=k.href||e.$anchor.attr("href")||e.href,e.src=e.$image.attr(e.tmpl.opt.src)||e.src,e.srcset=e.$image.attr(e.tmpl.opt.srcset)||e.srcset,e.width=parseInt(e.$image.attr("width"))||e.width,e.height=parseInt(e.$image.attr("height"))||e.height,e.title=e.$image.attr("title")||e.title,e.alt=e.$image.attr("alt")||e.alt,e.caption=k.title||k.captionTitle||e.caption,e.description=k.description||k.captionDesc||e.description,e.noLightbox=e.$anchor.hasClass(h.noLightbox),e.panelHide=e.$anchor.hasClass(h.panelHide),d.exif(k.exif)&&(e.exif=f.extend(e.exif,k.exif),e.hasExif=!0),e.maxCaptionLength>0){var l=g.trimTo(e.caption,e.maxCaptionLength);l!==e.caption&&e.$caption.find(i.caption.title).html(l)}if(e.maxDescriptionLength){var m=g.trimTo(e.description,e.maxDescriptionLength);m!==e.description&&e.$caption.find(i.caption.description).html(m)}var n=e.$image.get(0);d.string(n.src)&&0!==n.src.length||(d.string(e.placeholder)&&0!==e.placeholder.length||(e.placeholder=e.createPlaceholder(e.width,e.height)),e.placeholder.length>0&&(n.src=e.placeholder,e._undo.placeholder=!0));var o=e.getTypeClass();return e.$el.hasClass(o)||e.$el.addClass(o),e.hasExif&&!e.$el.hasClass(h.exif)&&e.$el.addClass(h.exif),!e.isCreated||!e.isAttached||e.isLoading||e.isLoaded||e.isError||e.$el.hasClass(h.idle)||e.$el.addClass(h.idle),e.doShortPixel(),!0},create:function(){var a=this;if(!a.isCreated&&d.string(a.href)&&d.string(a.src)&&d.number(a.width)&&d.number(a.height)){a.tmpl.trigger("create-item",[a]).isDefaultPrevented()||(a.isCreated=a.doCreateItem()),a.isCreated&&a.tmpl.trigger("created-item",[a])}return a.isCreated},_setAttributes:function(a,b){Object.keys(b).forEach(function(c){d.empty(b[c])||a.setAttribute(c,d.string(b[c])?b[c]:JSON.stringify(b[c]))})},doShortPixel:function(){function a(a,b,c){return"/"===b||"/"===c?"/":b}var c=this;if(c.tmpl.opt.shortpixel&&!b.supportsWebP){var d=/([\/,+])to_webp([\/,+])/i;c.href=c.href.replace(d,a),c.src=c.src.replace(d,a),c.srcset=c.srcset.replace(d,a)}},doCreateItem:function(){var c=this,e=c.cls,f=c.attr,h=c.hasExif?e.exif:"";c.doShortPixel();var i=document.createElement("div");c._setAttributes(i,f.elem),i.className=[e.elem,c.getTypeClass(),h,e.idle].join(" ");var j=document.createElement("figure");c._setAttributes(j,f.inner),j.className=e.inner;var k=[e.anchor];c.noLightbox&&k.push(e.noLightbox),c.panelHide&&k.push(e.panelHide);var l=document.createElement("a");c._setAttributes(l,f.anchor),c._setAttributes(l,{class:k.join(" "),href:c.href,"data-id":c.id,"data-type":c.type,"data-title":c.caption,"data-description":c.description,"data-tags":c.tags,"data-exif":c.exif,"data-product-id":c.productId}),d.string(c.placeholder)&&0!==c.placeholder.length||(c.placeholder=c.createPlaceholder(c.width,c.height));var m=document.createElement("img");c._setAttributes(m,f.image),c._setAttributes(m,{class:e.image,src:c.placeholder,width:c.width+"",height:c.height+"",title:c.title,alt:c.alt}),m.setAttribute(c.tmpl.opt.src,c.src),m.setAttribute(c.tmpl.opt.srcset,c.srcset);var n=document.createElement("span");n.className=e.overlay;var o=document.createElement("span");o.className=e.wrap;var p=document.createElement("div");p.className=e.loader;var q=document.createElement("figcaption");c._setAttributes(q,f.caption.elem),q.className=e.caption.elem;var r=document.createElement("div");c._setAttributes(r,f.caption.inner),r.className=e.caption.inner;var s=null;c.showCaptionTitle&&d.string(c.caption)&&c.caption.length>0&&(s=document.createElement("div"),c._setAttributes(s,f.caption.title),s.className=e.caption.title,s.innerHTML=c.maxCaptionLength>0?g.trimTo(c.caption,c.maxCaptionLength):c.caption);var t=null;return c.showCaptionDescription&&d.string(c.description)&&c.description.length>0&&(t=document.createElement("div"),c._setAttributes(t,f.caption.description),t.className=e.caption.description,t.innerHTML=c.maxDescriptionLength>0?g.trimTo(c.description,c.maxDescriptionLength):c.description),null!==s&&r.appendChild(s),null!==t&&r.appendChild(t),q.appendChild(r),o.appendChild(m),l.appendChild(n),l.appendChild(o),j.appendChild(l),j.appendChild(q),i.appendChild(j),i.appendChild(p),c.$el=a(i).data(b.DATA_ITEM,c),c.el=i,c.$inner=a(j),c.$anchor=a(l).on("click.foogallery",{self:c},c.onAnchorClick),c.$overlay=a(n),c.$wrap=a(o),c.$image=a(m),c.$caption=a(q).on("click.foogallery",{self:c},c.onCaptionClick),c.$loader=a(p),!0},append:function(){var a=this;if(a.isCreated&&!a.isAttached){a.tmpl.trigger("append-item",[a]).isDefaultPrevented()||(a.tmpl.$el.append(a.$el.removeClass(a.cls.hidden)),a.isAttached=!0),a.isAttached&&(a.tmpl.items.observe(a),a.tmpl.trigger("appended-item",[a]))}return a.isAttached},detach:function(){var a=this;if(a.isCreated&&a.isAttached){a.tmpl.items.unobserve(a);a.tmpl.trigger("detach-item",[a]).isDefaultPrevented()||(a.$el.detach().removeClass(a.cls.hidden),a.isAttached=!1),a.isAttached||a.tmpl.trigger("detached-item",[a])}return!a.isAttached},load:function(){var b=this;if(d.promise(b._load))return b._load;if(!b.isCreated||!b.isAttached)return e.reject("not created or attached");if(b.tmpl.trigger("load-item",[b]).isDefaultPrevented())return e.reject("default prevented");var c=b.cls,f=b.$image.get(0),g=f.src;return b.isLoading=!0,b.tmpl.items.unobserve(b),b.$el.removeClass(c.idle).removeClass(c.hidden).removeClass(c.loaded).removeClass(c.error).addClass(c.loading),b._load=a.Deferred(function(a){f.onload=function(){f.onload=f.onerror=null,b.isLoading=!1,b.isLoaded=!0,b.$el.removeClass(c.loading).addClass(c.loaded),b.tmpl.trigger("loaded-item",[b]),a.resolve(b)},f.onerror=function(){f.onload=f.onerror=null,b.isLoading=!1,b.isError=!0,b.$el.removeClass(c.loading).addClass(c.error),d.string(g)&&b.$image.prop("src",g),b.tmpl.trigger("error-item",[b]),a.reject(b)},f.src=b.src,f.srcset=b.srcset,f.complete&&f.onload()}).promise()},createPlaceholder:function(a,b){return d.number(a)&&d.number(b)?"data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20"+a+"%20"+b+"%22%3E%3C/svg%3E":""},getTypeClass:function(){return this.cls.types[this.type]||""},scrollTo:function(a){var b=this;if(b.isAttached){var c=b.$el.get(0);c.scrollIntoViewIfNeeded?c.scrollIntoViewIfNeeded():c.scrollIntoView("top"===a)}return b},updateState:function(){this.tmpl.state.update(this.tmpl.state.get(this))},toJSON:function(){return{type:this.type,id:this.id,productId:this.productId,href:this.href,src:this.src,srcset:this.srcset,width:this.width,height:this.height,alt:this.alt,title:this.title,caption:this.caption,description:this.description,tags:this.tags.slice(),maxCaptionLength:this.maxCaptionLength,maxDescriptionLength:this.maxDescriptionLength,showCaptionTitle:this.showCaptionTitle,showCaptionDescription:this.showCaptionDescription,noLightbox:this.noLightbox,panelHide:this.panelHide,attr:f.extend({},this.attr)}},onAnchorClick:function(a){var b=a.data.self;b.tmpl.trigger("anchor-click-item",[b]).isDefaultPrevented()?a.preventDefault():b.updateState()},onCaptionClick:function(b){var c=b.data.self;!c.tmpl.trigger("caption-click-item",[c]).isDefaultPrevented()&&c.$anchor.length>0&&!a(b.target).is("a,:input")&&c.$anchor.get(0).click()}}),b.template.configure("core",{item:{type:"item",id:"",href:"",placeholder:"",src:"",srcset:"",width:0,height:0,title:"",alt:"",caption:"",description:"",tags:[],maxCaptionLength:0,maxDescriptionLength:0,showCaptionTitle:!0,showCaptionDescription:!0,noLightbox:!1,panelHide:!1,exif:{aperture:null,camera:null,created_timestamp:null,shutter_speed:null,focal_length:null,iso:null,orientation:null},attr:{elem:{},inner:{},anchor:{},image:{},caption:{elem:{},inner:{},title:{},description:{}}}}},{item:{elem:"fg-item",inner:"fg-item-inner",exif:"fg-item-exif",anchor:"fg-thumb",overlay:"fg-image-overlay",wrap:"fg-image-wrap",image:"fg-image",loader:"fg-loader",idle:"fg-idle",loading:"fg-loading",loaded:"fg-loaded",error:"fg-error",hidden:"fg-hidden",noLightbox:"fg-no-lightbox",panelHide:"fg-panel-hide",types:{item:"fg-type-unknown"},caption:{elem:"fg-caption",inner:"fg-caption-inner",title:"fg-caption-title",description:"fg-caption-desc"}}},{item:{exif:{aperture:"Aperture",camera:"Camera",created_timestamp:"Date",shutter_speed:"Exposure",focal_length:"Focal Length",iso:"ISO",orientation:"Orientation"}}}),b.components.register("item",b.Item)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj,FooGallery.utils.str),function(a,b,c,d){b.Image=b.Item.extend({}),b.template.configure("core",null,{item:{types:{image:"fg-type-image"}}}),b.components.register("image",b.Image)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){a.PagingFactory=a.Factory.extend({construct:function(){this.registered={}},register:function(a,c,d,e,f,g,h){var i=this,j=i._super(a,c,h);if(j){var k=i.registered;k[a].ctrl=b.fn(d)?d:null,k[a].opt=b.hash(e)?e:{},k[a].cls=b.hash(f)?f:{},k[a].il8n=b.hash(g)?g:{}}return j},type:function(a){var c,d=this;return b.hash(a)&&b.hash(c=a.paging)&&b.string(c.type)&&d.contains(c.type)?c.type:null},merge:function(a){a=d.extend({},a);var c=this,e=c.type(a),f=c.registered,g=f.default.opt,h=f.default.cls,i=f.default.il8n,j=b.hash(a.paging)?a.paging:{},k=b.hash(a.cls)&&b.hash(a.cls.paging)?d.extend({},a.cls.paging):{},l=b.hash(a.il8n)&&b.hash(a.il8n.paging)?d.extend({},a.il8n.paging):{};return b.hash(a.cls)||(a.cls={}),b.hash(a.il8n)||(a.il8n={}),"default"!==e&&c.contains(e)?(a.paging=d.extend({},g,f[e].opt,j,{type:e}),a.cls=d.extend(a.cls,{paging:h},{paging:f[e].cls},{paging:k}),a.il8n=d.extend(a.il8n,{paging:i},{paging:f[e].il8n},{paging:l})):(a.paging=d.extend({},g,j,{type:e}),a.cls=d.extend(a.cls,{paging:h},{paging:k}),a.il8n=d.extend(a.il8n,{paging:i},{paging:l})),a},configure:function(a,b,c,e){var f=this;if(f.contains(a)){var g=f.registered;d.extend(g[a].opt,b),d.extend(g[a].cls,c),d.extend(g[a].il8n,e)}},hasCtrl:function(a){var c=this,d=c.registered[a];return b.hash(d)&&b.fn(d.ctrl)},makeCtrl:function(a,c,d,e){var f=this,g=f.registered[a];return b.hash(g)&&b.fn(g.ctrl)?new g.ctrl(c,d,e):null}}),a.paging=new a.PagingFactory}(FooGallery,FooGallery.utils.is,FooGallery.utils.fn,FooGallery.utils.obj),function(a,b,c,d){b.Paging=b.Component.extend({construct:function(a){var b=this;b._super(a),b.opt=b.tmpl.opt.paging,b.cls=b.tmpl.cls.paging,b.il8n=b.tmpl.il8n.paging,b.sel=b.tmpl.sel.paging,b.pushOrReplace=b.opt.pushOrReplace,b.type=b.opt.type,b.theme=b.opt.theme,b.size=b.opt.size,b.position=b.opt.position,b.scrollToTop=b.opt.scrollToTop,b.current=0,b.total=0,b.ctrls=[],b._pages=[]},init:function(){},fromHash:function(a){var b=parseInt(a);return isNaN(b)?null:b},toHash:function(a){return d.number(a)&&a>0?a.toString():null},getState:function(){return this.isValid(this.current)?this.current:null},setState:function(a){this.rebuild();var b=!1;a.item&&!this.contains(a.page,a.item)&&(a.page=this.find(a.item),a.page=0!==a.page?a.page:1,b=!0),this.set(a.page,b,!1,!1)},destroy:function(){var b=this;b._pages.splice(0,b._pages.length),a.each(b.ctrls.splice(0,b.ctrls.length),function(a,b){b.destroy()}),b._super()},build:function(){var a=this,c=a.tmpl.items.available();a.total=a.size>0&&c.length>0?Math.ceil(c.length/a.size):1;for(var d=0;d<a.total;d++)a._pages.push(c.splice(0,a.size));if(a.total>1&&b.paging.hasCtrl(a.type)){var e,f,g=a.position;"both"!==g&&"top"!==g||(e=b.paging.makeCtrl(a.type,a.tmpl,a,"top"),e.create()&&(e.append(),a.ctrls.push(e))),"both"!==g&&"bottom"!==g||(f=b.paging.makeCtrl(a.type,a.tmpl,a,"bottom"),f.create()&&(f.append(),a.ctrls.push(f)))}},rebuild:function(){var b=this;b.current=0,b.total=0,b._pages.splice(0,b._pages.length),a.each(b.ctrls.splice(0,b.ctrls.length),function(a,b){b.destroy()}),b.build()},all:function(){return this._pages.slice()},available:function(){return this.get(this.current)},controls:function(b){var c=this;c.isValid(b)&&a.each(c.ctrls,function(a,c){c.update(b)})},isValid:function(a){return d.number(a)&&a>0&&a<=this.total},number:function(a){return this.isValid(a)?a:0===this.current?1:this.current},create:function(a,b){var c=this;a=c.number(a);var d,e=a-1,f=c._pages[e];d=b?c.tmpl.items.all():c._pages.reduce(function(a,b,c){return c===e?a:a.concat(b)},c.tmpl.items.unavailable()),c.current=a,c.tmpl.items.detach(d),c.tmpl.items.create(f,!0)},get:function(a){var b=this;return b.isValid(a)?(a=b.number(a),b._pages[a-1]):[]},set:function(a,b,c,e){var f=this;if(f.isValid(a)){f.controls(a);var g,h=f.number(a);if(h!==f.current){var i=f.current,j=function(){if(c=!d.boolean(c)||c,e=!!d.boolean(e)&&e,c&&1===f.current&&!f.tmpl.state.exists()&&(g=f.tmpl.state.get(),f.tmpl.state.update(g,f.pushOrReplace)),f.create(h,e),c&&(g=f.tmpl.state.get(),f.tmpl.state.update(g,f.pushOrReplace)),f.tmpl.trigger("page-change",[f.current,i,e]),f.scrollToTop&&d.boolean(b)&&b){var a=f.get(f.current);a.length>0&&a[0].scrollTo("top")}f.tmpl.trigger("after-page-change",[f.current,i,e])};return!f.tmpl.trigger("before-page-change",[f.current,h,j,e]).isDefaultPrevented()&&(j(),!0)}}return!1},find:function(a){for(var b=this,d=0,e=b._pages.length;d<e;d++)if(-1!==c.inArray(a,b._pages[d]))return d+1;return 0},contains:function(a,b){var d=this.get(a);return-1!==c.inArray(b,d)},first:function(){this.goto(1)},last:function(){this.goto(this._pages.length)},prev:function(){this.goto(this.current-1)},next:function(){this.goto(this.current+1)},goto:function(a){this.set(a,!0)}}),b.PagingControl=b.Component.extend({construct:function(a,b,c){var d=this;d._super(a),d.pages=b,d.position=c,d.$container=null,d._containerExisted=!1,d._placeholderClasses=[]},create:function(){var b=this;return b.$container=a("#"+b.tmpl.id+"_paging-"+b.position),b.$container.length>0?(b._containerExisted=!0,b.$container.removeClass(function(a,c){return b._placeholderClasses=c.match(/(^|\s)fg-ph-\S+/g)||[],b._placeholderClasses.join(" ")}).addClass([b.pages.cls.container,b.pages.theme].join(" "))):b.$container=a("<nav/>",{class:[b.pages.cls.container,b.pages.theme].join(" ")}),!0},destroy:function(){var a=this;a._containerExisted?a.$container.empty().removeClass().addClass(a._placeholderClasses.join(" ")):a.$container.remove(),a.$container=null},append:function(){var a=this;a._containerExisted||("top"===a.position?a.$container.insertBefore(a.tmpl.$el):a.$container.insertAfter(a.tmpl.$el))},update:function(a){}}),b.paging.register("default",b.Paging,null,{type:"none",theme:"fg-light",size:30,pushOrReplace:"push",position:"none",scrollToTop:!0},{container:"fg-paging-container"},null,-100)}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){b.Dots=b.Paging.extend({}),b.DotsControl=b.PagingControl.extend({construct:function(a,b,c){this._super(a,b,c),this.$list=null,this.$items=null},create:function(){var b=this;if(b._super()){for(var c,d=b.pages.cls,e=b.pages.il8n,f=[],g=a("<ul/>",{class:d.list}),h=0,i=b.pages.total;h<i;h++)f.push(c=b.createItem(h+1,e.page)),g.append(c);return b.$list=g,b.$items=a(a.map(f,function(a){return a.get()})),b.$container.append(g),!0}return!1},destroy:function(){var b=this,c=b.pages.sel;b.$list.find(c.link).off("click.foogallery",b.onLinkClick),b.$list=a(),b.$items=a(),b._super()},update:function(a){this.setSelected(a-1)},setSelected:function(b){var c=this,e=c.pages.cls,f=c.pages.il8n,g=c.pages.sel;c.$items.filter(g.selected).removeClass(e.selected).each(function(b,c){var e=a(c),f=e.data("label"),h=e.find(g.reader);d.string(f)&&0!==h.length&&h.html(f)}),c.$items.eq(b).addClass(e.selected).each(function(b,c){var e=a(c),h=e.find(g.reader),i=h.html();d.string(i)&&0!==h.length&&(e.data("label",i),h.html(f.current))})},createItem:function(b,c,e,f,g){e=d.string(e)?e:b,c=d.string(c)?c:"";var h=this,i=h.pages.opt,j=h.pages.cls,k=a("<a/>",{class:j.link,href:"#page-"+b}).html(e).on("click.foogallery",{self:h,page:b},h.onLinkClick);d.empty(c)||k.attr("title",c.replace(/\{PAGE}/g,b).replace(/\{LIMIT}/g,i.limit+"")),g=d.string(g)?g:c,d.empty(g)||k.prepend(a("<span/>",{class:j.reader,text:g.replace(/\{PAGE}/g,"").replace(/\{LIMIT}/g,i.limit+"")}));var l=a("<li/>",{class:j.item}).append(k);return f=d.string(f)?f:"",d.empty(f)||l.addClass(f),l},onLinkClick:function(b){b.preventDefault();var c=b.data.self,d=b.data.page,e=c.pages.sel;a(this).closest(e.item).is(e.disabled)||c.pages.set(d,!0)}}),b.paging.register("dots",b.Dots,b.DotsControl,{type:"dots",position:"both",pushOrReplace:"push"},{list:"fg-dots",item:"fg-dot-item",link:"fg-dot-link",disabled:"fg-disabled",selected:"fg-selected",visible:"fg-visible",reader:"fg-sr-only"},{current:"Current page",page:"Page {PAGE}"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c){b.DefaultTemplate=b.Template.extend({}),b.template.register("default",b.DefaultTemplate,null,{container:"foogallery fg-default"})}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d){b.MasonryTemplate=b.Template.extend({construct:function(a,b){var c=this;c._super(a,b),c.masonry=null,c.on({"pre-init":c.onPreInit,destroyed:c.onDestroyed,"appended-items":c.onAppendedItems,"detach-item":c.onDetachItem,"layout after-filter-change":c.onLayoutRequired,"page-change":c.onPageChange},c)},onPreInit:function(){var a=this,b=a.sel,c=a.$el.hasClass("fg-fixed");a.template.isFitWidth=c,a.template.percentPosition=!c,a.template.transitionDuration=0,a.template.itemSelector=b.item.elem,c||(a.template.gutter=b.gutterWidth,a.template.columnWidth=b.columnWidth),a.masonry=new Masonry(a.el,a.template)},onDestroyed:function(){var a=this;a.masonry instanceof Masonry&&a.masonry.destroy()},onLayoutRequired:function(){this.masonry.layout()},onPageChange:function(a,b,c,d){d||this.masonry.layout()},onAppendedItems:function(a,b){var c=this,d=b.map(function(a){return a.el}),e=c.masonry.addItems(d);c.masonry.layoutItems(e,!0)},onDetachItem:function(a,b){a.isDefaultPrevented()||(a.preventDefault(),this.masonry.remove(b.el),b.$el.removeClass(this.cls.hidden),b.isAttached=!1)}}),b.template.register("masonry",b.MasonryTemplate,{template:{}},{container:"foogallery fg-masonry",columnWidth:"fg-column-width",gutterWidth:"fg-gutter-width"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b,c,d){b.Justified=c.Class.extend({construct:function(c,d){var e=this;e.tmpl=c,e.$el=c.$el,e.options=a.extend(!0,{},b.Justified.defaults,d),e._items=[],e.maxRowHeight=0,e.borderSize=0,e.align=-1!==["left","center","right"].indexOf(e.options.align)?e.options.align:"center"},init:function(){var a=this;a.maxRowHeight=a.getMaxRowHeight(a.options.maxRowHeight,a.options.rowHeight),a.borderSize=a.getBorderSize()},destroy:function(){this.$el.removeAttr("style")},getBorderSize:function(){switch(this.tmpl.getCSSClass("border","")){case"fg-border-thin":return 4;case"fg-border-medium":return 10;case"fg-border-thick":return 16;default:return 0}},getMaxRowHeight:function(a,b){if(d.string(a)){var c=parseInt(a);return isNaN(c)?b:c<=0?1/0:-1!==a.indexOf("%")?b*(c/100):c}return d.number(a)?a<=0?1/0:a:b},layout:function(a){var b=this;if(d.number(a)||(a=b.$el.width()),a>0){var c=b.createRows(a);0!==c.height&&c.rows.length>0&&(b.$el.height(c.height),c.rows.forEach(function(a,c){b.render(a)}))}},render:function(a){var b=this;a.items.forEach(function(c){c.elem&&(a.visible?(c.elem.style.setProperty("position","absolute"),c.elem.style.setProperty("width",c.width+"px"),c.elem.style.setProperty("height",c.height+"px"),c.elem.style.setProperty("top",c.top+"px"),c.elem.style.setProperty("left",c.left+"px"),c.elem.style.setProperty("margin","0"),c.elem.style.removeProperty("display"),b.maxRowHeight>0?c.elem.style.setProperty("max-height",b.maxRowHeight+2*b.borderSize+"px"):c.elem.style.removeProperty("max-height"),c.elem.classList.contains("fg-positioned")||c.elem.classList.add("fg-positioned")):c.elem.style.setProperty("display","none"))})},justify:function(a,b,c,d){var e=this,f=e.options.margins,g=f*(a.items.length-1),h=c-g,i=a.width-g,j=h/i;if(a.width=i*j,a.height=a.height*j,a.height>d+2*e.borderSize){var k=(d+2*e.borderSize)/a.height;a.width=a.width*k,a.height=a.height*k}a.top=b,a.left=0,"left"!==e.align&&a.width<h&&("right"===e.align?a.left=h-a.width:a.left=(h-a.width)/2),a.width+=g;var l=a.left;return a.items.forEach(function(c,d){d>0&&(l+=f),c.left=l,c.top=b;var e=a.height/c.height;c.width=c.width*e,c.height=c.height*e,l+=c.width}),a.height},createRows:function(a){function b(){return{index:++h,visible:!0,width:0,height:d.options.rowHeight+2*d.borderSize,top:0,left:0,items:[]}}function c(a,b){var c=a.width,e=a.height;if(e!==b){var f=b/e;e*=f,c*=f}var g=d.maxRowHeight/b,h=c*g,i=e*g;return{__item:a,elem:a.el,width:c,height:e,maxWidth:h,maxHeight:i,
12
+ top:0,left:0}}var d=this,e=d.options.margins,f=d.tmpl.getAvailable(),g=[],h=-1,i=b(),j=0,k=0;if(f.forEach(function(f){var h=c(f,i.height);if(i.width+h.width>a&&i.items.length>0){g.length>0&&(j+=e);var l=d.justify(i,j,a,d.maxRowHeight);l>k&&(k=l),j+=l,g.push(i),i=b()}i.items.length>0&&(i.width+=e),i.width+=h.width,i.items.push(h)}),i.items.length>0){g.length>0&&(j+=e);var l=d.justify(i,j,a,d.maxRowHeight);if(0!==k&&l>k){var m=k/l,n=i.width*m/a;(m<.9||n<.9)&&(l=d.justify(i,j,a,k-2*d.borderSize))}j+=l,g.push(i)}return{height:j,rows:g}}}),b.Justified.defaults={rowHeight:150,maxRowHeight:"200%",margins:0,align:"center"}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is),function(a,b){b.JustifiedTemplate=b.Template.extend({construct:function(a,b){var c=this;c._super(a,b),c.justified=null,c.on({"pre-init":c.onPreInit,init:c.onInit,destroyed:c.onDestroyed,"layout after-filter-change":c.onLayoutRequired,"page-change":c.onPageChange},c)},onPreInit:function(){var a=this;a.justified=new b.Justified(a,a.template)},onInit:function(){this.justified.init()},onDestroyed:function(){var a=this;a.justified instanceof b.Justified&&a.justified.destroy()},onLayoutRequired:function(){this.justified.layout(this.lastWidth)},onPageChange:function(a,b,c,d){d||this.justified.layout(this.lastWidth)}}),b.template.register("justified",b.JustifiedTemplate,null,{container:"foogallery fg-justified"})}(FooGallery.$,FooGallery),function(a,b){b.JustifiedCSSTemplate=b.Template.extend({}),b.template.register("justified-css",b.JustifiedCSSTemplate,null,{container:"foogallery fg-justified-css"})}(FooGallery.$,FooGallery),function(a,b,c,d,e){b.PortfolioTemplate=b.Template.extend({}),b.template.register("simple_portfolio",b.PortfolioTemplate,{},{container:"foogallery fg-simple_portfolio"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.fn),function(a,b,c,d){b.ImageViewerTemplate=b.Template.extend({construct:function(b,c){var e=this;e._super(d.extend({},b,{paging:{pushOrReplace:"replace",theme:"fg-light",type:"default",size:1,position:"none",scrollToTop:!1}}),c),e.$inner=a(),e.$current=a(),e.$total=a(),e.$prev=a(),e.$next=a(),e.on({"pre-init":e.onPreInit,init:e.onInit,destroy:e.onDestroy,"append-item":e.onAppendItem,"after-page-change":e.onAfterPageChange,"after-filter-change":e.onAfterFilterChange},e)},createChildren:function(){var b=this;return a("<div/>",{class:b.cls.inner}).append(a("<div/>",{class:b.cls.innerContainer}),a("<div/>",{class:b.cls.controls}).append(a("<div/>",{class:b.cls.prev}).append(a("<span/>",{text:b.il8n.prev})),a("<label/>",{class:b.cls.count,text:b.il8n.count}).prepend(a("<span/>",{class:b.cls.countCurrent,text:"0"})).append(a("<span/>",{class:b.cls.countTotal,text:"0"})),a("<div/>",{class:b.cls.next}).append(a("<span/>",{text:b.il8n.next}))))},destroyChildren:function(){var a=this;a.$el.find(a.sel.inner).remove()},onPreInit:function(a){var b=this;b.$inner=b.$el.find(b.sel.innerContainer),b.$current=b.$el.find(b.sel.countCurrent),b.$total=b.$el.find(b.sel.countTotal),b.$prev=b.$el.find(b.sel.prev),b.$next=b.$el.find(b.sel.next)},onInit:function(a){var b=this;b.template.attachFooBox&&b.$el.on("foobox.previous",{self:b},b.onFooBoxPrev).on("foobox.next",{self:b},b.onFooBoxNext),b.$prev.on("click",{self:b},b.onPrevClick),b.$next.on("click",{self:b},b.onNextClick)},onDestroy:function(a){var b=this;b.template.attachFooBox&&b.$el.off({"foobox.previous":b.onFooBoxPrev,"foobox.next":b.onFooBoxNext}),b.$prev.off("click",b.onPrevClick),b.$next.off("click",b.onNextClick)},onAppendItem:function(a,b){a.preventDefault(),this.$inner.append(b.$el),b.isAttached=!0},onAfterPageChange:function(a,b,c,d){d||this.update()},onAfterFilterChange:function(a){this.update()},update:function(){this.pages&&(this.$current.text(this.pages.current),this.$total.text(this.pages.total))},prev:function(){this.pages&&(this.template.loop&&1===this.pages.current?this.pages.last():this.pages.prev(),this.update())},next:function(){this.pages&&(this.template.loop&&this.pages.current===this.pages.total?this.pages.first():this.pages.next(),this.update())},onFooBoxPrev:function(a){a.data.self.prev()},onFooBoxNext:function(a){a.data.self.next()},onPrevClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.prev()},onNextClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.next()}}),b.template.register("image-viewer",b.ImageViewerTemplate,{template:{attachFooBox:!1,loop:!1}},{container:"foogallery fg-image-viewer",inner:"fiv-inner",innerContainer:"fiv-inner-container",controls:"fiv-ctrls",prev:"fiv-prev",next:"fiv-next",count:"fiv-count",countCurrent:"fiv-count-current",countTotal:"fiv-count-total"},{prev:"Prev",next:"Next",count:"of"})}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.obj),function(a,b,c){b.ThumbnailTemplate=b.Template.extend({construct:function(a,b){this._super(c.extend({},a,{filtering:{type:"none"},paging:{pushOrReplace:"replace",theme:"fg-light",type:"default",size:1,position:"none",scrollToTop:!1}}),b)}}),b.template.register("thumbnail",b.ThumbnailTemplate,null,{container:"foogallery fg-thumbnail"})}(FooGallery.$,FooGallery,FooGallery.utils.obj),function(a,b,c,d,e,f){b.StackAlbum=c.Class.extend({construct:function(c,f){var g=this;g.$el=d.jq(c)?c:a(c),g.el=g.$el.get(0),g.opt=e.extend({},b.StackAlbum.defaults,f,g.$el.data("foogallery")),g.$back=g.$el.find(".fg-header-back"),g.$active=g.$el.find(".fg-header-active"),g.$piles=g.$el.find(".fg-piles"),g.piles=g.$piles.find(".fg-pile").map(function(a,c){return new b.StackAlbum.Pile(g,c,{index:a})}).get(),g.ignoreResize=!1,g.robserver=new ResizeObserver(function(){!g.ignoreResize&&g.$el.is(":visible")&&g.layout(!0)})},init:function(){var a=this;a.piles.forEach(function(a){a.init()}),a.$back.on("click.foogallery",{self:a},a.onBackClick),a.robserver.observe(a.el)},destroy:function(){var a=this;a.robserver.disconnect(),a.$back.off(".foogallery"),a.piles.forEach(function(a){a.destroy()})},getLayoutInfo:function(){var a=this,b=a.opt.gutter+2*a.opt.border;return{maxWidth:a.$el.width(),space:b,halfSpace:b/2,itemWidth:a.opt.itemWidth,itemHeight:a.opt.itemHeight,itemOuterWidth:a.opt.itemWidth+2*a.opt.border,itemOuterHeight:a.opt.itemHeight+2*a.opt.border,blockWidth:a.opt.itemWidth+b,blockHeight:a.opt.itemHeight+b,border:a.opt.border,doubleBorder:2*a.opt.border,gutter:a.opt.gutter,halfGutter:a.opt.gutter/2}},layout:function(a){var b,c=this;a&&(c.$el.addClass("fg-disable-transitions"),c.$el.prop("offsetWidth")),c.hasActive?(b=c.activePile.layout(),c.activePile.setPosition(0,0,b.width,b.height),c.$piles.css({width:b.width+"px",height:b.height+"px"})):(b=c.layoutPiles(),c.$piles.css({width:b.width+"px",height:b.height+"px"})),a&&c.$el.removeClass("fg-disable-transitions")},layoutPiles:function(a){var b=this,c=b.getLayoutInfo(),e=0,f=1,g=0;return a=d.fn(a)?a:function(){},b.piles.forEach(function(b){var d=e;(e+=c.blockWidth)>c.maxWidth&&(d=0,e=c.blockWidth,f++);var h=c.blockHeight*(f-1);a(b,h,d,c.blockWidth,c.blockHeight),b.setPosition(h,d,c.blockWidth,c.blockHeight),e>g&&(g=e)}),{width:g,height:c.blockHeight*f}},setActive:function(a){var c,d=this,e=d.activePile,g=e instanceof b.StackAlbum.Pile;a=a instanceof b.StackAlbum.Pile?a:null,d.activePile=a,d.hasActive=null!==a,g&&e.collapse(),d.ignoreResize=!0,d.hasActive?(d.piles.forEach(function(b){b!==a&&b.hide(d.activePile)}),c=d.activePile.expand(),d.$active.text(a.title),d.$el.addClass("fg-has-active")):(c=d.layoutPiles(function(a){a.show()}),d.$el.removeClass("fg-has-active")),f.start(d.$piles,function(a){a.css({width:c.width+"px",height:c.height+"px"})},null,350).then(function(){d.ignoreResize=!1})},onBackClick:function(a){a.preventDefault(),a.stopPropagation(),a.data.self.setActive(null)}}),b.StackAlbum.defaults={gutter:50,itemWidth:150,itemHeight:150,border:10,angleStep:1,randomAngle:!1}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj,FooGallery.utils.transition),function(a,b,c,d,e){b.StackAlbum.Pile=c.Class.extend({construct:function(c,f,g){var h=this;h.album=c,h.$el=d.jq(f)?f:a(f),h.opt=e.extend({},b.StackAlbum.Pile.defaults,g,h.$el.data()),h.title=h.opt.title,h.items=h.$el.find(".fg-pile-item").map(function(a,c){return new b.StackAlbum.Item(h,c,{index:a})}).get(),h.$cover=a("<div/>",{class:"fg-pile-cover"}).append(a("<div/>",{class:"fg-pile-cover-content"}).append(a("<span/>",{class:"fg-pile-cover-title",text:h.opt.title}),a("<span/>",{class:"fg-pile-cover-count",text:h.items.length}))),h.top=0,h.left=0,h.isExpanded=!1},init:function(){var a=this,b=a.album.opt,c=a.getAngles(b.angleStep),d=b.randomAngle?a.randomAngle(c):b.angleStep;a.$cover.on("click.foogallery",{self:a},a.onCoverClick),a.items.forEach(function(e,f){e.init(),f>3||(0===f?(e.$el.addClass("fg-has-cover").append(a.$cover),e.load()):(f%2==0?e.setAngle(-d):e.setAngle(d),b.randomAngle?d=a.randomAngle(c):d+=b.angleStep))})},destroy:function(){var a=this;a.$cover.remove(),a.items.forEach(function(a,b){0===b&&a.$el.removeClass("fg-has-cover"),a.destroy()})},getAngles:function(a){for(var b=[],c=1;c<=3;c++)b.push(c*a);return b},randomAngle:function(a){var b=a.length,c=Math.floor(Math.random()*(b-0)+0),d=a.splice(c,1);return 1===d.length?d[0]:0},setPosition:function(a,b,c,e){var f=this;f.top=a,f.left=b,d.number(c)&&d.number(e)?f.$el.css({top:a+"px",left:b+"px",width:c+"px",height:e+"px"}):f.$el.css({top:a+"px",left:b+"px"})},layout:function(){var a=this,b=a.album.getLayoutInfo(),c=0,d=1,e=!1,f=0;return a.items.forEach(function(a){(c+=b.halfGutter)>b.maxWidth&&(c=b.halfGutter,d++,e=!0);var g=c;c+=b.itemOuterWidth+b.halfGutter,!e&&c>b.maxWidth&&(g=b.halfGutter,c=b.blockWidth,d++);var h=b.blockHeight*(d-1)+b.halfGutter;e=!1,a.setPosition(h,g,b.itemOuterWidth,b.itemOuterHeight),a.isLoaded||a.load(),c>f&&(f=c)}),{width:f,height:b.blockHeight*d}},expand:function(){var a,b=this;return b.$el.removeClass("fg-collapsed").addClass("fg-expanded"),a=b.layout(),b.setPosition(0,0,a.width,a.height),b.isExpanded=!0,a},collapse:function(){var a=this,b=a.album.getLayoutInfo();a.$el.removeClass("fg-expanded").addClass("fg-collapsed"),a.items.forEach(function(a){a.setPosition(b.halfGutter,b.halfGutter,b.itemOuterWidth,b.itemOuterHeight)});var c={width:b.blockWidth,height:b.blockHeight};return a.setPosition(0,0,c.width,c.height),a.isExpanded=!1,c},show:function(){this.$el.removeClass("fg-hidden fg-expanded fg-collapsed")},hide:function(a){var c=this;a instanceof b.StackAlbum.Pile&&c.setPosition(a.top,a.left),c.$el.addClass("fg-hidden")},onCoverClick:function(a){a.preventDefault(),a.stopPropagation();var b=a.data.self;b.album.setActive(b)}}),b.StackAlbum.Pile.defaults={index:-1,title:null}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj),function(a,b,c,d,e){b.StackAlbum.Item=c.Class.extend({construct:function(c,f,g){var h=this;h.$el=d.jq(f)?f:a(f),h.opt=e.extend({},b.StackAlbum.Item.defaults,g,h.$el.data()),h.$thumb=h.$el.find(".fg-pile-item-thumb"),h.$image=h.$el.find(".fg-pile-item-image"),h.isLoaded=!1,h.isLoading=!1,h._loading=null},init:function(){},destroy:function(){},setAngle:function(a){this.$el.css({transform:"rotate("+a+"deg)"})},setPosition:function(a,b,c,d){this.$el.css({top:a+"px",left:b+"px",width:c+"px",height:d+"px"})},load:function(){var b=this;return d.promise(b._loading)?b._loading:b._loading=a.Deferred(function(a){b.$el.addClass("fg-loading"),b.isLoading=!0,b.$image.on({"load.foogallery":function(){b.$image.off(".foogallery"),b.$el.removeClass("fg-loading"),b.isLoading=!1,b.isLoaded=!0,a.resolve()},"error.foogallery":function(){b.$image.off(".foogallery"),b.$el.removeClass("fg-loading"),b.isLoading=!1,b.isLoaded=!0,a.reject()}}),b.$image.prop("src",b.$image.attr(b.opt.src)).prop("srcset",b.$image.attr(b.opt.srcset))}).promise()}}),b.StackAlbum.Item.defaults={index:-1,src:"data-src-fg",srcset:"data-srcset-fg"}}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.is,FooGallery.utils.obj),function(a,b,c){a.fn.foogalleryStackAlbum=function(c){return this.each(function(c,d){var e=a(d),f=e.data("__FooGalleryAlbum__");f instanceof b.StackAlbum&&f.destroy(),f=new b.StackAlbum(e),f.init(),e.data("__FooGalleryAlbum__",f)})},b.loadStackAlbums=b.reloadStackAlbums=function(){a(function(){a(".foogallery-stack-album:not(.fg-ready)").foogalleryStackAlbum()}),c.ready(function(){a(".foogallery-stack-album.fg-ready").foogalleryStackAlbum()})},b.loadStackAlbums()}(FooGallery.$,FooGallery,FooGallery.utils),function(a,b,c,d,e){b.triggerPostLoad=function(c,d,e,f){var g=c.target;if(g instanceof b.Template&&g.initialized&&("after-page-change"===c.type&&!f||"after-filter-change"===c.type))try{if(g.$el.parents(".fbx-item").length>0)return;g.$el.hasClass("fbx-instance")&&window.FOOBOX&&a.fn.foobox?g.$el.foobox(window.FOOBOX.o):a("body").trigger("post-load")}catch(a){console.error(a)}},b.autoDefaults={on:{"after-page-change after-filter-change":b.triggerPostLoad}},b.autoEnabled=!0,b.auto=function(a){b.autoDefaults=d.merge(b.autoDefaults,a)},b.globalsMerged=!1,b.mergeGlobals=function(){if(!0!==b.globalsMerged&&window.FooGallery_il8n&&e.object(window.FooGallery_il8n)){var a=window.FooGallery_il8n;for(var c in a)if(a.hasOwnProperty(c)&&b[c]instanceof b.Factory&&e.object(a[c]))for(var d in a[c])a[c].hasOwnProperty(d)&&b[c].configure(d,null,null,a[c][d]);b.globalsMerged=!0}},b.load=b.reload=function(){a(function(){b.mergeGlobals(),b.autoEnabled&&a('[id^="foogallery-gallery-"]:not(.fg-ready)').foogallery(b.autoDefaults)}),c.ready(function(){b.mergeGlobals(),b.autoEnabled&&a('[id^="foogallery-gallery-"].fg-ready').foogallery(b.autoDefaults)})},b.load()}(FooGallery.$,FooGallery,FooGallery.utils,FooGallery.utils.obj,FooGallery.utils.is);
extensions/default-templates/simple-portfolio/class-simple-portfolio-gallery-template.php CHANGED
@@ -5,6 +5,9 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
5
  define('FOOGALLERY_SIMPLE_PORTFOLIO_GALLERY_TEMPLATE_URL', plugin_dir_url( __FILE__ ));
6
 
7
  class FooGallery_Simple_Portfolio_Gallery_Template {
 
 
 
8
  /**
9
  * Wire up everything we need to run the extension
10
  */
@@ -12,14 +15,9 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
12
  add_filter( 'foogallery_gallery_templates', array( $this, 'add_template' ) );
13
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
14
 
15
- add_filter( 'foogallery_located_template-simple_portfolio', array( $this, 'enqueue_dependencies' ) );
16
-
17
  //add extra fields to the templates
18
  add_filter( 'foogallery_override_gallery_template_fields-simple_portfolio', array( $this, 'add_common_thumbnail_fields' ), 101, 2 );
19
 
20
- //add the data options needed for simple portfolio
21
- add_filter( 'foogallery_build_container_data_options-simple_portfolio', array( $this, 'add_data_options' ), 10, 3 );
22
-
23
  //override specific settings when saving the gallery
24
  add_filter( 'foogallery_save_gallery_settings-simple_portfolio', array( $this, 'override_settings'), 10, 3 );
25
 
@@ -33,6 +31,9 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
33
  add_filter( 'foogallery_gallery_template_arguments-simple_portfolio', array( $this, 'build_gallery_template_arguments' ) );
34
 
35
  add_filter( 'foogallery_build_class_attribute', array( $this, 'override_class_attributes' ), 99, 2 );
 
 
 
36
  }
37
 
38
  /**
@@ -54,7 +55,7 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
54
  */
55
  function add_template( $gallery_templates ) {
56
  $gallery_templates[] = array(
57
- 'slug' => 'simple_portfolio',
58
  'name' => __( 'Simple Portfolio', 'foogallery' ),
59
  'preview_support' => true,
60
  'common_fields_support' => true,
@@ -63,6 +64,7 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
63
  'mandatory_classes' => 'fg-simple_portfolio',
64
  'thumbnail_dimensions' => true,
65
  'filtering_support' => true,
 
66
  'fields' => array(
67
  array(
68
  'id' => 'help',
@@ -93,7 +95,7 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
93
  'section' => __( 'General', 'foogallery' ),
94
  'default' => 'image',
95
  'type' => 'thumb_link',
96
- 'desc' => __( 'You can choose to link each thumbnail to the full size image, or to the image\'s attachment page, or you can choose to not link to anything.', 'foogallery' )
97
  ),
98
  array(
99
  'id' => 'lightbox',
@@ -110,7 +112,7 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
110
  'section' => __( 'General', 'foogallery' ),
111
  'type' => 'number',
112
  'class' => 'small-text',
113
- 'default' => 40,
114
  'step' => '1',
115
  'min' => '0',
116
  'row_data'=> array(
@@ -144,15 +146,6 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
144
  return $gallery_templates;
145
  }
146
 
147
- /**
148
- * Enqueue scripts that the simple portfolio template relies on
149
- */
150
- function enqueue_dependencies() {
151
- //enqueue core files
152
- foogallery_enqueue_core_gallery_template_style();
153
- foogallery_enqueue_core_gallery_template_script();
154
- }
155
-
156
  /**
157
  * Add thumbnail fields to the gallery template
158
  *
@@ -225,32 +218,6 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
225
  return $fields;
226
  }
227
 
228
- /**
229
- * Add the required data options if needed
230
- *
231
- * @param $options
232
- * @param $gallery FooGallery
233
- *
234
- * @param $attributes array
235
- *
236
- * @return array
237
- */
238
- function add_data_options($options, $gallery, $attributes) {
239
- $gutter = foogallery_gallery_template_setting( 'gutter', 40 );
240
- $options['template']['gutter'] = intval($gutter);
241
-
242
- $thumbnail_dimensions = foogallery_gallery_template_setting( 'thumbnail_dimensions', array() );
243
- if ( array_key_exists( 'width', $thumbnail_dimensions ) ) {
244
- $width = $thumbnail_dimensions['width'];
245
- $options['template']['columnWidth'] = intval( $width );
246
- }
247
-
248
- $align = foogallery_gallery_template_setting( 'align', 'center' );
249
- $options['template']['align'] = $align;
250
-
251
- return $options;
252
- }
253
-
254
  /**
255
  * Override specific settings so that the gallery template will always work
256
  *
@@ -345,7 +312,7 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
345
  * @return array
346
  */
347
  function override_class_attributes( $classes, $gallery ) {
348
- if ( 'simple_portfolio' === $gallery->gallery_template ) {
349
  if ( ( $key = array_search( 'fg-caption-hover', $classes ) ) !== false) {
350
  unset( $classes[$key] );
351
  }
@@ -355,5 +322,41 @@ if ( !class_exists( 'FooGallery_Simple_Portfolio_Gallery_Template' ) ) {
355
 
356
  return $classes;
357
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
  }
359
  }
5
  define('FOOGALLERY_SIMPLE_PORTFOLIO_GALLERY_TEMPLATE_URL', plugin_dir_url( __FILE__ ));
6
 
7
  class FooGallery_Simple_Portfolio_Gallery_Template {
8
+
9
+ const template_id = 'simple_portfolio';
10
+
11
  /**
12
  * Wire up everything we need to run the extension
13
  */
15
  add_filter( 'foogallery_gallery_templates', array( $this, 'add_template' ) );
16
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
17
 
 
 
18
  //add extra fields to the templates
19
  add_filter( 'foogallery_override_gallery_template_fields-simple_portfolio', array( $this, 'add_common_thumbnail_fields' ), 101, 2 );
20
 
 
 
 
21
  //override specific settings when saving the gallery
22
  add_filter( 'foogallery_save_gallery_settings-simple_portfolio', array( $this, 'override_settings'), 10, 3 );
23
 
31
  add_filter( 'foogallery_gallery_template_arguments-simple_portfolio', array( $this, 'build_gallery_template_arguments' ) );
32
 
33
  add_filter( 'foogallery_build_class_attribute', array( $this, 'override_class_attributes' ), 99, 2 );
34
+
35
+ //add a style block for the gallery based on the field settings for gutter, align and columnWidth
36
+ add_action( 'foogallery_loaded_template_before', array( $this, 'add_style_block' ), 10, 1 );
37
  }
38
 
39
  /**
55
  */
56
  function add_template( $gallery_templates ) {
57
  $gallery_templates[] = array(
58
+ 'slug' => self::template_id,
59
  'name' => __( 'Simple Portfolio', 'foogallery' ),
60
  'preview_support' => true,
61
  'common_fields_support' => true,
64
  'mandatory_classes' => 'fg-simple_portfolio',
65
  'thumbnail_dimensions' => true,
66
  'filtering_support' => true,
67
+ 'enqueue_core' => true,
68
  'fields' => array(
69
  array(
70
  'id' => 'help',
95
  'section' => __( 'General', 'foogallery' ),
96
  'default' => 'image',
97
  'type' => 'thumb_link',
98
+ 'desc' => __( 'You can choose to link each thumbnail to the full size image, or to the image\'s attachment page, or you can choose to not link to anything.', 'foogallery' ),
99
  ),
100
  array(
101
  'id' => 'lightbox',
112
  'section' => __( 'General', 'foogallery' ),
113
  'type' => 'number',
114
  'class' => 'small-text',
115
+ 'default' => 5,
116
  'step' => '1',
117
  'min' => '0',
118
  'row_data'=> array(
146
  return $gallery_templates;
147
  }
148
 
 
 
 
 
 
 
 
 
 
149
  /**
150
  * Add thumbnail fields to the gallery template
151
  *
218
  return $fields;
219
  }
220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  /**
222
  * Override specific settings so that the gallery template will always work
223
  *
312
  * @return array
313
  */
314
  function override_class_attributes( $classes, $gallery ) {
315
+ if ( self::template_id === $gallery->gallery_template ) {
316
  if ( ( $key = array_search( 'fg-caption-hover', $classes ) ) !== false) {
317
  unset( $classes[$key] );
318
  }
322
 
323
  return $classes;
324
  }
325
+
326
+ /**
327
+ * Add a style block based on the field settings
328
+ *
329
+ * @param $gallery FooGallery
330
+ */
331
+ function add_style_block( $gallery ) {
332
+ if ( self::template_id !== $gallery->gallery_template ) {
333
+ return;
334
+ }
335
+
336
+ $id = $gallery->container_id();
337
+ $gutter = intval( foogallery_gallery_template_setting( 'gutter', 5 ) );
338
+ $alignment = foogallery_gallery_template_setting( 'align', 'center' );
339
+ if ( $alignment === 'left' ) {
340
+ $alignment = 'flex-start';
341
+ } else if ( $alignment === 'right' ) {
342
+ $alignment = 'flex-end';
343
+ }
344
+ $thumb_width = 250;
345
+ $thumbnail_dimensions = foogallery_gallery_template_setting( 'thumbnail_dimensions', array() );
346
+ if ( array_key_exists( 'width', $thumbnail_dimensions ) ) {
347
+ $thumb_width = intval( $thumbnail_dimensions['width'] );
348
+ }
349
+ ?>
350
+ <style>
351
+ #<?php echo $id; ?>.fg-simple_portfolio {
352
+ justify-content: <?php echo $alignment; ?>;
353
+ }
354
+ #<?php echo $id; ?>.fg-simple_portfolio .fg-item {
355
+ flex-basis: <?php echo $thumb_width; ?>px;
356
+ margin: <?php echo $gutter; ?>px;
357
+ }
358
+ </style>
359
+ <?php
360
+ }
361
  }
362
  }
extensions/default-templates/thumbnail/class-thumbnail-gallery-template.php CHANGED
@@ -5,6 +5,9 @@ if ( !class_exists( 'FooGallery_Thumbnail_Gallery_Template' ) ) {
5
  define('FOOGALLERY_THUMBNAIL_GALLERY_TEMPLATE_URL', plugin_dir_url( __FILE__ ));
6
 
7
  class FooGallery_Thumbnail_Gallery_Template {
 
 
 
8
  /**
9
  * Wire up everything we need to run the extension
10
  */
@@ -12,27 +15,60 @@ if ( !class_exists( 'FooGallery_Thumbnail_Gallery_Template' ) ) {
12
  add_filter( 'foogallery_gallery_templates', array( $this, 'add_template' ) );
13
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
14
 
15
- add_filter( 'foogallery_located_template-thumbnail', array( $this, 'enqueue_dependencies' ) );
16
-
17
  //build up the thumb dimensions from some arguments
18
  add_filter( 'foogallery_calculate_thumbnail_dimensions-thumbnail', array( $this, 'build_thumbnail_dimensions_from_arguments' ), 10, 2 );
19
 
20
  //build up the thumb dimensions on save
21
  add_filter( 'foogallery_template_thumbnail_dimensions-thumbnail', array( $this, 'get_thumbnail_dimensions' ), 10, 2 );
22
 
23
- //alter the crop value if needed
24
- add_filter( 'foogallery_render_gallery_template_field_value', array( $this, 'alter_field_value'), 10, 4 );
 
 
 
25
  }
26
 
27
- function alter_field_value( $value, $field, $gallery, $template ) {
28
- //only do something if we are dealing with the thumbnail_dimensions field in this template
29
- if ( 'thumbnail' === $template['slug'] && 'thumbnail_dimensions' === $field['id'] ) {
30
- if ( !array_key_exists( 'crop', $value ) ) {
31
- $value['crop'] = true;
32
- }
33
- }
 
 
 
 
 
 
 
34
 
35
- return $value;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
37
 
38
  /**
@@ -61,6 +97,8 @@ if ( !class_exists( 'FooGallery_Thumbnail_Gallery_Template' ) ) {
61
  'lazyload_support' => true,
62
  'mandatory_classes' => 'fg-thumbnail',
63
  'thumbnail_dimensions' => true,
 
 
64
  'fields' => array(
65
  array(
66
  'id' => 'help',
@@ -74,11 +112,10 @@ if ( !class_exists( 'FooGallery_Thumbnail_Gallery_Template' ) ) {
74
  'title' => __( 'Size', 'foogallery' ),
75
  'desc' => __( 'Choose the size of your thumbnail.', 'foogallery' ),
76
  'section' => __( 'General', 'foogallery' ),
77
- 'type' => 'thumb_size',
78
  'default' => array(
79
  'width' => 250,
80
- 'height' => 200,
81
- 'crop' => true
82
  ),
83
  'row_data'=> array(
84
  'data-foogallery-change-selector' => 'input',
@@ -110,7 +147,12 @@ if ( !class_exists( 'FooGallery_Thumbnail_Gallery_Template' ) ) {
110
  'section' => __( 'General', 'foogallery' ),
111
  'default' => '',
112
  'type' => 'checkbox',
113
- 'desc' => __( 'You can link your thumbnails to Custom URL\'s (if they are set on your attachments). Fallback will be to the full size image.', 'foogallery' )
 
 
 
 
 
114
  ),
115
  array(
116
  'id' => 'lightbox',
@@ -170,15 +212,6 @@ if ( !class_exists( 'FooGallery_Thumbnail_Gallery_Template' ) ) {
170
  return $gallery_templates;
171
  }
172
 
173
- /**
174
- * Enqueue scripts that the masonry gallery template relies on
175
- */
176
- function enqueue_dependencies() {
177
- //enqueue core files
178
- foogallery_enqueue_core_gallery_template_style();
179
- foogallery_enqueue_core_gallery_template_script();
180
- }
181
-
182
  /**
183
  * Builds thumb dimensions from arguments
184
  *
@@ -192,7 +225,7 @@ if ( !class_exists( 'FooGallery_Thumbnail_Gallery_Template' ) ) {
192
  return array(
193
  'height' => intval($arguments['thumbnail_dimensions']['height']),
194
  'width' => intval($arguments['thumbnail_dimensions']['width']),
195
- 'crop' => $arguments['thumbnail_dimensions']['crop']
196
  );
197
  }
198
  return null;
5
  define('FOOGALLERY_THUMBNAIL_GALLERY_TEMPLATE_URL', plugin_dir_url( __FILE__ ));
6
 
7
  class FooGallery_Thumbnail_Gallery_Template {
8
+
9
+ const template_id = 'thumbnail';
10
+
11
  /**
12
  * Wire up everything we need to run the extension
13
  */
15
  add_filter( 'foogallery_gallery_templates', array( $this, 'add_template' ) );
16
  add_filter( 'foogallery_gallery_templates_files', array( $this, 'register_myself' ) );
17
 
 
 
18
  //build up the thumb dimensions from some arguments
19
  add_filter( 'foogallery_calculate_thumbnail_dimensions-thumbnail', array( $this, 'build_thumbnail_dimensions_from_arguments' ), 10, 2 );
20
 
21
  //build up the thumb dimensions on save
22
  add_filter( 'foogallery_template_thumbnail_dimensions-thumbnail', array( $this, 'get_thumbnail_dimensions' ), 10, 2 );
23
 
24
+ //add additional link attributes to each item
25
+ add_filter( 'foogallery_attachment_html_link_attributes', array( $this, 'alter_link_attributes'), 10, 3 );
26
+
27
+ //build up the arguments needed for rendering this template
28
+ add_filter( 'foogallery_gallery_template_arguments-thumbnail', array( $this, 'build_gallery_template_arguments' ) );
29
  }
30
 
31
+ /**
32
+ * Build up the arguments needed for rendering this gallery template
33
+ *
34
+ * @param $args
35
+ *
36
+ * @return array
37
+ */
38
+ function build_gallery_template_arguments( $args ) {
39
+ $args = foogallery_gallery_template_setting( 'thumbnail_dimensions', array() );
40
+ $args['crop'] = '1'; //we now force thumbs to be cropped
41
+
42
+ if ( foogallery_gallery_template_setting( 'link_custom_url', '' ) === 'on' ) {
43
+ $args['link'] = 'custom';
44
+ }
45
 
46
+ return $args;
47
+ }
48
+
49
+ /**
50
+ * Add a rel attribute to all image links to make the lightboxes work
51
+ *
52
+ * @param $attr
53
+ * @param $args
54
+ * @param $foogallery_attachment FooGalleryAttachment
55
+ *
56
+ * @return mixed
57
+ */
58
+ function alter_link_attributes($attr, $args, $foogallery_attachment) {
59
+ global $current_foogallery;
60
+ if ( isset( $current_foogallery ) && self::template_id === $current_foogallery->gallery_template ) {
61
+
62
+ //always set the rel so that lightboxes will group the images
63
+ $attr['rel'] = 'lightbox[' . $current_foogallery->ID . ']';
64
+
65
+ //check if we must hide the featured image within the lightbox
66
+ if ( isset( $foogallery_attachment->featured ) && foogallery_gallery_template_setting( 'exclude_featured_image', '' ) === 'on' ) {
67
+ $attr['class'] = 'fg-panel-hide';
68
+ }
69
+ }
70
+
71
+ return $attr;
72
  }
73
 
74
  /**
97
  'lazyload_support' => true,
98
  'mandatory_classes' => 'fg-thumbnail',
99
  'thumbnail_dimensions' => true,
100
+ 'paging_support' => false,
101
+ 'enqueue_core' => true,
102
  'fields' => array(
103
  array(
104
  'id' => 'help',
112
  'title' => __( 'Size', 'foogallery' ),
113
  'desc' => __( 'Choose the size of your thumbnail.', 'foogallery' ),
114
  'section' => __( 'General', 'foogallery' ),
115
+ 'type' => 'thumb_size_no_crop',
116
  'default' => array(
117
  'width' => 250,
118
+ 'height' => 200
 
119
  ),
120
  'row_data'=> array(
121
  'data-foogallery-change-selector' => 'input',
147
  'section' => __( 'General', 'foogallery' ),
148
  'default' => '',
149
  'type' => 'checkbox',
150
+ 'desc' => __( 'You can link your thumbnails to Custom URL\'s (if they are set on your attachments). Fallback will be to the full size image.', 'foogallery' ),
151
+ 'row_data'=> array(
152
+ 'data-foogallery-change-selector' => 'input',
153
+ 'data-foogallery-preview' => 'shortcode',
154
+ 'data-foogallery-value-selector' => 'input:checked',
155
+ )
156
  ),
157
  array(
158
  'id' => 'lightbox',
212
  return $gallery_templates;
213
  }
214
 
 
 
 
 
 
 
 
 
 
215
  /**
216
  * Builds thumb dimensions from arguments
217
  *
225
  return array(
226
  'height' => intval($arguments['thumbnail_dimensions']['height']),
227
  'width' => intval($arguments['thumbnail_dimensions']['width']),
228
+ 'crop' => true
229
  );
230
  }
231
  return null;
extensions/default-templates/thumbnail/gallery-thumbnail.php CHANGED
@@ -11,26 +11,12 @@ if ( !array_key_exists( 'crop', $args ) ) {
11
  $lightbox = foogallery_gallery_template_setting( 'lightbox', 'unknown' );
12
  $position = foogallery_gallery_template_setting( 'position', 'fg-center' );
13
 
14
- $caption_bgcolor = foogallery_gallery_template_setting( 'caption_bgcolor', 'rgba(0, 0, 0, 0.8)' );
15
- $caption_color = foogallery_gallery_template_setting( 'caption_color', '#fff' );
16
  $featured_attachment = $current_foogallery->featured_attachment( $args );
 
 
17
  $args['override_caption_title'] = foogallery_gallery_template_setting( 'caption_title', '' );
18
  $args['override_caption_desc'] = foogallery_gallery_template_setting( 'caption_description', '' );
19
 
20
- $thumb_url = $featured_attachment->url;
21
- if ( foogallery_gallery_template_setting( 'link_custom_url', '' ) === 'on' ) {
22
- if ( !empty( $featured_attachment->custom_url ) ) {
23
- $thumb_url = $featured_attachment->custom_url;
24
- }
25
- $args['link'] = 'custom';
26
- }
27
-
28
- $args['link_attributes'] = array(
29
- 'rel' => 'lightbox[' . $current_foogallery->ID . ']'
30
- );
31
- if ( foogallery_gallery_template_setting( 'exclude_featured_image', '' ) === 'on' ) {
32
- $args['link_attributes']['class']= 'fg-panel-hide';
33
- }
34
  $foogallery_single_thumbnail_classes = foogallery_build_class_attribute_safe( $current_foogallery, 'foogallery-single-thumbnail', 'foogallery-lightbox-' . $lightbox, $position );
35
  $foogallery_single_thumbnail_attributes = foogallery_build_container_attributes_safe( $current_foogallery, array( 'class' => $foogallery_single_thumbnail_classes ) );
36
  ?>
@@ -38,12 +24,9 @@ $foogallery_single_thumbnail_attributes = foogallery_build_container_attributes_
38
  <?php echo foogallery_attachment_html( $featured_attachment, $args ); ?>
39
  <div class="fg-st-hidden">
40
  <?php
41
- unset( $args['override_caption_title'] );
42
- unset( $args['override_caption_desc'] );
43
- unset( $args['link_attributes'] );
44
  foreach ( foogallery_current_gallery_attachments_for_rendering() as $attachment ) {
45
  if ( $attachment->url !== $featured_attachment->url ) {
46
- echo foogallery_attachment_html( $attachment, $args );
47
  }
48
  } ?>
49
  </div>
11
  $lightbox = foogallery_gallery_template_setting( 'lightbox', 'unknown' );
12
  $position = foogallery_gallery_template_setting( 'position', 'fg-center' );
13
 
 
 
14
  $featured_attachment = $current_foogallery->featured_attachment( $args );
15
+ $featured_attachment->featured = true;
16
+
17
  $args['override_caption_title'] = foogallery_gallery_template_setting( 'caption_title', '' );
18
  $args['override_caption_desc'] = foogallery_gallery_template_setting( 'caption_description', '' );
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  $foogallery_single_thumbnail_classes = foogallery_build_class_attribute_safe( $current_foogallery, 'foogallery-single-thumbnail', 'foogallery-lightbox-' . $lightbox, $position );
21
  $foogallery_single_thumbnail_attributes = foogallery_build_container_attributes_safe( $current_foogallery, array( 'class' => $foogallery_single_thumbnail_classes ) );
22
  ?>
24
  <?php echo foogallery_attachment_html( $featured_attachment, $args ); ?>
25
  <div class="fg-st-hidden">
26
  <?php
 
 
 
27
  foreach ( foogallery_current_gallery_attachments_for_rendering() as $attachment ) {
28
  if ( $attachment->url !== $featured_attachment->url ) {
29
+ echo foogallery_attachment_html( $attachment );
30
  }
31
  } ?>
32
  </div>
extensions/extensions.json.js DELETED
@@ -1,118 +0,0 @@
1
- [
2
- {
3
- "slug": "default_templates",
4
- "class": "FooGallery_Default_Templates_Extension",
5
- "categories": ["Featured" , "Free"],
6
- "title": "Default Templates",
7
- "description": "The bundled gallery templates.",
8
- "author": "FooPlugins",
9
- "author_url": "http://fooplugins.com",
10
- "thumbnail": "/assets/extension_bg.png",
11
- "tags": ["template"],
12
- "source": "bundled",
13
- "activated_by_default": true
14
- },
15
- {
16
- "slug": "albums",
17
- "class": "FooGallery_Albums_Extension",
18
- "title": "Albums",
19
- "categories": ["Featured" , "Free"],
20
- "description": "Group your galleries into albums. Boom!",
21
- "html": "Group your galleries into albums. Boom!",
22
- "author": "FooPlugins",
23
- "author_url": "http://fooplugins.com",
24
- "thumbnail": "/extensions/albums/foogallery-albums.png",
25
- "tags": ["functionality"],
26
- "source": "bundled",
27
- "css_class": "coming_soon"
28
- },
29
- {
30
- "slug": "media_categories",
31
- "class": "FooGallery_Media_Categories_Extension",
32
- "categories": ["Featured" , "Free"],
33
- "title": "Media Categories",
34
- "description": "Categorize Your Media.",
35
- "author": "FooPlugins",
36
- "author_url": "http://fooplugins.com",
37
- "thumbnail": "/assets/extension_bg.png",
38
- "tags": ["functionality"],
39
- "source": "bundled"
40
- },
41
- {
42
- "slug": "foobox-image-lightbox",
43
- "class": "FooGallery_FooBox_Free_Extension",
44
- "categories": ["Featured" , "Free"],
45
- "file": "foobox-free.php",
46
- "title": "FooBox FREE",
47
- "description": "The best lightbox for WordPress. Free",
48
- "author": "FooPlugins",
49
- "author_url": "http://fooplugins.com",
50
- "thumbnail": "/assets/extension_bg.png",
51
- "tags": ["lightbox"],
52
- "source": "repo",
53
- "activated_by_default": true,
54
- "minimum_version": "1.0.2.1"
55
- },
56
- {
57
- "slug": "foobox",
58
- "class": "FooGallery_FooBox_Extension",
59
- "categories": ["Featured" , "Premium"],
60
- "file": "foobox.php",
61
- "title": "FooBox PRO",
62
- "description": "The best lightbox for WordPress just got even better!",
63
- "price": "$27",
64
- "author": "FooPlugins",
65
- "author_url": "http://fooplugins.com",
66
- "thumbnail": "/assets/extension_bg.png",
67
- "tags": ["premium", "lightbox"],
68
- "source": "fooplugins",
69
- "download_button": {
70
- "text": "Buy - $27",
71
- "target": "_blank",
72
- "href": "http://fooplugins.com/plugins/foobox",
73
- "confirm": false
74
- },
75
- "activated_by_default": true,
76
- "minimum_version": "2.3.2"
77
- },
78
- {
79
- "slug": "polaroid_template",
80
- "class": "FooGallery_Polaroid_Template_Extension",
81
- "categories": ["Featured" , "Free"],
82
- "file": "foogallery-polaroid-template.php",
83
- "title": "Polaroid Template",
84
- "description": "A cool retro Polaroid gallery layout",
85
- "author": "FooPlugins",
86
- "author_url": "http://fooplugins.com",
87
- "thumbnail": "/assets/extension_bg.png",
88
- "tags": ["template"],
89
- "source": "github",
90
- "download_link": "https://github.com/fooplugins/foogallery-polaroid-template/archive/master.zip"
91
- },
92
- {
93
- "slug": "nextgen",
94
- "class": "FooGallery_Nextgen_Gallery_Importer_Extension",
95
- "categories": ["Free"],
96
- "title": "NextGen Importer",
97
- "description": "Imports all your existing NextGen galleries",
98
- "author": "FooPlugins",
99
- "author_url": "http://fooplugins.com",
100
- "thumbnail": "/assets/extension_bg.png",
101
- "tags": ["tools"],
102
- "source": "bundled"
103
- },
104
- {
105
- "slug": "media_menu",
106
- "class": "FooGallery_Media_Menu_Extension",
107
- "categories": ["Free"],
108
- "file": "foogallery-media-menu.php",
109
- "title": "Use Media Menu",
110
- "description": "Move FooGallery menu items underneath the Media menu rather",
111
- "author": "FooPlugins",
112
- "author_url": "http://fooplugins.com",
113
- "thumbnail": "/assets/extension_bg.png",
114
- "tags": ["admin"],
115
- "source": "github",
116
- "download_link": "https://github.com/fooplugins/foogallery-media-menu/archive/master.zip"
117
- }
118
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
extensions/nextgen-importer/class-nextgen-gallery-importer-extension.php CHANGED
@@ -22,9 +22,6 @@ if ( ! class_exists( 'FooGallery_Nextgen_Gallery_Importer_Extension' ) ) {
22
  add_action( 'foogallery_admin_menu_after', array( $this, 'add_menu' ) );
23
  add_action( 'foogallery_extension_activated-nextgen', array( $this, 'add_menu' ) );
24
 
25
- //hook into the foogallery menu
26
- add_action( 'foogallery_admin_help_after_section_one', array( $this, 'show_nextgen_import_help' ) );
27
-
28
  // Ajax calls for importing galleries
29
  add_action( 'wp_ajax_foogallery_nextgen_import', array( $this, 'ajax_nextgen_start_import' ) );
30
  add_action( 'wp_ajax_foogallery_nextgen_import_refresh', array( $this, 'ajax_nextgen_continue_import' ) );
@@ -147,28 +144,6 @@ if ( ! class_exists( 'FooGallery_Nextgen_Gallery_Importer_Extension' ) ) {
147
  die();
148
  }
149
 
150
- function show_nextgen_import_help() {
151
- ?>
152
- <div class="changelog">
153
-
154
- <div class="feature-section">
155
- <h2><?php _e( 'Import Your NextGen Galleries', 'foogallery' ); ?></h2>
156
-
157
- <img src="https://s3.amazonaws.com/foocdn/foogallery/admin-nextgen-import.jpg" class="foogallery-help-screenshot"/>
158
-
159
- <h4><?php _e( 'Import Galleries', 'foogallery' ); ?></h4>
160
-
161
- <p><?php printf( __( 'Import all your NextGen galleries in a single click, or choose the galleries you would like to migrate over to %s.', 'foogallery' ), foogallery_plugin_name() ); ?></p>
162
-
163
- <h4><?php _e( 'Import Images', 'foogallery' ); ?></h4>
164
-
165
- <p><?php _e( 'NextGen gallery images are imported into your WordPress media library, where they should be!', 'foogallery' ); ?></p>
166
-
167
- </div>
168
- </div>
169
- <?php
170
- }
171
-
172
  function ajax_nextgen_find_shortcodes() {
173
  if ( check_admin_referer( 'foogallery_nextgen_find_shortcodes' ) ) {
174
  $this->echo_findings_for_shortcode('nggallery', 'id');
22
  add_action( 'foogallery_admin_menu_after', array( $this, 'add_menu' ) );
23
  add_action( 'foogallery_extension_activated-nextgen', array( $this, 'add_menu' ) );
24
 
 
 
 
25
  // Ajax calls for importing galleries
26
  add_action( 'wp_ajax_foogallery_nextgen_import', array( $this, 'ajax_nextgen_start_import' ) );
27
  add_action( 'wp_ajax_foogallery_nextgen_import_refresh', array( $this, 'ajax_nextgen_continue_import' ) );
144
  die();
145
  }
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  function ajax_nextgen_find_shortcodes() {
148
  if ( check_admin_referer( 'foogallery_nextgen_find_shortcodes' ) ) {
149
  $this->echo_findings_for_shortcode('nggallery', 'id');
foogallery.php CHANGED
@@ -3,7 +3,7 @@
3
  /*
4
  Plugin Name: FooGallery
5
  Description: FooGallery is the most intuitive and extensible gallery management tool ever created for WordPress
6
- Version: 1.9.53
7
  Author: FooPlugins
8
  Plugin URI: http://fooplugins.com/foogallery/
9
  Author URI: http://fooplugins.com
@@ -25,7 +25,7 @@ if ( function_exists( 'foogallery_fs' ) ) {
25
  define( 'FOOGALLERY_PATH', plugin_dir_path( __FILE__ ) );
26
  define( 'FOOGALLERY_URL', plugin_dir_url( __FILE__ ) );
27
  define( 'FOOGALLERY_FILE', __FILE__ );
28
- define( 'FOOGALLERY_VERSION', '1.9.53' );
29
  define( 'FOOGALLERY_SETTINGS_VERSION', '2' );
30
  require_once FOOGALLERY_PATH . 'includes/constants.php';
31
  // Create a helper function for easy SDK access.
@@ -135,11 +135,12 @@ if ( function_exists( 'foogallery_fs' ) ) {
135
  new FooGallery_Public();
136
  }
137
 
 
 
138
  new FooGallery_Shortcodes();
139
  new FooGallery_Thumbnails();
140
  new FooGallery_Attachment_Filters();
141
  new FooGallery_Retina();
142
- new FooGallery_WPThumb_Enhancements();
143
  new FooGallery_Animated_Gif_Support();
144
  new FooGallery_Cache();
145
  new FooGallery_Common_Fields();
@@ -150,7 +151,7 @@ if ( function_exists( 'foogallery_fs' ) ) {
150
  new FooGallery_Upgrade();
151
  new FooGallery_Compatibility();
152
  new FooGallery_Extensions_Compatibility();
153
- new FooGallery_Default_Crop_Position();
154
  new FooGallery_ForceHttps();
155
  $checker = new FooGallery_Version_Check();
156
  $checker->wire_up_checker();
3
  /*
4
  Plugin Name: FooGallery
5
  Description: FooGallery is the most intuitive and extensible gallery management tool ever created for WordPress
6
+ Version: 2.0.24
7
  Author: FooPlugins
8
  Plugin URI: http://fooplugins.com/foogallery/
9
  Author URI: http://fooplugins.com
25
  define( 'FOOGALLERY_PATH', plugin_dir_path( __FILE__ ) );
26
  define( 'FOOGALLERY_URL', plugin_dir_url( __FILE__ ) );
27
  define( 'FOOGALLERY_FILE', __FILE__ );
28
+ define( 'FOOGALLERY_VERSION', '2.0.24' );
29
  define( 'FOOGALLERY_SETTINGS_VERSION', '2' );
30
  require_once FOOGALLERY_PATH . 'includes/constants.php';
31
  // Create a helper function for easy SDK access.
135
  new FooGallery_Public();
136
  }
137
 
138
+ //initialize the thumbnail manager
139
+ new FooGallery_Thumb_Manager();
140
  new FooGallery_Shortcodes();
141
  new FooGallery_Thumbnails();
142
  new FooGallery_Attachment_Filters();
143
  new FooGallery_Retina();
 
144
  new FooGallery_Animated_Gif_Support();
145
  new FooGallery_Cache();
146
  new FooGallery_Common_Fields();
151
  new FooGallery_Upgrade();
152
  new FooGallery_Compatibility();
153
  new FooGallery_Extensions_Compatibility();
154
+ new FooGallery_Crop_Position();
155
  new FooGallery_ForceHttps();
156
  $checker = new FooGallery_Version_Check();
157
  $checker->wire_up_checker();
freemius/LICENSE.txt CHANGED
@@ -1,7 +1,7 @@
1
  GNU GENERAL PUBLIC LICENSE
2
  Version 3, 29 June 2007
3
 
4
- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
  Everyone is permitted to copy and distribute verbatim copies
6
  of this license document, but changing it is not allowed.
7
 
1
  GNU GENERAL PUBLIC LICENSE
2
  Version 3, 29 June 2007
3
 
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
  Everyone is permitted to copy and distribute verbatim copies
6
  of this license document, but changing it is not allowed.
7
 
freemius/assets/css/admin/account.css CHANGED
@@ -1 +1 @@
1
- label.fs-tag,span.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn,span.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-info,span.fs-tag.fs-info{background:#00a0d2}label.fs-tag.fs-success,span.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error,span.fs-tag.fs-error{background:#dc3232}.fs-notice[data-id="license_not_whitelabeled"].success,.fs-notice[data-id="license_whitelabeled"].success{color:inherit;border-left-color:#00a0d2}.fs-notice[data-id="license_not_whitelabeled"].success label.fs-plugin-title,.fs-notice[data-id="license_whitelabeled"].success label.fs-plugin-title{display:none}#fs_account .postbox,#fs_account .widefat{max-width:800px}#fs_account h3{font-size:1.3em;padding:12px 15px;margin:0 0 12px 0;line-height:1.4;border-bottom:1px solid #F1F1F1}#fs_account h3 .dashicons{width:26px;height:26px;font-size:1.3em}#fs_account i.dashicons{font-size:1.2em;height:1.2em;width:1.2em}#fs_account .dashicons{vertical-align:middle}#fs_account .fs-header-actions{position:absolute;top:17px;right:15px;font-size:0.9em}#fs_account .fs-header-actions ul{margin:0}#fs_account .fs-header-actions li{float:left}#fs_account .fs-header-actions li form{display:inline-block}#fs_account .fs-header-actions li a{text-decoration:none}#fs_account_details .button-group{float:right}.rtl #fs_account .fs-header-actions{left:15px;right:auto}.fs-key-value-table{width:100%}.fs-key-value-table form{display:inline-block}.fs-key-value-table tr td:first-child{text-align:right}.fs-key-value-table tr td:first-child nobr{font-weight:bold}.fs-key-value-table tr td:first-child form{display:block}.fs-key-value-table tr td.fs-right{text-align:right}.fs-key-value-table tr.fs-odd{background:#ebebeb}.fs-key-value-table td,.fs-key-value-table th{padding:10px}.fs-key-value-table code{line-height:28px}.fs-key-value-table var,.fs-key-value-table code,.fs-key-value-table input[type="text"]{color:#0073AA;font-size:16px;background:none}.fs-key-value-table input[type="text"]{width:100%;font-weight:bold}.fs-field-beta_program label{margin-left:7px}label.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error{background:#dc3232}#fs_sites .fs-scrollable-table .fs-table-body{max-height:200px;overflow:auto;border:1px solid #e5e5e5}#fs_sites .fs-scrollable-table .fs-table-body>table.widefat{border:none !important}#fs_sites .fs-scrollable-table .fs-main-column{width:100%}#fs_sites .fs-scrollable-table .fs-site-details td:first-of-type{text-align:right;color:grey;width:1px}#fs_sites .fs-scrollable-table .fs-site-details td:last-of-type{text-align:right}#fs_sites .fs-scrollable-table .fs-install-details table tr td{width:1px;white-space:nowrap}#fs_sites .fs-scrollable-table .fs-install-details table tr td:last-of-type{width:auto}#fs_addons h3{border:none;margin-bottom:0;padding:4px 5px}#fs_addons td{vertical-align:middle}#fs_addons thead{white-space:nowrap}#fs_addons td:first-child,#fs_addons th:first-child{text-align:left;font-weight:bold}#fs_addons td:last-child,#fs_addons th:last-child{text-align:right}#fs_addons th{font-weight:bold}#fs_billing_address{width:100%}#fs_billing_address tr td{width:50%;padding:5px}#fs_billing_address tr:first-of-type td{padding-top:0}#fs_billing_address span{font-weight:bold}#fs_billing_address input,#fs_billing_address select{display:block;width:100%;margin-top:5px}#fs_billing_address input::-moz-placeholder,#fs_billing_address select::-moz-placeholder{color:transparent;opacity:1}#fs_billing_address input:-ms-input-placeholder,#fs_billing_address select:-ms-input-placeholder{color:transparent}#fs_billing_address input::-webkit-input-placeholder,#fs_billing_address select::-webkit-input-placeholder{color:transparent}#fs_billing_address input.fs-read-mode,#fs_billing_address select.fs-read-mode{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode td span{display:none}#fs_billing_address.fs-read-mode input,#fs_billing_address.fs-read-mode select{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode input::-moz-placeholder,#fs_billing_address.fs-read-mode select::-moz-placeholder{color:#ccc;opacity:1}#fs_billing_address.fs-read-mode input:-ms-input-placeholder,#fs_billing_address.fs-read-mode select:-ms-input-placeholder{color:#ccc}#fs_billing_address.fs-read-mode input::-webkit-input-placeholder,#fs_billing_address.fs-read-mode select::-webkit-input-placeholder{color:#ccc}#fs_billing_address button{display:block;width:100%}
1
+ label.fs-tag,span.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn,span.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-info,span.fs-tag.fs-info{background:#00a0d2}label.fs-tag.fs-success,span.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error,span.fs-tag.fs-error{background:#dc3232}.fs-notice[data-id="license_not_whitelabeled"].success,.fs-notice[data-id="license_whitelabeled"].success{color:inherit;border-left-color:#00a0d2}.fs-notice[data-id="license_not_whitelabeled"].success label.fs-plugin-title,.fs-notice[data-id="license_whitelabeled"].success label.fs-plugin-title{display:none}#fs_account .postbox,#fs_account .widefat{max-width:800px}#fs_account h3{font-size:1.3em;padding:12px 15px;margin:0 0 12px 0;line-height:1.4;border-bottom:1px solid #F1F1F1}#fs_account h3 .dashicons{width:26px;height:26px;font-size:1.3em}#fs_account i.dashicons{font-size:1.2em;height:1.2em;width:1.2em}#fs_account .dashicons{vertical-align:middle}#fs_account .fs-header-actions{position:absolute;top:17px;right:15px;font-size:0.9em}#fs_account .fs-header-actions ul{margin:0}#fs_account .fs-header-actions li{float:left}#fs_account .fs-header-actions li form{display:inline-block}#fs_account .fs-header-actions li a{text-decoration:none}#fs_account_details .button-group{float:right}.rtl #fs_account .fs-header-actions{left:15px;right:auto}.fs-key-value-table{width:100%}.fs-key-value-table form{display:inline-block}.fs-key-value-table tr td:first-child{text-align:right}.fs-key-value-table tr td:first-child nobr{font-weight:bold}.fs-key-value-table tr td:first-child form{display:block}.fs-key-value-table tr td.fs-right{text-align:right}.fs-key-value-table tr.fs-odd{background:#ebebeb}.fs-key-value-table td,.fs-key-value-table th{padding:10px}.fs-key-value-table code{line-height:28px}.fs-key-value-table var,.fs-key-value-table code,.fs-key-value-table input[type="text"]{color:#0073AA;font-size:16px;background:none}.fs-key-value-table input[type="text"]{width:100%;font-weight:bold}.fs-field-beta_program label{margin-left:7px}label.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error{background:#dc3232}#fs_sites .fs-scrollable-table .fs-table-body{max-height:200px;overflow:auto;border:1px solid #e5e5e5}#fs_sites .fs-scrollable-table .fs-table-body>table.widefat{border:none !important}#fs_sites .fs-scrollable-table .fs-main-column{width:100%}#fs_sites .fs-scrollable-table .fs-site-details td:first-of-type{text-align:right;color:grey;width:1px}#fs_sites .fs-scrollable-table .fs-site-details td:last-of-type{text-align:right}#fs_sites .fs-scrollable-table .fs-install-details table tr td{width:1px;white-space:nowrap}#fs_sites .fs-scrollable-table .fs-install-details table tr td:last-of-type{width:auto}#fs_addons h3{border:none;margin-bottom:0;padding:4px 5px}#fs_addons td{vertical-align:middle}#fs_addons thead{white-space:nowrap}#fs_addons td:first-child,#fs_addons th:first-child{text-align:left;font-weight:bold}#fs_addons td:last-child,#fs_addons th:last-child{text-align:right}#fs_addons th{font-weight:bold}#fs_billing_address{width:100%}#fs_billing_address tr td{width:50%;padding:5px}#fs_billing_address tr:first-of-type td{padding-top:0}#fs_billing_address span{font-weight:bold}#fs_billing_address input,#fs_billing_address select{display:block;width:100%;margin-top:5px}#fs_billing_address input::-moz-placeholder,#fs_billing_address select::-moz-placeholder{color:transparent;opacity:1}#fs_billing_address input:-ms-input-placeholder,#fs_billing_address select:-ms-input-placeholder{color:transparent}#fs_billing_address input::-webkit-input-placeholder,#fs_billing_address select::-webkit-input-placeholder{color:transparent}#fs_billing_address input.fs-read-mode,#fs_billing_address select.fs-read-mode{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode td span{display:none}#fs_billing_address.fs-read-mode input,#fs_billing_address.fs-read-mode select{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode input::-moz-placeholder,#fs_billing_address.fs-read-mode select::-moz-placeholder{color:#ccc;opacity:1}#fs_billing_address.fs-read-mode input:-ms-input-placeholder,#fs_billing_address.fs-read-mode select:-ms-input-placeholder{color:#ccc}#fs_billing_address.fs-read-mode input::-webkit-input-placeholder,#fs_billing_address.fs-read-mode select::-webkit-input-placeholder{color:#ccc}#fs_billing_address button{display:block;width:100%}
freemius/assets/css/admin/common.css CHANGED
@@ -1,2 +1,2 @@
1
- .fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:white;text-transform:uppercase;padding:5px 10px;-moz-border-radius:3px 0 0 3px;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;font-weight:bold;border-right:0;-moz-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);box-shadow:0 2px 1px -1px rgba(0,0,0,0.3)}.theme-browser .theme .fs-premium-theme-badge-container{position:absolute;right:0;top:0}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge{position:relative;top:0;margin-top:10px;text-align:center}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-premium-theme-badge{font-size:1.1em}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-beta-theme-badge{background:#00a0d2}.fs-switch{position:relative;display:inline-block;color:#ccc;text-shadow:0 1px 1px rgba(255,255,255,0.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);background:#ececec;box-shadow:0 0 4px rgba(0,0,0,0.1),inset 0 1px 3px 0 rgba(0,0,0,0.1);cursor:pointer}.fs-switch span{display:inline-block;width:35px;text-transform:uppercase}.fs-switch .fs-toggle{position:absolute;top:1px;width:37px;height:25px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.3);border-radius:4px;background:#fff;background-color:#fff;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #ececec), color-stop(1, #fff));background-image:-webkit-linear-gradient(top, #ececec, #fff);background-image:-moz-linear-gradient(top, #ececec, #fff);background-image:-ms-linear-gradient(top, #ececec, #fff);background-image:-o-linear-gradient(top, #ececec, #fff);background-image:linear-gradient(top, bottom, #ececec, #fff);box-shadow:inset 0 1px 0 0 rgba(255,255,255,0.5);z-index:999;-moz-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-o-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-ms-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-webkit-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1)}.fs-switch.fs-off .fs-toggle{left:2%}.fs-switch.fs-on .fs-toggle{left:54%}.fs-switch.fs-round{top:8px;padding:4px 25px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round .fs-toggle{top:0;width:24px;height:24px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round.fs-off .fs-toggle{left:-1px}.fs-switch.fs-round.fs-on{background:#0085ba}.fs-switch.fs-round.fs-on .fs-toggle{left:25px}.fs-switch.fs-small.fs-round{padding:1px 19px}.fs-switch.fs-small.fs-round .fs-toggle{top:0;width:18px;height:18px;-moz-border-radius:18px;-webkit-border-radius:18px;border-radius:18px}.fs-switch.fs-small.fs-round.fs-on .fs-toggle{left:19px}.fs-switch-feedback{margin-left:10px}.fs-switch-feedback.success{color:#71ae00}.rtl .fs-switch-feedback{margin-left:0;margin-right:10px}#fs_frame{line-height:0;font-size:0}.fs-full-size-wrapper{margin:40px 0 -65px -20px}@media (max-width: 600px){.fs-full-size-wrapper{margin:0 0 -65px -10px}}
2
- .fs-notice{position:relative}.fs-notice.fs-has-title{margin-bottom:30px !important}.fs-notice.success{color:green}.fs-notice.promotion{border-color:#00a0d2 !important;background-color:#f2fcff !important}.fs-notice .fs-notice-body{margin:.5em 0;padding:2px}.fs-notice .fs-close{cursor:pointer;color:#aaa;float:right}.fs-notice .fs-close:hover{color:#666}.fs-notice .fs-close>*{margin-top:7px;display:inline-block}.fs-notice label.fs-plugin-title{background:rgba(0,0,0,0.3);color:#fff;padding:2px 10px;position:absolute;top:100%;bottom:auto;right:auto;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;left:10px;font-size:12px;font-weight:bold;cursor:auto}div.fs-notice.updated,div.fs-notice.success,div.fs-notice.promotion{display:block !important}.rtl .fs-notice .fs-close{float:left}.fs-secure-notice{position:fixed;top:32px;left:160px;right:0;background:#ebfdeb;padding:10px 20px;color:green;z-index:9999;-moz-box-shadow:0 2px 2px rgba(6,113,6,0.3);-webkit-box-shadow:0 2px 2px rgba(6,113,6,0.3);box-shadow:0 2px 2px rgba(6,113,6,0.3);opacity:0.95;filter:alpha(opacity=95)}.fs-secure-notice:hover{opacity:1;filter:alpha(opacity=100)}.fs-secure-notice a.fs-security-proof{color:green;text-decoration:none}@media screen and (max-width: 960px){.fs-secure-notice{left:36px}}@media screen and (max-width: 600px){.fs-secure-notice{display:none}}@media screen and (max-width: 500px){#fs_promo_tab{display:none}}@media screen and (max-width: 782px){.fs-secure-notice{left:0;top:46px;text-align:center}}span.fs-submenu-item.fs-sub:before{content:'\21B3';padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:'\21B2'}.fs-submenu-item.pricing.upgrade-mode{color:greenyellow}.fs-submenu-item.pricing.trial-mode{color:#83e2ff}#adminmenu .update-plugins.fs-trial{background-color:#00b9eb}.fs-ajax-spinner{border:0;width:20px;height:20px;margin-right:5px;vertical-align:sub;display:inline-block;background:url("/wp-admin/images/wpspin_light-2x.gif");background-size:contain;margin-bottom:-2px}.wrap.fs-section h2{text-align:left}.plugins p.fs-upgrade-notice{border:0;background-color:#d54e21;padding:10px;color:#f9f9f9;margin-top:10px}
1
+ .fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:white;text-transform:uppercase;padding:5px 10px;-moz-border-radius:3px 0 0 3px;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;font-weight:bold;border-right:0;-moz-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,0.3);box-shadow:0 2px 1px -1px rgba(0,0,0,0.3)}.theme-browser .theme .fs-premium-theme-badge-container{position:absolute;right:0;top:0}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge{position:relative;top:0;margin-top:10px;text-align:center}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-premium-theme-badge{font-size:1.1em}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-beta-theme-badge{background:#00a0d2}.fs-switch{position:relative;display:inline-block;color:#ccc;text-shadow:0 1px 1px rgba(255,255,255,0.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);background:#ececec;box-shadow:0 0 4px rgba(0,0,0,0.1),inset 0 1px 3px 0 rgba(0,0,0,0.1);cursor:pointer}.fs-switch span{display:inline-block;width:35px;text-transform:uppercase}.fs-switch .fs-toggle{position:absolute;top:1px;width:37px;height:25px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.3);border-radius:4px;background:#fff;background-color:#fff;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #ececec), color-stop(1, #fff));background-image:-webkit-linear-gradient(top, #ececec, #fff);background-image:-moz-linear-gradient(top, #ececec, #fff);background-image:-ms-linear-gradient(top, #ececec, #fff);background-image:-o-linear-gradient(top, #ececec, #fff);background-image:linear-gradient(top, bottom, #ececec, #fff);box-shadow:inset 0 1px 0 0 rgba(255,255,255,0.5);z-index:999;-moz-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-o-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-ms-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);-webkit-transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1);transition:0.4s cubic-bezier(0.54, 1.6, 0.5, 1)}.fs-switch.fs-off .fs-toggle{left:2%}.fs-switch.fs-on .fs-toggle{left:54%}.fs-switch.fs-round{top:8px;padding:4px 25px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round .fs-toggle{top:0;width:24px;height:24px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round.fs-off .fs-toggle{left:-1px}.fs-switch.fs-round.fs-on{background:#0085ba}.fs-switch.fs-round.fs-on .fs-toggle{left:25px}.fs-switch.fs-small.fs-round{padding:1px 19px}.fs-switch.fs-small.fs-round .fs-toggle{top:0;width:18px;height:18px;-moz-border-radius:18px;-webkit-border-radius:18px;border-radius:18px}.fs-switch.fs-small.fs-round.fs-on .fs-toggle{left:19px}.fs-switch-feedback{margin-left:10px}.fs-switch-feedback.success{color:#71ae00}.rtl .fs-switch-feedback{margin-left:0;margin-right:10px}#fs_frame{line-height:0;font-size:0}.fs-full-size-wrapper{margin:40px 0 -65px -20px}@media (max-width: 600px){.fs-full-size-wrapper{margin:0 0 -65px -10px}}
2
+ .fs-notice{position:relative}.fs-notice.fs-has-title{margin-bottom:30px !important}.fs-notice.success{color:green}.fs-notice.promotion{border-color:#00a0d2 !important;background-color:#f2fcff !important}.fs-notice .fs-notice-body{margin:.5em 0;padding:2px}.fs-notice .fs-close{cursor:pointer;color:#aaa;float:right}.fs-notice .fs-close:hover{color:#666}.fs-notice .fs-close>*{margin-top:7px;display:inline-block}.fs-notice label.fs-plugin-title{background:rgba(0,0,0,0.3);color:#fff;padding:2px 10px;position:absolute;top:100%;bottom:auto;right:auto;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;left:10px;font-size:12px;font-weight:bold;cursor:auto}div.fs-notice.updated,div.fs-notice.success,div.fs-notice.promotion{display:block !important}.rtl .fs-notice .fs-close{float:left}.fs-secure-notice{position:fixed;top:32px;left:160px;right:0;background:#ebfdeb;padding:10px 20px;color:green;z-index:9999;-moz-box-shadow:0 2px 2px rgba(6,113,6,0.3);-webkit-box-shadow:0 2px 2px rgba(6,113,6,0.3);box-shadow:0 2px 2px rgba(6,113,6,0.3);opacity:0.95;filter:alpha(opacity=95)}.fs-secure-notice:hover{opacity:1;filter:alpha(opacity=100)}.fs-secure-notice a.fs-security-proof{color:green;text-decoration:none}@media screen and (max-width: 960px){.fs-secure-notice{left:36px}}@media screen and (max-width: 600px){.fs-secure-notice{display:none}}@media screen and (max-width: 1250px){#fs_promo_tab{display:none}}@media screen and (max-width: 782px){.fs-secure-notice{left:0;top:46px;text-align:center}}span.fs-submenu-item.fs-sub:before{content:'\21B3';padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:'\21B2'}.fs-submenu-item.pricing.upgrade-mode{color:greenyellow}.fs-submenu-item.pricing.trial-mode{color:#83e2ff}#adminmenu .update-plugins.fs-trial{background-color:#00b9eb}.fs-ajax-spinner{border:0;width:20px;height:20px;margin-right:5px;vertical-align:sub;display:inline-block;background:url("/wp-admin/images/wpspin_light-2x.gif");background-size:contain;margin-bottom:-2px}.wrap.fs-section h2{text-align:left}.plugins p.fs-upgrade-notice{border:0;background-color:#d54e21;padding:10px;color:#f9f9f9;margin-top:10px}
freemius/assets/css/admin/connect.css CHANGED
@@ -1 +1 @@
1
- #fs_connect{width:480px;-moz-box-shadow:0px 1px 2px rgba(0,0,0,0.3);-webkit-box-shadow:0px 1px 2px rgba(0,0,0,0.3);box-shadow:0px 1px 2px rgba(0,0,0,0.3);margin:20px 0}@media screen and (max-width: 479px){#fs_connect{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;width:auto;margin:0 0 0 -10px}}#fs_connect .fs-content{background:#fff;padding:15px 20px}#fs_connect .fs-content .fs-error{background:snow;color:#d3135a;border:1px solid #d3135a;-moz-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);text-align:center;padding:5px;margin-bottom:10px}#fs_connect .fs-content p{margin:0;padding:0;font-size:1.2em}#fs_connect .fs-license-key-container{position:relative;width:280px;margin:10px auto 0 auto}#fs_connect .fs-license-key-container input{width:100%}#fs_connect .fs-license-key-container .dashicons{position:absolute;top:5px;right:5px}#fs_connect.require-license-key .fs-sites-list-container td{cursor:pointer}#fs_connect #delegate_to_site_admins{margin-right:15px;float:right;height:26px;vertical-align:middle;line-height:37px;font-weight:bold;border-bottom:1px dashed;text-decoration:none}#fs_connect #delegate_to_site_admins.rtl{margin-left:15px;margin-right:0}#fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}#fs_connect .fs-actions .button{padding:0 10px 1px;line-height:35px;height:37px;font-size:16px;margin-bottom:0}#fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}#fs_connect .fs-actions .button.button-primary{padding-right:15px;padding-left:15px}#fs_connect .fs-actions .button.button-primary:after{content:' \279C'}#fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}#fs_connect .fs-actions .button.button-secondary{float:right}#fs_connect.fs-anonymous-disabled .fs-actions .button.button-primary{width:100%}#fs_connect .fs-permissions{padding:10px 20px;background:#FEFEFE;-moz-transition:background 0.5s ease;-o-transition:background 0.5s ease;-ms-transition:background 0.5s ease;-webkit-transition:background 0.5s ease;transition:background 0.5s ease}#fs_connect .fs-permissions .fs-license-sync-disclaimer{text-align:center;margin-top:0}#fs_connect .fs-permissions .fs-trigger{font-size:0.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions ul{height:0;overflow:hidden;margin:0}#fs_connect .fs-permissions ul li{margin-bottom:12px}#fs_connect .fs-permissions ul li:last-child{margin-bottom:0}#fs_connect .fs-permissions ul li i.dashicons{float:left;font-size:40px;width:40px;height:40px}#fs_connect .fs-permissions ul li .fs-switch{float:right}#fs_connect .fs-permissions ul li .fs-permission-description{margin-left:55px}#fs_connect .fs-permissions ul li .fs-permission-description span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}#fs_connect .fs-permissions.fs-open{background:#fff}#fs_connect .fs-permissions.fs-open ul{height:auto;margin:20px 20px 10px 20px}@media screen and (max-width: 479px){#fs_connect .fs-permissions{background:#fff}#fs_connect .fs-permissions .fs-trigger{display:none}#fs_connect .fs-permissions ul{height:auto;margin:20px}}#fs_connect .fs-freemium-licensing{padding:8px;background:#777;color:#fff}#fs_connect .fs-freemium-licensing p{text-align:center;display:block;margin:0;padding:0}#fs_connect .fs-freemium-licensing a{color:#C2EEFF;text-decoration:underline}#fs_connect .fs-visual{padding:12px;line-height:0;background:#fafafa;height:80px;position:relative}#fs_connect .fs-visual .fs-site-icon{position:absolute;left:20px;top:10px}#fs_connect .fs-visual .fs-connect-logo{position:absolute;right:20px;top:10px}#fs_connect .fs-visual .fs-plugin-icon{position:absolute;top:10px;left:50%;margin-left:-40px}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-site-icon,#fs_connect .fs-visual img,#fs_connect .fs-visual object{width:80px;height:80px}#fs_connect .fs-visual .dashicons-wordpress{font-size:64px;background:#01749a;color:#fff;width:64px;height:64px;padding:8px}#fs_connect .fs-visual .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-visual .dashicons-plus.fs-first{left:28%}#fs_connect .fs-visual .dashicons-plus.fs-second{left:65%}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-connect-logo,#fs_connect .fs-visual .fs-site-icon{border:1px solid #ccc;padding:1px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:0.85em;padding:5px;background:rgba(0,0,0,0.05)}#fs_connect .fs-terms,#fs_connect .fs-terms a{color:#999}#fs_connect .fs-terms a{text-decoration:none}.fs-multisite-options-container{margin-top:10px;border:1px solid #ccc;padding:5px}.fs-multisite-options-container a{text-decoration:none}.fs-multisite-options-container a:focus{box-shadow:none}.fs-multisite-options-container a.selected{font-weight:bold}.fs-multisite-options-container.fs-apply-on-all-sites{border:0 none;padding:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options{border-spacing:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options td:not(:first-child){display:none}.fs-multisite-options-container .fs-sites-list-container{display:none;overflow:auto}.fs-multisite-options-container .fs-sites-list-container table td{border-top:1px solid #ccc;padding:4px 2px}.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity 0.3s ease-in-out;-o-transition:opacity 0.3s ease-in-out;-ms-transition:opacity 0.3s ease-in-out;-webkit-transition:opacity 0.3s ease-in-out;transition:opacity 0.3s ease-in-out;position:absolute;background:rgba(0,0,0,0.8);color:#fff;font-family:'arial', serif;font-size:12px;padding:10px;z-index:999999;bottom:100%;margin-bottom:5px;left:0;right:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.2);box-shadow:1px 1px 1px rgba(0,0,0,0.2);line-height:1.3em;font-weight:bold;text-align:left}.rtl .fs-tooltip-trigger .fs-tooltip{text-align:right}.fs-tooltip-trigger .fs-tooltip::after{content:' ';display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:rgba(0,0,0,0.8) transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl .fs-tooltip-trigger .fs-tooltip::after{right:21px;left:auto}.fs-tooltip-trigger:hover .fs-tooltip{visibility:visible;opacity:1}#fs_marketing_optin{display:none;margin-top:10px;border:1px solid #ccc;padding:10px;line-height:1.5em}#fs_marketing_optin .fs-message{display:block;margin-bottom:5px;font-size:1.05em;font-weight:600}#fs_marketing_optin.error{border:1px solid #d3135a;background:#fee}#fs_marketing_optin.error .fs-message{color:#d3135a}#fs_marketing_optin .fs-input-container{margin-top:5px}#fs_marketing_optin .fs-input-container label{margin-top:5px;display:block}#fs_marketing_optin .fs-input-container label input{float:left;margin:1px 0 0 0}#fs_marketing_optin .fs-input-container label:first-child{display:block;margin-bottom:2px}#fs_marketing_optin .fs-input-label{display:block;margin-left:20px}#fs_marketing_optin .fs-input-label .underlined{text-decoration:underline}.rtl #fs_marketing_optin .fs-input-container label input{float:right}.rtl #fs_marketing_optin .fs-input-label{margin-left:0;margin-right:20px}.rtl #fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}.rtl #fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}.rtl #fs_connect .fs-actions .button.button-primary:after{content:' \000bb'}.rtl #fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}.rtl #fs_connect .fs-actions .button.button-secondary{float:left}.rtl #fs_connect .fs-permissions ul li .fs-permission-description{margin-right:55px;margin-left:0}.rtl #fs_connect .fs-permissions ul li .fs-switch{float:left}.rtl #fs_connect .fs-permissions ul li i.dashicons{float:right}.rtl #fs_connect .fs-visual .fs-site-icon{right:20px;left:auto}.rtl #fs_connect .fs-visual .fs-connect-logo{right:auto;left:20px}#fs_theme_connect_wrapper{position:fixed;top:0;height:100%;width:100%;z-index:99990;background:rgba(0,0,0,0.75);text-align:center;overflow-y:auto}#fs_theme_connect_wrapper:before{content:"";display:inline-block;vertical-align:middle;height:100%}#fs_theme_connect_wrapper>button.close{color:white;cursor:pointer;height:40px;width:40px;position:absolute;right:0;border:0;background-color:transparent;top:32px}#fs_theme_connect_wrapper #fs_connect{top:0;text-align:left;display:inline-block;vertical-align:middle;margin-top:52px;margin-bottom:20px}#fs_theme_connect_wrapper #fs_connect .fs-terms{background:rgba(140,140,140,0.64)}#fs_theme_connect_wrapper #fs_connect .fs-terms,#fs_theme_connect_wrapper #fs_connect .fs-terms a{color:#c5c5c5}.wp-pointer-content #fs_connect{margin:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.fs-opt-in-pointer .wp-pointer-content{padding:0}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow{border-bottom-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow-inner{border-bottom-color:#fafafa}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow{border-top-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow-inner{border-top-color:#fafafa}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow{border-right-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow-inner{border-right-color:#fafafa}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow{border-left-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow-inner{border-left-color:#fafafa}
1
+ #fs_connect{width:480px;-moz-box-shadow:0px 1px 2px rgba(0,0,0,0.3);-webkit-box-shadow:0px 1px 2px rgba(0,0,0,0.3);box-shadow:0px 1px 2px rgba(0,0,0,0.3);margin:20px 0}@media screen and (max-width: 479px){#fs_connect{-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;width:auto;margin:0 0 0 -10px}}#fs_connect .fs-content{background:#fff;padding:15px 20px}#fs_connect .fs-content .fs-error{background:snow;color:#d3135a;border:1px solid #d3135a;-moz-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);text-align:center;padding:5px;margin-bottom:10px}#fs_connect .fs-content p{margin:0;padding:0;font-size:1.2em}#fs_connect .fs-license-key-container{position:relative;width:280px;margin:10px auto 0 auto}#fs_connect .fs-license-key-container input{width:100%}#fs_connect .fs-license-key-container .dashicons{position:absolute;top:5px;right:5px}#fs_connect.require-license-key .fs-sites-list-container td{cursor:pointer}#fs_connect #delegate_to_site_admins{margin-right:15px;float:right;height:26px;vertical-align:middle;line-height:37px;font-weight:bold;border-bottom:1px dashed;text-decoration:none}#fs_connect #delegate_to_site_admins.rtl{margin-left:15px;margin-right:0}#fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}#fs_connect .fs-actions .button{padding:0 10px 1px;line-height:35px;height:37px;font-size:16px;margin-bottom:0}#fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}#fs_connect .fs-actions .button.button-primary{padding-right:15px;padding-left:15px}#fs_connect .fs-actions .button.button-primary:after{content:' \279C'}#fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}#fs_connect .fs-actions .button.button-secondary{float:right}#fs_connect.fs-anonymous-disabled .fs-actions .button.button-primary{width:100%}#fs_connect .fs-permissions{padding:10px 20px;background:#FEFEFE;-moz-transition:background 0.5s ease;-o-transition:background 0.5s ease;-ms-transition:background 0.5s ease;-webkit-transition:background 0.5s ease;transition:background 0.5s ease}#fs_connect .fs-permissions .fs-license-sync-disclaimer{text-align:center;margin-top:0}#fs_connect .fs-permissions>.fs-trigger{font-size:0.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions ul{height:0;overflow:hidden;margin:0}#fs_connect .fs-permissions ul li{margin-bottom:12px}#fs_connect .fs-permissions ul li:last-child{margin-bottom:0}#fs_connect .fs-permissions ul li>i.dashicons{float:left;font-size:40px;width:40px;height:40px}#fs_connect .fs-permissions ul li .fs-switch{float:right}#fs_connect .fs-permissions ul li .fs-permission-description{margin-left:55px}#fs_connect .fs-permissions ul li .fs-permission-description span{font-weight:bold;text-transform:uppercase;color:#23282d}#fs_connect .fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}#fs_connect .fs-permissions.fs-open{background:#fff}#fs_connect .fs-permissions.fs-open ul{overflow:initial;height:auto;margin:20px 20px 10px 20px}@media screen and (max-width: 479px){#fs_connect .fs-permissions{background:#fff}#fs_connect .fs-permissions .fs-trigger{display:none}#fs_connect .fs-permissions ul{height:auto;margin:20px}}#fs_connect .fs-freemium-licensing{padding:8px;background:#777;color:#fff}#fs_connect .fs-freemium-licensing p{text-align:center;display:block;margin:0;padding:0}#fs_connect .fs-freemium-licensing a{color:#C2EEFF;text-decoration:underline}#fs_connect .fs-visual{padding:12px;line-height:0;background:#fafafa;height:80px;position:relative}#fs_connect .fs-visual .fs-site-icon{position:absolute;left:20px;top:10px}#fs_connect .fs-visual .fs-connect-logo{position:absolute;right:20px;top:10px}#fs_connect .fs-visual .fs-plugin-icon{position:absolute;top:10px;left:50%;margin-left:-40px}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-site-icon,#fs_connect .fs-visual img,#fs_connect .fs-visual object{width:80px;height:80px}#fs_connect .fs-visual .dashicons-wordpress{font-size:64px;background:#01749a;color:#fff;width:64px;height:64px;padding:8px}#fs_connect .fs-visual .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-visual .dashicons-plus.fs-first{left:28%}#fs_connect .fs-visual .dashicons-plus.fs-second{left:65%}#fs_connect .fs-visual .fs-plugin-icon,#fs_connect .fs-visual .fs-connect-logo,#fs_connect .fs-visual .fs-site-icon{border:1px solid #ccc;padding:1px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:0.85em;padding:5px;background:rgba(0,0,0,0.05)}#fs_connect .fs-terms,#fs_connect .fs-terms a{color:#999}#fs_connect .fs-terms a{text-decoration:none}.fs-multisite-options-container{margin-top:10px;border:1px solid #ccc;padding:5px}.fs-multisite-options-container a{text-decoration:none}.fs-multisite-options-container a:focus{box-shadow:none}.fs-multisite-options-container a.selected{font-weight:bold}.fs-multisite-options-container.fs-apply-on-all-sites{border:0 none;padding:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options{border-spacing:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options td:not(:first-child){display:none}.fs-multisite-options-container .fs-sites-list-container{display:none;overflow:auto}.fs-multisite-options-container .fs-sites-list-container table td{border-top:1px solid #ccc;padding:4px 2px}.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity 0.3s ease-in-out;-o-transition:opacity 0.3s ease-in-out;-ms-transition:opacity 0.3s ease-in-out;-webkit-transition:opacity 0.3s ease-in-out;transition:opacity 0.3s ease-in-out;position:absolute;background:rgba(0,0,0,0.8);color:#fff !important;font-family:'arial', serif;font-size:12px;padding:10px;z-index:999999;bottom:100%;margin-bottom:5px;left:-17px;right:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,0.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,0.2);box-shadow:1px 1px 1px rgba(0,0,0,0.2);line-height:1.3em;font-weight:bold;text-align:left;text-transform:none !important}.rtl .fs-tooltip-trigger .fs-tooltip{text-align:right;left:auto;right:-17px}.fs-tooltip-trigger .fs-tooltip::after{content:' ';display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:rgba(0,0,0,0.8) transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl .fs-tooltip-trigger .fs-tooltip::after{right:21px;left:auto}.fs-tooltip-trigger:hover .fs-tooltip{visibility:visible;opacity:1}#fs_marketing_optin{display:none;margin-top:10px;border:1px solid #ccc;padding:10px;line-height:1.5em}#fs_marketing_optin .fs-message{display:block;margin-bottom:5px;font-size:1.05em;font-weight:600}#fs_marketing_optin.error{border:1px solid #d3135a;background:#fee}#fs_marketing_optin.error .fs-message{color:#d3135a}#fs_marketing_optin .fs-input-container{margin-top:5px}#fs_marketing_optin .fs-input-container label{margin-top:5px;display:block}#fs_marketing_optin .fs-input-container label input{float:left;margin:1px 0 0 0}#fs_marketing_optin .fs-input-container label:first-child{display:block;margin-bottom:2px}#fs_marketing_optin .fs-input-label{display:block;margin-left:20px}#fs_marketing_optin .fs-input-label .underlined{text-decoration:underline}.rtl #fs_marketing_optin .fs-input-container label input{float:right}.rtl #fs_marketing_optin .fs-input-label{margin-left:0;margin-right:20px}.rtl #fs_connect .fs-actions{padding:10px 20px;background:#C0C7CA}.rtl #fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}.rtl #fs_connect .fs-actions .button.button-primary:after{content:' \000bb'}.rtl #fs_connect .fs-actions .button.button-primary.fs-loading:after{content:''}.rtl #fs_connect .fs-actions .button.button-secondary{float:left}.rtl #fs_connect .fs-permissions ul li .fs-permission-description{margin-right:55px