Responsive Lightbox & Gallery - Version 2.2.0

Version Description

  • New: Introducing Remote Library feature
  • New: Gutenberg editor compatibility
  • Tweak: PHP 7.3 support
Download this release

Release Info

Developer dfactory
Plugin Icon 128x128 Responsive Lightbox & Gallery
Version 2.2.0
Comparing to
See all releases

Code changes from version 2.1 to 2.2.0

Files changed (136) hide show
  1. assets/featherlight/featherlight.css +158 -160
  2. assets/featherlight/featherlight.gallery.css +122 -122
  3. assets/featherlight/featherlight.gallery.js +169 -169
  4. assets/featherlight/featherlight.gallery.min.css +8 -8
  5. assets/featherlight/featherlight.gallery.min.js +6 -6
  6. assets/featherlight/featherlight.js +641 -631
  7. assets/featherlight/featherlight.min.css +8 -8
  8. assets/featherlight/featherlight.min.js +8 -8
  9. assets/imagelightbox/css/imagelightbox.css +7 -5
  10. assets/imagelightbox/css/imagelightbox.min.css +0 -1
  11. assets/imagelightbox/js/imagelightbox.js +0 -315
  12. assets/imagelightbox/js/imagelightbox.min.js +1 -1
  13. assets/infinitescroll/infinite-scroll.pkgd.js +2204 -2197
  14. assets/infinitescroll/infinite-scroll.pkgd.min.js +12 -12
  15. assets/jstree/jstree.js +8604 -8588
  16. assets/jstree/jstree.min.js +6 -6
  17. assets/jstree/themes/default-dark/32px.png +0 -0
  18. assets/jstree/themes/default-dark/40px.png +0 -0
  19. assets/jstree/themes/default-dark/style.css +1146 -1152
  20. assets/jstree/themes/default-dark/style.min.css +1 -1
  21. assets/jstree/themes/default-dark/throbber.gif +0 -0
  22. assets/jstree/themes/default/32px.png +0 -0
  23. assets/jstree/themes/default/40px.png +0 -0
  24. assets/jstree/themes/default/style.css +1102 -1108
  25. assets/jstree/themes/default/style.min.css +1 -1
  26. assets/jstree/themes/default/throbber.gif +0 -0
  27. assets/knockout/knockout.js +6557 -0
  28. assets/knockout/knockout.min.js +138 -0
  29. assets/masonry/masonry.pkgd.js +2504 -2502
  30. assets/masonry/masonry.pkgd.min.js +9 -9
  31. assets/prettyphoto/css/prettyPhoto.css +170 -796
  32. assets/prettyphoto/css/prettyPhoto.min.css +0 -1
  33. assets/prettyphoto/js/jquery.prettyPhoto.js +2 -977
  34. assets/prettyphoto/js/jquery.prettyPhoto.min.js +0 -1
  35. assets/select2/css/select2.css +71 -55
  36. assets/select2/css/select2.min.css +1 -1
  37. assets/select2/js/i18n/af.js +1 -1
  38. assets/select2/js/i18n/ar.js +1 -1
  39. assets/select2/js/i18n/az.js +1 -1
  40. assets/select2/js/i18n/bg.js +1 -1
  41. assets/select2/js/i18n/bs.js +1 -1
  42. assets/select2/js/i18n/ca.js +1 -1
  43. assets/select2/js/i18n/cs.js +1 -1
  44. assets/select2/js/i18n/da.js +1 -1
  45. assets/select2/js/i18n/de.js +1 -1
  46. assets/select2/js/i18n/dsb.js +1 -1
  47. assets/select2/js/i18n/el.js +1 -1
  48. assets/select2/js/i18n/en.js +1 -1
  49. assets/select2/js/i18n/es.js +1 -1
  50. assets/select2/js/i18n/et.js +1 -1
  51. assets/select2/js/i18n/eu.js +1 -1
  52. assets/select2/js/i18n/fa.js +1 -1
  53. assets/select2/js/i18n/fi.js +1 -1
  54. assets/select2/js/i18n/fr.js +2 -2
  55. assets/select2/js/i18n/gl.js +1 -1
  56. assets/select2/js/i18n/he.js +1 -1
  57. assets/select2/js/i18n/hi.js +1 -1
  58. assets/select2/js/i18n/hr.js +1 -1
  59. assets/select2/js/i18n/hsb.js +1 -1
  60. assets/select2/js/i18n/hu.js +1 -1
  61. assets/select2/js/i18n/hy.js +1 -1
  62. assets/select2/js/i18n/id.js +1 -1
  63. assets/select2/js/i18n/is.js +1 -1
  64. assets/select2/js/i18n/it.js +1 -1
  65. assets/select2/js/i18n/ja.js +1 -1
  66. assets/select2/js/i18n/km.js +1 -1
  67. assets/select2/js/i18n/ko.js +1 -1
  68. assets/select2/js/i18n/lt.js +1 -1
  69. assets/select2/js/i18n/lv.js +1 -1
  70. assets/select2/js/i18n/mk.js +1 -1
  71. assets/select2/js/i18n/ms.js +1 -1
  72. assets/select2/js/i18n/nb.js +2 -2
  73. assets/select2/js/i18n/nl.js +1 -1
  74. assets/select2/js/i18n/pl.js +1 -1
  75. assets/select2/js/i18n/ps.js +1 -1
  76. assets/select2/js/i18n/pt-BR.js +1 -1
  77. assets/select2/js/i18n/pt.js +1 -1
  78. assets/select2/js/i18n/ro.js +1 -1
  79. assets/select2/js/i18n/ru.js +1 -1
  80. assets/select2/js/i18n/sk.js +1 -1
  81. assets/select2/js/i18n/sl.js +1 -1
  82. assets/select2/js/i18n/sr-Cyrl.js +1 -1
  83. assets/select2/js/i18n/sr.js +1 -1
  84. assets/select2/js/i18n/sv.js +1 -1
  85. assets/select2/js/i18n/th.js +1 -1
  86. assets/select2/js/i18n/tk.js +0 -3
  87. assets/select2/js/i18n/tr.js +1 -1
  88. assets/select2/js/i18n/uk.js +1 -1
  89. assets/select2/js/i18n/vi.js +1 -1
  90. assets/select2/js/i18n/zh-CN.js +1 -1
  91. assets/select2/js/i18n/zh-TW.js +1 -1
  92. assets/select2/js/select2.full.js +0 -6559
  93. assets/select2/js/select2.full.min.js +0 -1
  94. assets/swipebox/css/swipebox.css +0 -295
  95. assets/swipebox/css/swipebox.min.css +0 -1
  96. assets/swipebox/js/jquery.swipebox.js +0 -958
  97. assets/swipebox/js/jquery.swipebox.min.js +0 -2
  98. assets/tosrus/css/jquery.tosrus.all.css +484 -479
  99. assets/tosrus/css/jquery.tosrus.all.min.css +1 -0
  100. assets/tosrus/css/jquery.tosrus.min.all.css +0 -1
  101. assets/tosrus/js/hammer.js +0 -2643
  102. assets/tosrus/js/hammer.min.js +0 -7
  103. assets/tosrus/js/jquery.tosrus.all.js +0 -619
  104. assets/tosrus/js/jquery.tosrus.min.all.js +82 -72
  105. assets/tosrus/js/jquery.tosrus.min.js +13 -0
  106. css/admin-folders.css +63 -65
  107. css/admin-galleries.css +472 -460
  108. css/{admin-post.css → admin-gallery.css} +58 -58
  109. css/admin.css +656 -652
  110. css/gutenberg.min.css +1 -0
  111. includes/class-folders.php +1087 -1142
  112. includes/class-frontend.php +2091 -2089
  113. includes/class-galleries.php +4056 -3616
  114. includes/class-remote-library-api.php +207 -0
  115. includes/class-remote-library.php +515 -0
  116. includes/class-settings.php +2487 -2426
  117. includes/class-tour.php +327 -296
  118. includes/class-welcome.php +144 -135
  119. includes/class-widgets.php +581 -569
  120. includes/functions.php +1 -1
  121. includes/providers/class-flickr.php +250 -0
  122. includes/providers/class-unsplash.php +210 -0
  123. includes/providers/class-wikimedia.php +248 -0
  124. js/admin-folders.js +1270 -1116
  125. js/admin-galleries.js +705 -516
  126. js/admin-gallery.js +333 -0
  127. js/admin-media.js +487 -0
  128. js/admin-post.js +0 -231
  129. js/admin-widgets.js +5 -5
  130. js/admin.js +76 -66
  131. js/front.js +802 -792
  132. js/gutenberg.min.js +12 -0
  133. languages/responsive-lightbox.pot +1028 -738
  134. library/simplehtmldom/simple_html_dom.php +2353 -0
  135. readme.txt +98 -32
  136. responsive-lightbox.php +1570 -1414
assets/featherlight/featherlight.css CHANGED
@@ -1,160 +1,158 @@
1
- /**
2
- * Featherlight – ultra slim jQuery lightbox
3
- * Version 1.7.12 - http://noelboss.github.io/featherlight/
4
- *
5
- * Copyright 2017, Noël Raoul Bossart (http://www.noelboss.com)
6
- * MIT Licensed.
7
- **/
8
- @media all {
9
- html.with-featherlight {
10
- /* disable global scrolling when featherlights are visible */
11
- overflow: hidden;
12
- }
13
-
14
- .featherlight {
15
- display: none;
16
-
17
- /* dimensions: spanning the background from edge to edge */
18
- position:fixed;
19
- top: 0; right: 0; bottom: 0; left: 0;
20
- z-index: 2147483647; /* z-index needs to be >= elements on the site. */
21
-
22
- /* position: centering content */
23
- text-align: center;
24
-
25
- /* insures that the ::before pseudo element doesn't force wrap with fixed width content; */
26
- white-space: nowrap;
27
-
28
- /* styling */
29
- cursor: pointer;
30
- background: #333;
31
- /* IE8 "hack" for nested featherlights */
32
- background: rgba(0, 0, 0, 0);
33
- }
34
-
35
- /* support for nested featherlights. Does not work in IE8 (use JS to fix) */
36
- .featherlight:last-of-type {
37
- background: rgba(0, 0, 0, 0.8);
38
- }
39
-
40
- .featherlight:before {
41
- /* position: trick to center content vertically */
42
- content: '';
43
- display: inline-block;
44
- height: 100%;
45
- vertical-align: middle;
46
- }
47
-
48
- .featherlight .featherlight-content {
49
- /* make content container for positioned elements (close button) */
50
- position: relative;
51
-
52
- /* position: centering vertical and horizontal */
53
- text-align: left;
54
- vertical-align: middle;
55
- display: inline-block;
56
-
57
- /* dimensions: cut off images */
58
- overflow: auto;
59
- padding: 25px 25px 0;
60
- border-bottom: 25px solid transparent;
61
-
62
- /* dimensions: handling large content */
63
- margin-left: 5%;
64
- margin-right: 5%;
65
- max-height: 95%;
66
-
67
- /* styling */
68
- background: #fff;
69
- cursor: auto;
70
-
71
- /* reset white-space wrapping */
72
- white-space: normal;
73
- }
74
-
75
- /* contains the content */
76
- .featherlight .featherlight-inner {
77
- /* make sure its visible */
78
- display: block;
79
- }
80
-
81
- /* don't show these though */
82
- .featherlight script.featherlight-inner,
83
- .featherlight link.featherlight-inner,
84
- .featherlight style.featherlight-inner {
85
- display: none;
86
- }
87
-
88
- .featherlight .featherlight-close-icon {
89
- /* position: centering vertical and horizontal */
90
- position: absolute;
91
- z-index: 9999;
92
- top: 0;
93
- right: 0;
94
-
95
- /* dimensions: 25px x 25px */
96
- line-height: 25px;
97
- width: 25px;
98
-
99
- /* styling */
100
- cursor: pointer;
101
- text-align: center;
102
- font-family: Arial, sans-serif;
103
- background: #fff; /* Set the background in case it overlaps the content */
104
- background: rgba(255, 255, 255, 0.3);
105
- color: #000;
106
- border: none;
107
- padding: 0;
108
- }
109
-
110
- /* See http://stackoverflow.com/questions/16077341/how-to-reset-all-default-styles-of-the-html5-button-element */
111
- .featherlight .featherlight-close-icon::-moz-focus-inner {
112
- border: 0;
113
- padding: 0;
114
- }
115
-
116
- .featherlight .featherlight-image {
117
- /* styling */
118
- width: 100%;
119
- }
120
-
121
-
122
- .featherlight-iframe .featherlight-content {
123
- /* removed the border for image croping since iframe is edge to edge */
124
- border-bottom: 0;
125
- padding: 0;
126
- -webkit-overflow-scrolling: touch;
127
- overflow-y: scroll;
128
- }
129
-
130
- .featherlight iframe {
131
- /* styling */
132
- border: none;
133
- }
134
-
135
- .featherlight * { /* See https://github.com/noelboss/featherlight/issues/42 */
136
- -webkit-box-sizing: border-box;
137
- -moz-box-sizing: border-box;
138
- box-sizing: border-box;
139
- }
140
- }
141
-
142
- /* handling phones and small screens */
143
- @media only screen and (max-width: 1024px) {
144
- .featherlight .featherlight-content {
145
- /* dimensions: maximize lightbox with for small screens */
146
- margin-left: 0;
147
- margin-right: 0;
148
- max-height: 98%;
149
-
150
- padding: 10px 10px 0;
151
- border-bottom: 10px solid transparent;
152
- }
153
- }
154
-
155
- /* hide non featherlight items when printing */
156
- @media print {
157
- html.with-featherlight > * > :not(.featherlight) {
158
- display: none;
159
- }
160
- }
1
+ /**
2
+ * Featherlight – ultra slim jQuery lightbox
3
+ * Version 1.7.13 - http://noelboss.github.io/featherlight/
4
+ *
5
+ * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
6
+ * MIT Licensed.
7
+ **/
8
+
9
+ html.with-featherlight {
10
+ /* disable global scrolling when featherlights are visible */
11
+ overflow: hidden;
12
+ }
13
+
14
+ .featherlight {
15
+ display: none;
16
+
17
+ /* dimensions: spanning the background from edge to edge */
18
+ position:fixed;
19
+ top: 0; right: 0; bottom: 0; left: 0;
20
+ z-index: 2147483647; /* z-index needs to be >= elements on the site. */
21
+
22
+ /* position: centering content */
23
+ text-align: center;
24
+
25
+ /* insures that the ::before pseudo element doesn't force wrap with fixed width content; */
26
+ white-space: nowrap;
27
+
28
+ /* styling */
29
+ cursor: pointer;
30
+ background: #333;
31
+ /* IE8 "hack" for nested featherlights */
32
+ background: rgba(0, 0, 0, 0);
33
+ }
34
+
35
+ /* support for nested featherlights. Does not work in IE8 (use JS to fix) */
36
+ .featherlight:last-of-type {
37
+ background: rgba(0, 0, 0, 0.8);
38
+ }
39
+
40
+ .featherlight:before {
41
+ /* position: trick to center content vertically */
42
+ content: '';
43
+ display: inline-block;
44
+ height: 100%;
45
+ vertical-align: middle;
46
+ }
47
+
48
+ .featherlight .featherlight-content {
49
+ /* make content container for positioned elements (close button) */
50
+ position: relative;
51
+
52
+ /* position: centering vertical and horizontal */
53
+ text-align: left;
54
+ vertical-align: middle;
55
+ display: inline-block;
56
+
57
+ /* dimensions: cut off images */
58
+ overflow: auto;
59
+ padding: 25px 25px 0;
60
+ border-bottom: 25px solid transparent;
61
+
62
+ /* dimensions: handling large content */
63
+ margin-left: 5%;
64
+ margin-right: 5%;
65
+ max-height: 95%;
66
+
67
+ /* styling */
68
+ background: #fff;
69
+ cursor: auto;
70
+
71
+ /* reset white-space wrapping */
72
+ white-space: normal;
73
+ }
74
+
75
+ /* contains the content */
76
+ .featherlight .featherlight-inner {
77
+ /* make sure its visible */
78
+ display: block;
79
+ }
80
+
81
+ /* don't show these though */
82
+ .featherlight script.featherlight-inner,
83
+ .featherlight link.featherlight-inner,
84
+ .featherlight style.featherlight-inner {
85
+ display: none;
86
+ }
87
+
88
+ .featherlight .featherlight-close-icon {
89
+ /* position: centering vertical and horizontal */
90
+ position: absolute;
91
+ z-index: 9999;
92
+ top: 0;
93
+ right: 0;
94
+
95
+ /* dimensions: 25px x 25px */
96
+ line-height: 25px;
97
+ width: 25px;
98
+
99
+ /* styling */
100
+ cursor: pointer;
101
+ text-align: center;
102
+ font-family: Arial, sans-serif;
103
+ background: #fff; /* Set the background in case it overlaps the content */
104
+ background: rgba(255, 255, 255, 0.3);
105
+ color: #000;
106
+ border: none;
107
+ padding: 0;
108
+ }
109
+
110
+ /* See http://stackoverflow.com/questions/16077341/how-to-reset-all-default-styles-of-the-html5-button-element */
111
+ .featherlight .featherlight-close-icon::-moz-focus-inner {
112
+ border: 0;
113
+ padding: 0;
114
+ }
115
+
116
+ .featherlight .featherlight-image {
117
+ /* styling */
118
+ width: 100%;
119
+ }
120
+
121
+
122
+ .featherlight-iframe .featherlight-content {
123
+ /* removed the border for image croping since iframe is edge to edge */
124
+ border-bottom: 0;
125
+ padding: 0;
126
+ -webkit-overflow-scrolling: touch;
127
+ }
128
+
129
+ .featherlight iframe {
130
+ /* styling */
131
+ border: none;
132
+ }
133
+
134
+ .featherlight * { /* See https://github.com/noelboss/featherlight/issues/42 */
135
+ -webkit-box-sizing: border-box;
136
+ -moz-box-sizing: border-box;
137
+ box-sizing: border-box;
138
+ }
139
+
140
+ /* handling phones and small screens */
141
+ @media only screen and (max-width: 1024px) {
142
+ .featherlight .featherlight-content {
143
+ /* dimensions: maximize lightbox with for small screens */
144
+ margin-left: 0;
145
+ margin-right: 0;
146
+ max-height: 98%;
147
+
148
+ padding: 10px 10px 0;
149
+ border-bottom: 10px solid transparent;
150
+ }
151
+ }
152
+
153
+ /* hide non featherlight items when printing */
154
+ @media print {
155
+ html.with-featherlight > * > :not(.featherlight) {
156
+ display: none;
157
+ }
158
+ }
assets/featherlight/featherlight.gallery.css CHANGED
@@ -1,122 +1,122 @@
1
- /**
2
- * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
3
- * Version 1.7.12 - http://noelboss.github.io/featherlight/
4
- *
5
- * Copyright 2017, Noël Raoul Bossart (http://www.noelboss.com)
6
- * MIT Licensed.
7
- **/
8
- @media all {
9
- .featherlight-next,
10
- .featherlight-previous {
11
- display: block;
12
- position: absolute;
13
- top: 25px;
14
- right: 25px;
15
- bottom: 0;
16
- left: 80%;
17
- cursor: pointer;
18
- /* preventing text selection */
19
- -webkit-touch-callout: none;
20
- -webkit-user-select: none;
21
- -khtml-user-select: none;
22
- -moz-user-select: none;
23
- -ms-user-select: none;
24
- user-select: none;
25
- /* IE9 hack, otherwise navigation doesn't appear */
26
- background: rgba(0,0,0,0);
27
- }
28
-
29
- .featherlight-previous {
30
- left: 25px;
31
- right: 80%;
32
- }
33
-
34
- .featherlight-next:hover,
35
- .featherlight-previous:hover {
36
- background: rgba(255,255,255,0.25);
37
- }
38
-
39
-
40
- .featherlight-next span,
41
- .featherlight-previous span {
42
- display: none;
43
- position: absolute;
44
-
45
- top: 50%;
46
- left: 5%;
47
- width: 82%;
48
-
49
- /* center horizontally */
50
- text-align: center;
51
-
52
- font-size: 80px;
53
- line-height: 80px;
54
-
55
- /* center vertically */
56
- margin-top: -40px;
57
-
58
- text-shadow: 0px 0px 5px #fff;
59
- color: #fff;
60
- font-style: normal;
61
- font-weight: normal;
62
- }
63
- .featherlight-next span {
64
- right: 5%;
65
- left: auto;
66
- }
67
-
68
-
69
- .featherlight-next:hover span,
70
- .featherlight-previous:hover span {
71
- display: inline-block;
72
- }
73
-
74
- .featherlight-swipe-aware .featherlight-next,
75
- .featherlight-swipe-aware .featherlight-previous {
76
- display: none;
77
- }
78
-
79
- /* Hide navigation while loading */
80
- .featherlight-loading .featherlight-previous, .featherlight-loading .featherlight-next {
81
- display:none;
82
- }
83
-
84
- /* Hide navigation in case of single image */
85
- .featherlight-first-slide.featherlight-last-slide .featherlight-previous,
86
- .featherlight-first-slide.featherlight-last-slide .featherlight-next {
87
- display:none;
88
- }
89
- }
90
-
91
- /* Always display arrows on touch devices */
92
- @media only screen and (max-device-width: 1024px){
93
- .featherlight-next:hover,
94
- .featherlight-previous:hover {
95
- background: none;
96
- }
97
- .featherlight-next span,
98
- .featherlight-previous span {
99
- display: block;
100
- }
101
- }
102
-
103
- /* handling phones and small screens */
104
- @media only screen and (max-width: 1024px) {
105
- .featherlight-next,
106
- .featherlight-previous {
107
- top: 10px;
108
- right: 10px;
109
- left: 85%;
110
- }
111
-
112
- .featherlight-previous {
113
- left: 10px;
114
- right: 85%;
115
- }
116
-
117
- .featherlight-next span,
118
- .featherlight-previous span {
119
- margin-top: -30px;
120
- font-size: 40px;
121
- }
122
- }
1
+ /**
2
+ * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
3
+ * Version 1.7.13 - http://noelboss.github.io/featherlight/
4
+ *
5
+ * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
6
+ * MIT Licensed.
7
+ **/
8
+
9
+ .featherlight-next,
10
+ .featherlight-previous {
11
+ display: block;
12
+ position: absolute;
13
+ top: 25px;
14
+ right: 25px;
15
+ bottom: 0;
16
+ left: 80%;
17
+ cursor: pointer;
18
+ /* preventing text selection */
19
+ -webkit-touch-callout: none;
20
+ -webkit-user-select: none;
21
+ -khtml-user-select: none;
22
+ -moz-user-select: none;
23
+ -ms-user-select: none;
24
+ user-select: none;
25
+ /* IE9 hack, otherwise navigation doesn't appear */
26
+ background: rgba(0,0,0,0);
27
+ }
28
+
29
+ .featherlight-previous {
30
+ left: 25px;
31
+ right: 80%;
32
+ }
33
+
34
+ .featherlight-next:hover,
35
+ .featherlight-previous:hover {
36
+ background: rgba(255,255,255,0.25);
37
+ }
38
+
39
+
40
+ .featherlight-next span,
41
+ .featherlight-previous span {
42
+ display: none;
43
+ position: absolute;
44
+
45
+ top: 50%;
46
+ left: 5%;
47
+ width: 82%;
48
+
49
+ /* center horizontally */
50
+ text-align: center;
51
+
52
+ font-size: 80px;
53
+ line-height: 80px;
54
+
55
+ /* center vertically */
56
+ margin-top: -40px;
57
+
58
+ text-shadow: 0px 0px 5px #fff;
59
+ color: #fff;
60
+ font-style: normal;
61
+ font-weight: normal;
62
+ }
63
+ .featherlight-next span {
64
+ right: 5%;
65
+ left: auto;
66
+ }
67
+
68
+
69
+ .featherlight-next:hover span,
70
+ .featherlight-previous:hover span {
71
+ display: inline-block;
72
+ }
73
+
74
+ .featherlight-swipe-aware .featherlight-next,
75
+ .featherlight-swipe-aware .featherlight-previous {
76
+ display: none;
77
+ }
78
+
79
+ /* Hide navigation while loading */
80
+ .featherlight-loading .featherlight-previous, .featherlight-loading .featherlight-next {
81
+ display:none;
82
+ }
83
+
84
+ /* Hide navigation in case of single image */
85
+ .featherlight-first-slide.featherlight-last-slide .featherlight-previous,
86
+ .featherlight-first-slide.featherlight-last-slide .featherlight-next {
87
+ display:none;
88
+ }
89
+
90
+
91
+ /* Always display arrows on touch devices */
92
+ @media only screen and (max-device-width: 1024px){
93
+ .featherlight-next:hover,
94
+ .featherlight-previous:hover {
95
+ background: none;
96
+ }
97
+ .featherlight-next span,
98
+ .featherlight-previous span {
99
+ display: block;
100
+ }
101
+ }
102
+
103
+ /* handling phones and small screens */
104
+ @media only screen and (max-width: 1024px) {
105
+ .featherlight-next,
106
+ .featherlight-previous {
107
+ top: 10px;
108
+ right: 10px;
109
+ left: 85%;
110
+ }
111
+
112
+ .featherlight-previous {
113
+ left: 10px;
114
+ right: 85%;
115
+ }
116
+
117
+ .featherlight-next span,
118
+ .featherlight-previous span {
119
+ margin-top: -30px;
120
+ font-size: 40px;
121
+ }
122
+ }
assets/featherlight/featherlight.gallery.js CHANGED
@@ -1,169 +1,169 @@
1
- /**
2
- * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
3
- * Version 1.7.12 - http://noelboss.github.io/featherlight/
4
- *
5
- * Copyright 2017, Noël Raoul Bossart (http://www.noelboss.com)
6
- * MIT Licensed.
7
- **/
8
- (function($) {
9
- "use strict";
10
-
11
- var warn = function(m) {
12
- if(window.console && window.console.warn) {
13
- window.console.warn('FeatherlightGallery: ' + m);
14
- }
15
- };
16
-
17
- if('undefined' === typeof $) {
18
- return warn('Too much lightness, Featherlight needs jQuery.');
19
- } else if(!$.featherlight) {
20
- return warn('Load the featherlight plugin before the gallery plugin');
21
- }
22
-
23
- var isTouchAware = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
24
- jQueryConstructor = $.event && $.event.special.swipeleft && $,
25
- hammerConstructor = window.Hammer && function($el){
26
- var mc = new window.Hammer.Manager($el[0]);
27
- mc.add(new window.Hammer.Swipe());
28
- return mc;
29
- },
30
- swipeAwareConstructor = isTouchAware && (jQueryConstructor || hammerConstructor);
31
- if(isTouchAware && !swipeAwareConstructor) {
32
- warn('No compatible swipe library detected; one must be included before featherlightGallery for swipe motions to navigate the galleries.');
33
- }
34
-
35
- var callbackChain = {
36
- afterClose: function(_super, event) {
37
- var self = this;
38
- self.$instance.off('next.'+self.namespace+' previous.'+self.namespace);
39
- if (self._swiper) {
40
- self._swiper
41
- .off('swipeleft', self._swipeleft) /* See http://stackoverflow.com/questions/17367198/hammer-js-cant-remove-event-listener */
42
- .off('swiperight', self._swiperight);
43
- self._swiper = null;
44
- }
45
- return _super(event);
46
- },
47
- beforeOpen: function(_super, event){
48
- var self = this;
49
-
50
- self.$instance.on('next.'+self.namespace+' previous.'+self.namespace, function(event){
51
- var offset = event.type === 'next' ? +1 : -1;
52
- self.navigateTo(self.currentNavigation() + offset);
53
- });
54
-
55
- if (swipeAwareConstructor) {
56
- self._swiper = swipeAwareConstructor(self.$instance)
57
- .on('swipeleft', self._swipeleft = function() { self.$instance.trigger('next'); })
58
- .on('swiperight', self._swiperight = function() { self.$instance.trigger('previous'); });
59
-
60
- self.$instance
61
- .addClass(this.namespace+'-swipe-aware', swipeAwareConstructor);
62
- }
63
-
64
- self.$instance.find('.'+self.namespace+'-content')
65
- .append(self.createNavigation('previous'))
66
- .append(self.createNavigation('next'));
67
-
68
- return _super(event);
69
- },
70
- beforeContent: function(_super, event) {
71
- var index = this.currentNavigation();
72
- var len = this.slides().length;
73
- this.$instance
74
- .toggleClass(this.namespace+'-first-slide', index === 0)
75
- .toggleClass(this.namespace+'-last-slide', index === len - 1);
76
- return _super(event);
77
- },
78
- onKeyUp: function(_super, event){
79
- var dir = {
80
- 37: 'previous', /* Left arrow */
81
- 39: 'next' /* Rigth arrow */
82
- }[event.keyCode];
83
- if(dir) {
84
- this.$instance.trigger(dir);
85
- return false;
86
- } else {
87
- return _super(event);
88
- }
89
- }
90
- };
91
-
92
- function FeatherlightGallery($source, config) {
93
- if(this instanceof FeatherlightGallery) { /* called with new */
94
- $.featherlight.apply(this, arguments);
95
- this.chainCallbacks(callbackChain);
96
- } else {
97
- var flg = new FeatherlightGallery($.extend({$source: $source, $currentTarget: $source.first()}, config));
98
- flg.open();
99
- return flg;
100
- }
101
- }
102
-
103
- $.featherlight.extend(FeatherlightGallery, {
104
- autoBind: '[data-featherlight-gallery]'
105
- });
106
-
107
- $.extend(FeatherlightGallery.prototype, {
108
- /** Additional settings for Gallery **/
109
- previousIcon: '◀', /* Code that is used as previous icon */
110
- nextIcon: '▶', /* Code that is used as next icon */
111
- galleryFadeIn: 100, /* fadeIn speed when image is loaded */
112
- galleryFadeOut: 300, /* fadeOut speed before image is loaded */
113
-
114
- slides: function() {
115
- if (this.filter) {
116
- return this.$source.find(this.filter);
117
- }
118
- return this.$source;
119
- },
120
-
121
- images: function() {
122
- warn('images is deprecated, please use slides instead');
123
- return this.slides();
124
- },
125
-
126
- currentNavigation: function() {
127
- return this.slides().index(this.$currentTarget);
128
- },
129
-
130
- navigateTo: function(index) {
131
- var self = this,
132
- source = self.slides(),
133
- len = source.length,
134
- $inner = self.$instance.find('.' + self.namespace + '-inner');
135
- index = ((index % len) + len) % len; /* pin index to [0, len[ */
136
-
137
- self.$currentTarget = source.eq(index);
138
- self.beforeContent();
139
- return $.when(
140
- self.getContent(),
141
- $inner.fadeTo(self.galleryFadeOut,0.2)
142
- ).always(function($newContent) {
143
- self.setContent($newContent);
144
- self.afterContent();
145
- $newContent.fadeTo(self.galleryFadeIn,1);
146
- });
147
- },
148
-
149
- createNavigation: function(target) {
150
- var self = this;
151
- return $('<span title="'+target+'" class="'+this.namespace+'-'+target+'"><span>'+this[target+'Icon']+'</span></span>').click(function(evt){
152
- $(this).trigger(target+'.'+self.namespace);
153
- evt.preventDefault();
154
- });
155
- }
156
- });
157
-
158
- $.featherlightGallery = FeatherlightGallery;
159
-
160
- /* extend jQuery with selector featherlight method $(elm).featherlight(config, elm); */
161
- $.fn.featherlightGallery = function(config) {
162
- FeatherlightGallery.attach(this, config);
163
- return this;
164
- };
165
-
166
- /* bind featherlight on ready if config autoBind is set */
167
- $(document).ready(function(){ FeatherlightGallery._onReady(); });
168
-
169
- }(jQuery));
1
+ /**
2
+ * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
3
+ * Version 1.7.13 - http://noelboss.github.io/featherlight/
4
+ *
5
+ * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
6
+ * MIT Licensed.
7
+ **/
8
+ (function($) {
9
+ "use strict";
10
+
11
+ var warn = function(m) {
12
+ if(window.console && window.console.warn) {
13
+ window.console.warn('FeatherlightGallery: ' + m);
14
+ }
15
+ };
16
+
17
+ if('undefined' === typeof $) {
18
+ return warn('Too much lightness, Featherlight needs jQuery.');
19
+ } else if(!$.featherlight) {
20
+ return warn('Load the featherlight plugin before the gallery plugin');
21
+ }
22
+
23
+ var isTouchAware = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
24
+ jQueryConstructor = $.event && $.event.special.swipeleft && $,
25
+ hammerConstructor = window.Hammer && function($el){
26
+ var mc = new window.Hammer.Manager($el[0]);
27
+ mc.add(new window.Hammer.Swipe());
28
+ return mc;
29
+ },
30
+ swipeAwareConstructor = isTouchAware && (jQueryConstructor || hammerConstructor);
31
+ if(isTouchAware && !swipeAwareConstructor) {
32
+ warn('No compatible swipe library detected; one must be included before featherlightGallery for swipe motions to navigate the galleries.');
33
+ }
34
+
35
+ var callbackChain = {
36
+ afterClose: function(_super, event) {
37
+ var self = this;
38
+ self.$instance.off('next.'+self.namespace+' previous.'+self.namespace);
39
+ if (self._swiper) {
40
+ self._swiper
41
+ .off('swipeleft', self._swipeleft) /* See http://stackoverflow.com/questions/17367198/hammer-js-cant-remove-event-listener */
42
+ .off('swiperight', self._swiperight);
43
+ self._swiper = null;
44
+ }
45
+ return _super(event);
46
+ },
47
+ beforeOpen: function(_super, event){
48
+ var self = this;
49
+
50
+ self.$instance.on('next.'+self.namespace+' previous.'+self.namespace, function(event){
51
+ var offset = event.type === 'next' ? +1 : -1;
52
+ self.navigateTo(self.currentNavigation() + offset);
53
+ });
54
+
55
+ if (swipeAwareConstructor) {
56
+ self._swiper = swipeAwareConstructor(self.$instance)
57
+ .on('swipeleft', self._swipeleft = function() { self.$instance.trigger('next'); })
58
+ .on('swiperight', self._swiperight = function() { self.$instance.trigger('previous'); });
59
+
60
+ self.$instance
61
+ .addClass(this.namespace+'-swipe-aware', swipeAwareConstructor);
62
+ }
63
+
64
+ self.$instance.find('.'+self.namespace+'-content')
65
+ .append(self.createNavigation('previous'))
66
+ .append(self.createNavigation('next'));
67
+
68
+ return _super(event);
69
+ },
70
+ beforeContent: function(_super, event) {
71
+ var index = this.currentNavigation();
72
+ var len = this.slides().length;
73
+ this.$instance
74
+ .toggleClass(this.namespace+'-first-slide', index === 0)
75
+ .toggleClass(this.namespace+'-last-slide', index === len - 1);
76
+ return _super(event);
77
+ },
78
+ onKeyUp: function(_super, event){
79
+ var dir = {
80
+ 37: 'previous', /* Left arrow */
81
+ 39: 'next' /* Rigth arrow */
82
+ }[event.keyCode];
83
+ if(dir) {
84
+ this.$instance.trigger(dir);
85
+ return false;
86
+ } else {
87
+ return _super(event);
88
+ }
89
+ }
90
+ };
91
+
92
+ function FeatherlightGallery($source, config) {
93
+ if(this instanceof FeatherlightGallery) { /* called with new */
94
+ $.featherlight.apply(this, arguments);
95
+ this.chainCallbacks(callbackChain);
96
+ } else {
97
+ var flg = new FeatherlightGallery($.extend({$source: $source, $currentTarget: $source.first()}, config));
98
+ flg.open();
99
+ return flg;
100
+ }
101
+ }
102
+
103
+ $.featherlight.extend(FeatherlightGallery, {
104
+ autoBind: '[data-featherlight-gallery]'
105
+ });
106
+
107
+ $.extend(FeatherlightGallery.prototype, {
108
+ /** Additional settings for Gallery **/
109
+ previousIcon: '&#9664;', /* Code that is used as previous icon */
110
+ nextIcon: '&#9654;', /* Code that is used as next icon */
111
+ galleryFadeIn: 100, /* fadeIn speed when image is loaded */
112
+ galleryFadeOut: 300, /* fadeOut speed before image is loaded */
113
+
114
+ slides: function() {
115
+ if (this.filter) {
116
+ return this.$source.find(this.filter);
117
+ }
118
+ return this.$source;
119
+ },
120
+
121
+ images: function() {
122
+ warn('images is deprecated, please use slides instead');
123
+ return this.slides();
124
+ },
125
+
126
+ currentNavigation: function() {
127
+ return this.slides().index(this.$currentTarget);
128
+ },
129
+
130
+ navigateTo: function(index) {
131
+ var self = this,
132
+ source = self.slides(),
133
+ len = source.length,
134
+ $inner = self.$instance.find('.' + self.namespace + '-inner');
135
+ index = ((index % len) + len) % len; /* pin index to [0, len[ */
136
+
137
+ self.$currentTarget = source.eq(index);
138
+ self.beforeContent();
139
+ return $.when(
140
+ self.getContent(),
141
+ $inner.fadeTo(self.galleryFadeOut,0.2)
142
+ ).always(function($newContent) {
143
+ self.setContent($newContent);
144
+ self.afterContent();
145
+ $newContent.fadeTo(self.galleryFadeIn,1);
146
+ });
147
+ },
148
+
149
+ createNavigation: function(target) {
150
+ var self = this;
151
+ return $('<span title="'+target+'" class="'+this.namespace+'-'+target+'"><span>'+this[target+'Icon']+'</span></span>').click(function(evt){
152
+ $(this).trigger(target+'.'+self.namespace);
153
+ evt.preventDefault();
154
+ });
155
+ }
156
+ });
157
+
158
+ $.featherlightGallery = FeatherlightGallery;
159
+
160
+ /* extend jQuery with selector featherlight method $(elm).featherlight(config, elm); */
161
+ $.fn.featherlightGallery = function(config) {
162
+ FeatherlightGallery.attach(this, config);
163
+ return this;
164
+ };
165
+
166
+ /* bind featherlight on ready if config autoBind is set */
167
+ $(document).ready(function(){ FeatherlightGallery._onReady(); });
168
+
169
+ }(jQuery));
assets/featherlight/featherlight.gallery.min.css CHANGED
@@ -1,8 +1,8 @@
1
- /**
2
- * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
3
- * Version 1.7.12 - http://noelboss.github.io/featherlight/
4
- *
5
- * Copyright 2017, Noël Raoul Bossart (http://www.noelboss.com)
6
- * MIT Licensed.
7
- **/
8
- @media all{.featherlight-next,.featherlight-previous{display:block;position:absolute;top:25px;right:25px;bottom:0;left:80%;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:rgba(0,0,0,0)}.featherlight-previous{left:25px;right:80%}.featherlight-next:hover,.featherlight-previous:hover{background:rgba(255,255,255,.25)}.featherlight-next span,.featherlight-previous span{display:none;position:absolute;top:50%;left:5%;width:82%;text-align:center;font-size:80px;line-height:80px;margin-top:-40px;text-shadow:0 0 5px #fff;color:#fff;font-style:normal;font-weight:400}.featherlight-next span{right:5%;left:auto}.featherlight-next:hover span,.featherlight-previous:hover span{display:inline-block}.featherlight-first-slide.featherlight-last-slide .featherlight-next,.featherlight-first-slide.featherlight-last-slide .featherlight-previous,.featherlight-loading .featherlight-next,.featherlight-loading .featherlight-previous,.featherlight-swipe-aware .featherlight-next,.featherlight-swipe-aware .featherlight-previous{display:none}}@media only screen and (max-device-width:1024px){.featherlight-next:hover,.featherlight-previous:hover{background:0 0}.featherlight-next span,.featherlight-previous span{display:block}}@media only screen and (max-width:1024px){.featherlight-next,.featherlight-previous{top:10px;right:10px;left:85%}.featherlight-previous{left:10px;right:85%}.featherlight-next span,.featherlight-previous span{margin-top:-30px;font-size:40px}}
1
+ /**
2
+ * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
3
+ * Version 1.7.13 - http://noelboss.github.io/featherlight/
4
+ *
5
+ * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
6
+ * MIT Licensed.
7
+ **/
8
+ .featherlight-next,.featherlight-previous{display:block;position:absolute;top:25px;right:25px;bottom:0;left:80%;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:rgba(0,0,0,0)}.featherlight-previous{left:25px;right:80%}.featherlight-next:hover,.featherlight-previous:hover{background:rgba(255,255,255,.25)}.featherlight-next span,.featherlight-previous span{display:none;position:absolute;top:50%;left:5%;width:82%;text-align:center;font-size:80px;line-height:80px;margin-top:-40px;text-shadow:0 0 5px #fff;color:#fff;font-style:normal;font-weight:400}.featherlight-next span{right:5%;left:auto}.featherlight-next:hover span,.featherlight-previous:hover span{display:inline-block}.featherlight-first-slide.featherlight-last-slide .featherlight-next,.featherlight-first-slide.featherlight-last-slide .featherlight-previous,.featherlight-loading .featherlight-next,.featherlight-loading .featherlight-previous,.featherlight-swipe-aware .featherlight-next,.featherlight-swipe-aware .featherlight-previous{display:none}@media only screen and (max-device-width:1024px){.featherlight-next:hover,.featherlight-previous:hover{background:0 0}.featherlight-next span,.featherlight-previous span{display:block}}@media only screen and (max-width:1024px){.featherlight-next,.featherlight-previous{top:10px;right:10px;left:85%}.featherlight-previous{left:10px;right:85%}.featherlight-next span,.featherlight-previous span{margin-top:-30px;font-size:40px}}
assets/featherlight/featherlight.gallery.min.js CHANGED
@@ -1,7 +1,7 @@
1
- /**
2
- * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
3
- * Version 1.7.12 - http://noelboss.github.io/featherlight/
4
- *
5
- * Copyright 2017, Noël Raoul Bossart (http://www.noelboss.com)
6
- * MIT Licensed.
7
**/!function(a){"use strict";function b(c,d){if(!(this instanceof b)){var e=new b(a.extend({$source:c,$currentTarget:c.first()},d));return e.open(),e}a.featherlight.apply(this,arguments),this.chainCallbacks(h)}var c=function(a){window.console&&window.console.warn&&window.console.warn("FeatherlightGallery: "+a)};if("undefined"==typeof a)return c("Too much lightness, Featherlight needs jQuery.");if(!a.featherlight)return c("Load the featherlight plugin before the gallery plugin");var d="ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch,e=a.event&&a.event.special.swipeleft&&a,f=window.Hammer&&function(a){var b=new window.Hammer.Manager(a[0]);return b.add(new window.Hammer.Swipe),b},g=d&&(e||f);d&&!g&&c("No compatible swipe library detected; one must be included before featherlightGallery for swipe motions to navigate the galleries.");var h={afterClose:function(a,b){var c=this;return c.$instance.off("next."+c.namespace+" previous."+c.namespace),c._swiper&&(c._swiper.off("swipeleft",c._swipeleft).off("swiperight",c._swiperight),c._swiper=null),a(b)},beforeOpen:function(a,b){var c=this;return c.$instance.on("next."+c.namespace+" previous."+c.namespace,function(a){var b="next"===a.type?1:-1;c.navigateTo(c.currentNavigation()+b)}),g&&(c._swiper=g(c.$instance).on("swipeleft",c._swipeleft=function(){c.$instance.trigger("next")}).on("swiperight",c._swiperight=function(){c.$instance.trigger("previous")}),c.$instance.addClass(this.namespace+"-swipe-aware",g)),c.$instance.find("."+c.namespace+"-content").append(c.createNavigation("previous")).append(c.createNavigation("next")),a(b)},beforeContent:function(a,b){var c=this.currentNavigation(),d=this.slides().length;return this.$instance.toggleClass(this.namespace+"-first-slide",0===c).toggleClass(this.namespace+"-last-slide",c===d-1),a(b)},onKeyUp:function(a,b){var c={37:"previous",39:"next"}[b.keyCode];return c?(this.$instance.trigger(c),!1):a(b)}};a.featherlight.extend(b,{autoBind:"[data-featherlight-gallery]"}),a.extend(b.prototype,{previousIcon:"&#9664;",nextIcon:"&#9654;",galleryFadeIn:100,galleryFadeOut:300,slides:function(){return this.filter?this.$source.find(this.filter):this.$source},images:function(){return c("images is deprecated, please use slides instead"),this.slides()},currentNavigation:function(){return this.slides().index(this.$currentTarget)},navigateTo:function(b){var c=this,d=c.slides(),e=d.length,f=c.$instance.find("."+c.namespace+"-inner");return b=(b%e+e)%e,c.$currentTarget=d.eq(b),c.beforeContent(),a.when(c.getContent(),f.fadeTo(c.galleryFadeOut,.2)).always(function(a){c.setContent(a),c.afterContent(),a.fadeTo(c.galleryFadeIn,1)})},createNavigation:function(b){var c=this;return a('<span title="'+b+'" class="'+this.namespace+"-"+b+'"><span>'+this[b+"Icon"]+"</span></span>").click(function(d){a(this).trigger(b+"."+c.namespace),d.preventDefault()})}}),a.featherlightGallery=b,a.fn.featherlightGallery=function(a){return b.attach(this,a),this},a(document).ready(function(){b._onReady()})}(jQuery);
1
+ /**
2
+ * Featherlight Gallery – an extension for the ultra slim jQuery lightbox
3
+ * Version 1.7.13 - http://noelboss.github.io/featherlight/
4
+ *
5
+ * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
6
+ * MIT Licensed.
7
**/!function(a){"use strict";function b(c,d){if(!(this instanceof b)){var e=new b(a.extend({$source:c,$currentTarget:c.first()},d));return e.open(),e}a.featherlight.apply(this,arguments),this.chainCallbacks(h)}var c=function(a){window.console&&window.console.warn&&window.console.warn("FeatherlightGallery: "+a)};if("undefined"==typeof a)return c("Too much lightness, Featherlight needs jQuery.");if(!a.featherlight)return c("Load the featherlight plugin before the gallery plugin");var d="ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch,e=a.event&&a.event.special.swipeleft&&a,f=window.Hammer&&function(a){var b=new window.Hammer.Manager(a[0]);return b.add(new window.Hammer.Swipe),b},g=d&&(e||f);d&&!g&&c("No compatible swipe library detected; one must be included before featherlightGallery for swipe motions to navigate the galleries.");var h={afterClose:function(a,b){var c=this;return c.$instance.off("next."+c.namespace+" previous."+c.namespace),c._swiper&&(c._swiper.off("swipeleft",c._swipeleft).off("swiperight",c._swiperight),c._swiper=null),a(b)},beforeOpen:function(a,b){var c=this;return c.$instance.on("next."+c.namespace+" previous."+c.namespace,function(a){var b="next"===a.type?1:-1;c.navigateTo(c.currentNavigation()+b)}),g&&(c._swiper=g(c.$instance).on("swipeleft",c._swipeleft=function(){c.$instance.trigger("next")}).on("swiperight",c._swiperight=function(){c.$instance.trigger("previous")}),c.$instance.addClass(this.namespace+"-swipe-aware",g)),c.$instance.find("."+c.namespace+"-content").append(c.createNavigation("previous")).append(c.createNavigation("next")),a(b)},beforeContent:function(a,b){var c=this.currentNavigation(),d=this.slides().length;return this.$instance.toggleClass(this.namespace+"-first-slide",0===c).toggleClass(this.namespace+"-last-slide",c===d-1),a(b)},onKeyUp:function(a,b){var c={37:"previous",39:"next"}[b.keyCode];return c?(this.$instance.trigger(c),!1):a(b)}};a.featherlight.extend(b,{autoBind:"[data-featherlight-gallery]"}),a.extend(b.prototype,{previousIcon:"&#9664;",nextIcon:"&#9654;",galleryFadeIn:100,galleryFadeOut:300,slides:function(){return this.filter?this.$source.find(this.filter):this.$source},images:function(){return c("images is deprecated, please use slides instead"),this.slides()},currentNavigation:function(){return this.slides().index(this.$currentTarget)},navigateTo:function(b){var c=this,d=c.slides(),e=d.length,f=c.$instance.find("."+c.namespace+"-inner");return b=(b%e+e)%e,c.$currentTarget=d.eq(b),c.beforeContent(),a.when(c.getContent(),f.fadeTo(c.galleryFadeOut,.2)).always(function(a){c.setContent(a),c.afterContent(),a.fadeTo(c.galleryFadeIn,1)})},createNavigation:function(b){var c=this;return a('<span title="'+b+'" class="'+this.namespace+"-"+b+'"><span>'+this[b+"Icon"]+"</span></span>").click(function(d){a(this).trigger(b+"."+c.namespace),d.preventDefault()})}}),a.featherlightGallery=b,a.fn.featherlightGallery=function(a){return b.attach(this,a),this},a(document).ready(function(){b._onReady()})}(jQuery);
assets/featherlight/featherlight.js CHANGED
@@ -1,631 +1,641 @@
1
- /**
2
- * Featherlight - ultra slim jQuery lightbox
3
- * Version 1.7.12 - http://noelboss.github.io/featherlight/
4
- *
5
- * Copyright 2017, Noël Raoul Bossart (http://www.noelboss.com)
6
- * MIT Licensed.
7
- **/
8
- (function($) {
9
- "use strict";
10
-
11
- if('undefined' === typeof $) {
12
- if('console' in window){ window.console.info('Too much lightness, Featherlight needs jQuery.'); }
13
- return;
14
- }
15
- if($.fn.jquery.match(/-ajax/)) {
16
- if('console' in window){ window.console.info('Featherlight needs regular jQuery, not the slim version.'); }
17
- return;
18
- }
19
- /* Featherlight is exported as $.featherlight.
20
- It is a function used to open a featherlight lightbox.
21
-
22
- [tech]
23
- Featherlight uses prototype inheritance.
24
- Each opened lightbox will have a corresponding object.
25
- That object may have some attributes that override the
26
- prototype's.
27
- Extensions created with Featherlight.extend will have their
28
- own prototype that inherits from Featherlight's prototype,
29
- thus attributes can be overriden either at the object level,
30
- or at the extension level.
31
- To create callbacks that chain themselves instead of overriding,
32
- use chainCallbacks.
33
- For those familiar with CoffeeScript, this correspond to
34
- Featherlight being a class and the Gallery being a class
35
- extending Featherlight.
36
- The chainCallbacks is used since we don't have access to
37
- CoffeeScript's `super`.
38
- */
39
-
40
- function Featherlight($content, config) {
41
- if(this instanceof Featherlight) { /* called with new */
42
- this.id = Featherlight.id++;
43
- this.setup($content, config);
44
- this.chainCallbacks(Featherlight._callbackChain);
45
- } else {
46
- var fl = new Featherlight($content, config);
47
- fl.open();
48
- return fl;
49
- }
50
- }
51
-
52
- var opened = [],
53
- pruneOpened = function(remove) {
54
- opened = $.grep(opened, function(fl) {
55
- return fl !== remove && fl.$instance.closest('body').length > 0;
56
- } );
57
- return opened;
58
- };
59
-
60
- // Removes keys of `set` from `obj` and returns the removed key/values.
61
- function slice(obj, set) {
62
- var r = {};
63
- for (var key in obj) {
64
- if (key in set) {
65
- r[key] = obj[key];
66
- delete obj[key];
67
- }
68
- }
69
- return r;
70
- }
71
-
72
- // NOTE: List of available [iframe attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe).
73
- var iFrameAttributeSet = {
74
- allowfullscreen: 1, frameborder: 1, height: 1, longdesc: 1, marginheight: 1, marginwidth: 1,
75
- name: 1, referrerpolicy: 1, scrolling: 1, sandbox: 1, src: 1, srcdoc: 1, width: 1
76
- };
77
-
78
- // Converts camelCased attributes to dasherized versions for given prefix:
79
- // parseAttrs({hello: 1, hellFrozeOver: 2}, 'hell') => {froze-over: 2}
80
- function parseAttrs(obj, prefix) {
81
- var attrs = {},
82
- regex = new RegExp('^' + prefix + '([A-Z])(.*)');
83
- for (var key in obj) {
84
- var match = key.match(regex);
85
- if (match) {
86
- var dasherized = (match[1] + match[2].replace(/([A-Z])/g, '-$1')).toLowerCase();
87
- attrs[dasherized] = obj[key];
88
- }
89
- }
90
- return attrs;
91
- }
92
-
93
- /* document wide key handler */
94
- var eventMap = { keyup: 'onKeyUp', resize: 'onResize' };
95
-
96
- var globalEventHandler = function(event) {
97
- $.each(Featherlight.opened().reverse(), function() {
98
- if (!event.isDefaultPrevented()) {
99
- if (false === this[eventMap[event.type]](event)) {
100
- event.preventDefault(); event.stopPropagation(); return false;
101
- }
102
- }
103
- });
104
- };
105
-
106
- var toggleGlobalEvents = function(set) {
107
- if(set !== Featherlight._globalHandlerInstalled) {
108
- Featherlight._globalHandlerInstalled = set;
109
- var events = $.map(eventMap, function(_, name) { return name+'.'+Featherlight.prototype.namespace; } ).join(' ');
110
- $(window)[set ? 'on' : 'off'](events, globalEventHandler);
111
- }
112
- };
113
-
114
- Featherlight.prototype = {
115
- constructor: Featherlight,
116
- /*** defaults ***/
117
- /* extend featherlight with defaults and methods */
118
- namespace: 'featherlight', /* Name of the events and css class prefix */
119
- targetAttr: 'data-featherlight', /* Attribute of the triggered element that contains the selector to the lightbox content */
120
- variant: null, /* Class that will be added to change look of the lightbox */
121
- resetCss: false, /* Reset all css */
122
- background: null, /* Custom DOM for the background, wrapper and the closebutton */
123
- openTrigger: 'click', /* Event that triggers the lightbox */
124
- closeTrigger: 'click', /* Event that triggers the closing of the lightbox */
125
- filter: null, /* Selector to filter events. Think $(...).on('click', filter, eventHandler) */
126
- root: 'body', /* Where to append featherlights */
127
- openSpeed: 250, /* Duration of opening animation */
128
- closeSpeed: 250, /* Duration of closing animation */
129
- closeOnClick: 'background', /* Close lightbox on click ('background', 'anywhere' or false) */
130
- closeOnEsc: true, /* Close lightbox when pressing esc */
131
- closeIcon: '&#10005;', /* Close icon */
132
- loading: '', /* Content to show while initial content is loading */
133
- persist: false, /* If set, the content will persist and will be shown again when opened again. 'shared' is a special value when binding multiple elements for them to share the same content */
134
- otherClose: null, /* Selector for alternate close buttons (e.g. "a.close") */
135
- beforeOpen: $.noop, /* Called before open. can return false to prevent opening of lightbox. Gets event as parameter, this contains all data */
136
- beforeContent: $.noop, /* Called when content is loaded. Gets event as parameter, this contains all data */
137
- beforeClose: $.noop, /* Called before close. can return false to prevent opening of lightbox. Gets event as parameter, this contains all data */
138
- afterOpen: $.noop, /* Called after open. Gets event as parameter, this contains all data */
139
- afterContent: $.noop, /* Called after content is ready and has been set. Gets event as parameter, this contains all data */
140
- afterClose: $.noop, /* Called after close. Gets event as parameter, this contains all data */
141
- onKeyUp: $.noop, /* Called on key up for the frontmost featherlight */
142
- onResize: $.noop, /* Called after new content and when a window is resized */
143
- type: null, /* Specify type of lightbox. If unset, it will check for the targetAttrs value. */
144
- contentFilters: ['jquery', 'image', 'html', 'ajax', 'iframe', 'text'], /* List of content filters to use to determine the content */
145
-
146
- /*** methods ***/
147
- /* setup iterates over a single instance of featherlight and prepares the background and binds the events */
148
- setup: function(target, config){
149
- /* all arguments are optional */
150
- if (typeof target === 'object' && target instanceof $ === false && !config) {
151
- config = target;
152
- target = undefined;
153
- }
154
-
155
- var self = $.extend(this, config, {target: target}),
156
- css = !self.resetCss ? self.namespace : self.namespace+'-reset', /* by adding -reset to the classname, we reset all the default css */
157
- $background = $(self.background || [
158
- '<div class="'+css+'-loading '+css+'">',
159
- '<div class="'+css+'-content">',
160
- '<button class="'+css+'-close-icon '+ self.namespace + '-close" aria-label="Close">',
161
- self.closeIcon,
162
- '</button>',
163
- '<div class="'+self.namespace+'-inner">' + self.loading + '</div>',
164
- '</div>',
165
- '</div>'].join('')),
166
- closeButtonSelector = '.'+self.namespace+'-close' + (self.otherClose ? ',' + self.otherClose : '');
167
-
168
- self.$instance = $background.clone().addClass(self.variant); /* clone DOM for the background, wrapper and the close button */
169
-
170
- /* close when click on background/anywhere/null or closebox */
171
- self.$instance.on(self.closeTrigger+'.'+self.namespace, function(event) {
172
- if(event.isDefaultPrevented()) {
173
- return;
174
- }
175
- var $target = $(event.target);
176
- if( ('background' === self.closeOnClick && $target.is('.'+self.namespace))
177
- || 'anywhere' === self.closeOnClick
178
- || $target.closest(closeButtonSelector).length ){
179
- self.close(event);
180
- event.preventDefault();
181
- }
182
- });
183
-
184
- return this;
185
- },
186
-
187
- /* this method prepares the content and converts it into a jQuery object or a promise */
188
- getContent: function(){
189
- if(this.persist !== false && this.$content) {
190
- return this.$content;
191
- }
192
- var self = this,
193
- filters = this.constructor.contentFilters,
194
- readTargetAttr = function(name){ return self.$currentTarget && self.$currentTarget.attr(name); },
195
- targetValue = readTargetAttr(self.targetAttr),
196
- data = self.target || targetValue || '';
197
-
198
- /* Find which filter applies */
199
- var filter = filters[self.type]; /* check explicit type like {type: 'image'} */
200
-
201
- /* check explicit type like data-featherlight="image" */
202
- if(!filter && data in filters) {
203
- filter = filters[data];
204
- data = self.target && targetValue;
205
- }
206
- data = data || readTargetAttr('href') || '';
207
-
208
- /* check explicity type & content like {image: 'photo.jpg'} */
209
- if(!filter) {
210
- for(var filterName in filters) {
211
- if(self[filterName]) {
212
- filter = filters[filterName];
213
- data = self[filterName];
214
- }
215
- }
216
- }
217
-
218
- /* otherwise it's implicit, run checks */
219
- if(!filter) {
220
- var target = data;
221
- data = null;
222
- $.each(self.contentFilters, function() {
223
- filter = filters[this];
224
- if(filter.test) {
225
- data = filter.test(target);
226
- }
227
- if(!data && filter.regex && target.match && target.match(filter.regex)) {
228
- data = target;
229
- }
230
- return !data;
231
- });
232
- if(!data) {
233
- if('console' in window){ window.console.error('Featherlight: no content filter found ' + (target ? ' for "' + target + '"' : ' (no target specified)')); }
234
- return false;
235
- }
236
- }
237
- /* Process it */
238
- return filter.process.call(self, data);
239
- },
240
-
241
- /* sets the content of $instance to $content */
242
- setContent: function($content){
243
- this.$instance.removeClass(this.namespace+'-loading');
244
-
245
- /* we need a special class for the iframe */
246
- this.$instance.toggleClass(this.namespace+'-iframe', $content.is('iframe'));
247
-
248
- /* replace content by appending to existing one before it is removed
249
- this insures that featherlight-inner remain at the same relative
250
- position to any other items added to featherlight-content */
251
- this.$instance.find('.'+this.namespace+'-inner')
252
- .not($content) /* excluded new content, important if persisted */
253
- .slice(1).remove().end() /* In the unexpected event where there are many inner elements, remove all but the first one */
254
- .replaceWith($.contains(this.$instance[0], $content[0]) ? '' : $content);
255
-
256
- this.$content = $content.addClass(this.namespace+'-inner');
257
-
258
- return this;
259
- },
260
-
261
- /* opens the lightbox. "this" contains $instance with the lightbox, and with the config.
262
- Returns a promise that is resolved after is successfully opened. */
263
- open: function(event){
264
- var self = this;
265
- self.$instance.hide().appendTo(self.root);
266
- if((!event || !event.isDefaultPrevented())
267
- && self.beforeOpen(event) !== false) {
268
-
269
- if(event){
270
- event.preventDefault();
271
- }
272
- var $content = self.getContent();
273
-
274
- if($content) {
275
- opened.push(self);
276
-
277
- toggleGlobalEvents(true);
278
-
279
- self.$instance.fadeIn(self.openSpeed);
280
- self.beforeContent(event);
281
-
282
- /* Set content and show */
283
- return $.when($content)
284
- .always(function($content){
285
- self.setContent($content);
286
- self.afterContent(event);
287
- })
288
- .then(self.$instance.promise())
289
- /* Call afterOpen after fadeIn is done */
290
- .done(function(){ self.afterOpen(event); });
291
- }
292
- }
293
- self.$instance.detach();
294
- return $.Deferred().reject().promise();
295
- },
296
-
297
- /* closes the lightbox. "this" contains $instance with the lightbox, and with the config
298
- returns a promise, resolved after the lightbox is successfully closed. */
299
- close: function(event){
300
- var self = this,
301
- deferred = $.Deferred();
302
-
303
- if(self.beforeClose(event) === false) {
304
- deferred.reject();
305
- } else {
306
-
307
- if (0 === pruneOpened(self).length) {
308
- toggleGlobalEvents(false);
309
- }
310
-
311
- self.$instance.fadeOut(self.closeSpeed,function(){
312
- self.$instance.detach();
313
- self.afterClose(event);
314
- deferred.resolve();
315
- });
316
- }
317
- return deferred.promise();
318
- },
319
-
320
- /* resizes the content so it fits in visible area and keeps the same aspect ratio.
321
- Does nothing if either the width or the height is not specified.
322
- Called automatically on window resize.
323
- Override if you want different behavior. */
324
- resize: function(w, h) {
325
- if (w && h) {
326
- /* Reset apparent image size first so container grows */
327
- this.$content.css('width', '').css('height', '');
328
- /* Calculate the worst ratio so that dimensions fit */
329
- /* Note: -1 to avoid rounding errors */
330
- var ratio = Math.max(
331
- w / (this.$content.parent().width()-1),
332
- h / (this.$content.parent().height()-1));
333
- /* Resize content */
334
- if (ratio > 1) {
335
- ratio = h / Math.floor(h / ratio); /* Round ratio down so height calc works */
336
- this.$content.css('width', '' + w / ratio + 'px').css('height', '' + h / ratio + 'px');
337
- }
338
- }
339
- },
340
-
341
- /* Utility function to chain callbacks
342
- [Warning: guru-level]
343
- Used be extensions that want to let users specify callbacks but
344
- also need themselves to use the callbacks.
345
- The argument 'chain' has callback names as keys and function(super, event)
346
- as values. That function is meant to call `super` at some point.
347
- */
348
- chainCallbacks: function(chain) {
349
- for (var name in chain) {
350
- this[name] = $.proxy(chain[name], this, $.proxy(this[name], this));
351
- }
352
- }
353
- };
354
-
355
- $.extend(Featherlight, {
356
- id: 0, /* Used to id single featherlight instances */
357
- autoBind: '[data-featherlight]', /* Will automatically bind elements matching this selector. Clear or set before onReady */
358
- defaults: Featherlight.prototype, /* You can access and override all defaults using $.featherlight.defaults, which is just a synonym for $.featherlight.prototype */
359
- /* Contains the logic to determine content */
360
- contentFilters: {
361
- jquery: {
362
- regex: /^[#.]\w/, /* Anything that starts with a class name or identifiers */
363
- test: function(elem) { return elem instanceof $ && elem; },
364
- process: function(elem) { return this.persist !== false ? $(elem) : $(elem).clone(true); }
365
- },
366
- image: {
367
- regex: /\.(png|jpg|jpeg|gif|tiff?|bmp|svg)(\?\S*)?#x2F;i,
368
- process: function(url) {
369
- var self = this,
370
- deferred = $.Deferred(),
371
- img = new Image(),
372
- $img = $('<img src="'+url+'" alt="" class="'+self.namespace+'-image" />');
373
- img.onload = function() {
374
- /* Store naturalWidth & height for IE8 */
375
- $img.naturalWidth = img.width; $img.naturalHeight = img.height;
376
- deferred.resolve( $img );
377
- };
378
- img.onerror = function() { deferred.reject($img); };
379
- img.src = url;
380
- return deferred.promise();
381
- }
382
- },
383
- html: {
384
- regex: /^\s*<[\w!][^<]*>/, /* Anything that starts with some kind of valid tag */
385
- process: function(html) { return $(html); }
386
- },
387
- ajax: {
388
- regex: /./, /* At this point, any content is assumed to be an URL */
389
- process: function(url) {
390
- var self = this,
391
- deferred = $.Deferred();
392
- /* we are using load so one can specify a target with: url.html #targetelement */
393
- var $container = $('<div></div>').load(url, function(response, status){
394
- if ( status !== "error" ) {
395
- deferred.resolve($container.contents());
396
- }
397
- deferred.fail();
398
- });
399
- return deferred.promise();
400
- }
401
- },
402
- iframe: {
403
- process: function(url) {
404
- var deferred = new $.Deferred();
405
- var $content = $('<iframe/>');
406
- var css = parseAttrs(this, 'iframe');
407
- var attrs = slice(css, iFrameAttributeSet);
408
- $content.hide()
409
- .attr('src', url)
410
- .attr(attrs)
411
- .css(css)
412
- .on('load', function() { deferred.resolve($content.show()); })
413
- // We can't move an <iframe> and avoid reloading it,
414
- // so let's put it in place ourselves right now:
415
- .appendTo(this.$instance.find('.' + this.namespace + '-content'));
416
- return deferred.promise();
417
- }
418
- },
419
- text: {
420
- process: function(text) { return $('<div>', {text: text}); }
421
- }
422
- },
423
-
424
- functionAttributes: ['beforeOpen', 'afterOpen', 'beforeContent', 'afterContent', 'beforeClose', 'afterClose'],
425
-
426
- /*** class methods ***/
427
- /* read element's attributes starting with data-featherlight- */
428
- readElementConfig: function(element, namespace) {
429
- var Klass = this,
430
- regexp = new RegExp('^data-' + namespace + '-(.*)'),
431
- config = {};
432
- if (element && element.attributes) {
433
- $.each(element.attributes, function(){
434
- var match = this.name.match(regexp);
435
- if (match) {
436
- var val = this.value,
437
- name = $.camelCase(match[1]);
438
- if ($.inArray(name, Klass.functionAttributes) >= 0) { /* jshint -W054 */
439
- val = new Function(val); /* jshint +W054 */
440
- } else {
441
- try { val = JSON.parse(val); }
442
- catch(e) {}
443
- }
444
- config[name] = val;
445
- }
446
- });
447
- }
448
- return config;
449
- },
450
-
451
- /* Used to create a Featherlight extension
452
- [Warning: guru-level]
453
- Creates the extension's prototype that in turn
454
- inherits Featherlight's prototype.
455
- Could be used to extend an extension too...
456
- This is pretty high level wizardy, it comes pretty much straight
457
- from CoffeeScript and won't teach you anything about Featherlight
458
- as it's not really specific to this library.
459
- My suggestion: move along and keep your sanity.
460
- */
461
- extend: function(child, defaults) {
462
- /* Setup class hierarchy, adapted from CoffeeScript */
463
- var Ctor = function(){ this.constructor = child; };
464
- Ctor.prototype = this.prototype;
465
- child.prototype = new Ctor();
466
- child.__super__ = this.prototype;
467
- /* Copy class methods & attributes */
468
- $.extend(child, this, defaults);
469
- child.defaults = child.prototype;
470
- return child;
471
- },
472
-
473
- attach: function($source, $content, config) {
474
- var Klass = this;
475
- if (typeof $content === 'object' && $content instanceof $ === false && !config) {
476
- config = $content;
477
- $content = undefined;
478
- }
479
- /* make a copy */
480
- config = $.extend({}, config);
481
-
482
- /* Only for openTrigger and namespace... */
483
- var namespace = config.namespace || Klass.defaults.namespace,
484
- tempConfig = $.extend({}, Klass.defaults, Klass.readElementConfig($source[0], namespace), config),
485
- sharedPersist;
486
- var handler = function(event) {
487
- var $target = $(event.currentTarget);
488
- /* ... since we might as well compute the config on the actual target */
489
- var elemConfig = $.extend(
490
- {$source: $source, $currentTarget: $target},
491
- Klass.readElementConfig($source[0], tempConfig.namespace),
492
- Klass.readElementConfig(event.currentTarget, tempConfig.namespace),
493
- config);
494
- var fl = sharedPersist || $target.data('featherlight-persisted') || new Klass($content, elemConfig);
495
- if(fl.persist === 'shared') {
496
- sharedPersist = fl;
497
- } else if(fl.persist !== false) {
498
- $target.data('featherlight-persisted', fl);
499
- }
500
- if (elemConfig.$currentTarget.blur) {
501
- elemConfig.$currentTarget.blur(); // Otherwise 'enter' key might trigger the dialog again
502
- }
503
- fl.open(event);
504
- };
505
-
506
- $source.on(tempConfig.openTrigger+'.'+tempConfig.namespace, tempConfig.filter, handler);
507
-
508
- return handler;
509
- },
510
-
511
- current: function() {
512
- var all = this.opened();
513
- return all[all.length - 1] || null;
514
- },
515
-
516
- opened: function() {
517
- var klass = this;
518
- pruneOpened();
519
- return $.grep(opened, function(fl) { return fl instanceof klass; } );
520
- },
521
-
522
- close: function(event) {
523
- var cur = this.current();
524
- if(cur) { return cur.close(event); }
525
- },
526
-
527
- /* Does the auto binding on startup.
528
- Meant only to be used by Featherlight and its extensions
529
- */
530
- _onReady: function() {
531
- var Klass = this;
532
- if(Klass.autoBind){
533
- /* Bind existing elements */
534
- $(Klass.autoBind).each(function(){
535
- Klass.attach($(this));
536
- });
537
- /* If a click propagates to the document level, then we have an item that was added later on */
538
- $(document).on('click', Klass.autoBind, function(evt) {
539
- if (evt.isDefaultPrevented()) {
540
- return;
541
- }
542
- /* Bind featherlight */
543
- var handler = Klass.attach($(evt.currentTarget));
544
- /* Dispatch event directly */
545
- handler(evt);
546
- });
547
- }
548
- },
549
-
550
- /* Featherlight uses the onKeyUp callback to intercept the escape key.
551
- Private to Featherlight.
552
- */
553
- _callbackChain: {
554
- onKeyUp: function(_super, event){
555
- if(27 === event.keyCode) {
556
- if (this.closeOnEsc) {
557
- $.featherlight.close(event);
558
- }
559
- return false;
560
- } else {
561
- return _super(event);
562
- }
563
- },
564
-
565
- beforeOpen: function(_super, event) {
566
- // Used to disable scrolling
567
- $(document.documentElement).addClass('with-featherlight');
568
-
569
- // Remember focus:
570
- this._previouslyActive = document.activeElement;
571
-
572
- // Disable tabbing:
573
- // See http://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus
574
- this._$previouslyTabbable = $("a, input, select, textarea, iframe, button, iframe, [contentEditable=true]")
575
- .not('[tabindex]')
576
- .not(this.$instance.find('button'));
577
-
578
- this._$previouslyWithTabIndex = $('[tabindex]').not('[tabindex="-1"]');
579
- this._previousWithTabIndices = this._$previouslyWithTabIndex.map(function(_i, elem) {
580
- return $(elem).attr('tabindex');
581
- });
582
-
583
- this._$previouslyWithTabIndex.add(this._$previouslyTabbable).attr('tabindex', -1);
584
-
585
- if (document.activeElement.blur) {
586
- document.activeElement.blur();
587
- }
588
- return _super(event);
589
- },
590
-
591
- afterClose: function(_super, event) {
592
- var r = _super(event);
593
- // Restore focus
594
- var self = this;
595
- this._$previouslyTabbable.removeAttr('tabindex');
596
- this._$previouslyWithTabIndex.each(function(i, elem) {
597
- $(elem).attr('tabindex', self._previousWithTabIndices[i]);
598
- });
599
- this._previouslyActive.focus();
600
- // Restore scroll
601
- if(Featherlight.opened().length === 0) {
602
- $(document.documentElement).removeClass('with-featherlight');
603
- }
604
- return r;
605
- },
606
-
607
- onResize: function(_super, event){
608
- this.resize(this.$content.naturalWidth, this.$content.naturalHeight);
609
- return _super(event);
610
- },
611
-
612
- afterContent: function(_super, event){
613
- var r = _super(event);
614
- this.$instance.find('[autofocus]:not([disabled])').focus();
615
- this.onResize(event);
616
- return r;
617
- }
618
- }
619
- });
620
-
621
- $.featherlight = Featherlight;
622
-
623
- /* bind jQuery elements to trigger featherlight */
624
- $.fn.featherlight = function($content, config) {
625
- Featherlight.attach(this, $content, config);
626
- return this;
627
- };
628
-
629
- /* bind featherlight on ready if config autoBind is set */
630
- $(document).ready(function(){ Featherlight._onReady(); });
631
- }(jQuery));
1
+ /**
2
+ * Featherlight - ultra slim jQuery lightbox
3
+ * Version 1.7.13 - http://noelboss.github.io/featherlight/
4
+ *
5
+ * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
6
+ * MIT Licensed.
7
+ **/
8
+ (function($) {
9
+ "use strict";
10
+
11
+ if('undefined' === typeof $) {
12
+ if('console' in window){ window.console.info('Too much lightness, Featherlight needs jQuery.'); }
13
+ return;
14
+ }
15
+ if($.fn.jquery.match(/-ajax/)) {
16
+ if('console' in window){ window.console.info('Featherlight needs regular jQuery, not the slim version.'); }
17
+ return;
18
+ }
19
+ /* Featherlight is exported as $.featherlight.
20
+ It is a function used to open a featherlight lightbox.
21
+
22
+ [tech]
23
+ Featherlight uses prototype inheritance.
24
+ Each opened lightbox will have a corresponding object.
25
+ That object may have some attributes that override the
26
+ prototype's.
27
+ Extensions created with Featherlight.extend will have their
28
+ own prototype that inherits from Featherlight's prototype,
29
+ thus attributes can be overriden either at the object level,
30
+ or at the extension level.
31
+ To create callbacks that chain themselves instead of overriding,
32
+ use chainCallbacks.
33
+ For those familiar with CoffeeScript, this correspond to
34
+ Featherlight being a class and the Gallery being a class
35
+ extending Featherlight.
36
+ The chainCallbacks is used since we don't have access to
37
+ CoffeeScript's `super`.
38
+ */
39
+
40
+ function Featherlight($content, config) {
41
+ if(this instanceof Featherlight) { /* called with new */
42
+ this.id = Featherlight.id++;
43
+ this.setup($content, config);
44
+ this.chainCallbacks(Featherlight._callbackChain);
45
+ } else {
46
+ var fl = new Featherlight($content, config);
47
+ fl.open();
48
+ return fl;
49
+ }
50
+ }
51
+
52
+ var opened = [],
53
+ pruneOpened = function(remove) {
54
+ opened = $.grep(opened, function(fl) {
55
+ return fl !== remove && fl.$instance.closest('body').length > 0;
56
+ } );
57
+ return opened;
58
+ };
59
+
60
+ // Removes keys of `set` from `obj` and returns the removed key/values.
61
+ function slice(obj, set) {
62
+ var r = {};
63
+ for (var key in obj) {
64
+ if (key in set) {
65
+ r[key] = obj[key];
66
+ delete obj[key];
67
+ }
68
+ }
69
+ return r;
70
+ }
71
+
72
+ // NOTE: List of available [iframe attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe).
73
+ var iFrameAttributeSet = {
74
+ allow: 1, allowfullscreen: 1, frameborder: 1, height: 1, longdesc: 1, marginheight: 1, marginwidth: 1,
75
+ mozallowfullscreen: 1, name: 1, referrerpolicy: 1, sandbox: 1, scrolling: 1, src: 1, srcdoc: 1, style: 1,
76
+ webkitallowfullscreen: 1, width: 1
77
+ };
78
+
79
+ // Converts camelCased attributes to dasherized versions for given prefix:
80
+ // parseAttrs({hello: 1, hellFrozeOver: 2}, 'hell') => {froze-over: 2}
81
+ function parseAttrs(obj, prefix) {
82
+ var attrs = {},
83
+ regex = new RegExp('^' + prefix + '([A-Z])(.*)');
84
+ for (var key in obj) {
85
+ var match = key.match(regex);
86
+ if (match) {
87
+ var dasherized = (match[1] + match[2].replace(/([A-Z])/g, '-$1')).toLowerCase();
88
+ attrs[dasherized] = obj[key];
89
+ }
90
+ }
91
+ return attrs;
92
+ }
93
+
94
+ /* document wide key handler */
95
+ var eventMap = { keyup: 'onKeyUp', resize: 'onResize' };
96
+
97
+ var globalEventHandler = function(event) {
98
+ $.each(Featherlight.opened().reverse(), function() {
99
+ if (!event.isDefaultPrevented()) {
100
+ if (false === this[eventMap[event.type]](event)) {
101
+ event.preventDefault(); event.stopPropagation(); return false;
102
+ }
103
+ }
104
+ });
105
+ };
106
+
107
+ var toggleGlobalEvents = function(set) {
108
+ if(set !== Featherlight._globalHandlerInstalled) {
109
+ Featherlight._globalHandlerInstalled = set;
110
+ var events = $.map(eventMap, function(_, name) { return name+'.'+Featherlight.prototype.namespace; } ).join(' ');
111
+ $(window)[set ? 'on' : 'off'](events, globalEventHandler);
112
+ }
113
+ };
114
+
115
+ Featherlight.prototype = {
116
+ constructor: Featherlight,
117
+ /*** defaults ***/
118
+ /* extend featherlight with defaults and methods */
119
+ namespace: 'featherlight', /* Name of the events and css class prefix */
120
+ targetAttr: 'data-featherlight', /* Attribute of the triggered element that contains the selector to the lightbox content */
121
+ variant: null, /* Class that will be added to change look of the lightbox */
122
+ resetCss: false, /* Reset all css */
123
+ background: null, /* Custom DOM for the background, wrapper and the closebutton */
124
+ openTrigger: 'click', /* Event that triggers the lightbox */
125
+ closeTrigger: 'click', /* Event that triggers the closing of the lightbox */
126
+ filter: null, /* Selector to filter events. Think $(...).on('click', filter, eventHandler) */
127
+ root: 'body', /* Where to append featherlights */
128
+ openSpeed: 250, /* Duration of opening animation */
129
+ closeSpeed: 250, /* Duration of closing animation */
130
+ closeOnClick: 'background', /* Close lightbox on click ('background', 'anywhere' or false) */
131
+ closeOnEsc: true, /* Close lightbox when pressing esc */
132
+ closeIcon: '&#10005;', /* Close icon */
133
+ loading: '', /* Content to show while initial content is loading */
134
+ persist: false, /* If set, the content will persist and will be shown again when opened again. 'shared' is a special value when binding multiple elements for them to share the same content */
135
+ otherClose: null, /* Selector for alternate close buttons (e.g. "a.close") */
136
+ beforeOpen: $.noop, /* Called before open. can return false to prevent opening of lightbox. Gets event as parameter, this contains all data */
137
+ beforeContent: $.noop, /* Called when content is loaded. Gets event as parameter, this contains all data */
138
+ beforeClose: $.noop, /* Called before close. can return false to prevent opening of lightbox. Gets event as parameter, this contains all data */
139
+ afterOpen: $.noop, /* Called after open. Gets event as parameter, this contains all data */
140
+ afterContent: $.noop, /* Called after content is ready and has been set. Gets event as parameter, this contains all data */
141
+ afterClose: $.noop, /* Called after close. Gets event as parameter, this contains all data */
142
+ onKeyUp: $.noop, /* Called on key up for the frontmost featherlight */
143
+ onResize: $.noop, /* Called after new content and when a window is resized */
144
+ type: null, /* Specify type of lightbox. If unset, it will check for the targetAttrs value. */
145
+ contentFilters: ['jquery', 'image', 'html', 'ajax', 'iframe', 'text'], /* List of content filters to use to determine the content */
146
+
147
+ /*** methods ***/
148
+ /* setup iterates over a single instance of featherlight and prepares the background and binds the events */
149
+ setup: function(target, config){
150
+ /* all arguments are optional */
151
+ if (typeof target === 'object' && target instanceof $ === false && !config) {
152
+ config = target;
153
+ target = undefined;
154
+ }
155
+
156
+ var self = $.extend(this, config, {target: target}),
157
+ css = !self.resetCss ? self.namespace : self.namespace+'-reset', /* by adding -reset to the classname, we reset all the default css */
158
+ $background = $(self.background || [
159
+ '<div class="'+css+'-loading '+css+'">',
160
+ '<div class="'+css+'-content">',
161
+ '<button class="'+css+'-close-icon '+ self.namespace + '-close" aria-label="Close">',
162
+ self.closeIcon,
163
+ '</button>',
164
+ '<div class="'+self.namespace+'-inner">' + self.loading + '</div>',
165
+ '</div>',
166
+ '</div>'].join('')),
167
+ closeButtonSelector = '.'+self.namespace+'-close' + (self.otherClose ? ',' + self.otherClose : '');
168
+
169
+ self.$instance = $background.clone().addClass(self.variant); /* clone DOM for the background, wrapper and the close button */
170
+
171
+ /* close when click on background/anywhere/null or closebox */
172
+ self.$instance.on(self.closeTrigger+'.'+self.namespace, function(event) {
173
+ if(event.isDefaultPrevented()) {
174
+ return;
175
+ }
176
+ var $target = $(event.target);
177
+ if( ('background' === self.closeOnClick && $target.is('.'+self.namespace))
178
+ || 'anywhere' === self.closeOnClick
179
+ || $target.closest(closeButtonSelector).length ){
180
+ self.close(event);
181
+ event.preventDefault();
182
+ }
183
+ });
184
+
185
+ return this;
186
+ },
187
+
188
+ /* this method prepares the content and converts it into a jQuery object or a promise */
189
+ getContent: function(){
190
+ if(this.persist !== false && this.$content) {
191
+ return this.$content;
192
+ }
193
+ var self = this,
194
+ filters = this.constructor.contentFilters,
195
+ readTargetAttr = function(name){ return self.$currentTarget && self.$currentTarget.attr(name); },
196
+ targetValue = readTargetAttr(self.targetAttr),
197
+ data = self.target || targetValue || '';
198
+
199
+ /* Find which filter applies */
200
+ var filter = filters[self.type]; /* check explicit type like {type: 'image'} */
201
+
202
+ /* check explicit type like data-featherlight="image" */
203
+ if(!filter && data in filters) {
204
+ filter = filters[data];
205
+ data = self.target && targetValue;
206
+ }
207
+ data = data || readTargetAttr('href') || '';
208
+
209
+ /* check explicity type & content like {image: 'photo.jpg'} */
210
+ if(!filter) {
211
+ for(var filterName in filters) {
212
+ if(self[filterName]) {
213
+ filter = filters[filterName];
214
+ data = self[filterName];
215
+ }
216
+ }
217
+ }
218
+
219
+ /* otherwise it's implicit, run checks */
220
+ if(!filter) {
221
+ var target = data;
222
+ data = null;
223
+ $.each(self.contentFilters, function() {
224
+ filter = filters[this];
225
+ if(filter.test) {
226
+ data = filter.test(target);
227
+ }
228
+ if(!data && filter.regex && target.match && target.match(filter.regex)) {
229
+ data = target;
230
+ }
231
+ return !data;
232
+ });
233
+ if(!data) {
234
+ if('console' in window){ window.console.error('Featherlight: no content filter found ' + (target ? ' for "' + target + '"' : ' (no target specified)')); }
235
+ return false;
236
+ }
237
+ }
238
+ /* Process it */
239
+ return filter.process.call(self, data);
240
+ },
241
+
242
+ /* sets the content of $instance to $content */
243
+ setContent: function($content){
244
+ this.$instance.removeClass(this.namespace+'-loading');
245
+
246
+ /* we need a special class for the iframe */
247
+ this.$instance.toggleClass(this.namespace+'-iframe', $content.is('iframe'));
248
+
249
+ /* replace content by appending to existing one before it is removed
250
+ this insures that featherlight-inner remain at the same relative
251
+ position to any other items added to featherlight-content */
252
+ this.$instance.find('.'+this.namespace+'-inner')
253
+ .not($content) /* excluded new content, important if persisted */
254
+ .slice(1).remove().end() /* In the unexpected event where there are many inner elements, remove all but the first one */
255
+ .replaceWith($.contains(this.$instance[0], $content[0]) ? '' : $content);
256
+
257
+ this.$content = $content.addClass(this.namespace+'-inner');
258
+
259
+ return this;
260
+ },
261
+
262
+ /* opens the lightbox. "this" contains $instance with the lightbox, and with the config.
263
+ Returns a promise that is resolved after is successfully opened. */
264
+ open: function(event){
265
+ var self = this;
266
+ self.$instance.hide().appendTo(self.root);
267
+ if((!event || !event.isDefaultPrevented())
268
+ && self.beforeOpen(event) !== false) {
269
+
270
+ if(event){
271
+ event.preventDefault();
272
+ }
273
+ var $content = self.getContent();
274
+
275
+ if($content) {
276
+ opened.push(self);
277
+
278
+ toggleGlobalEvents(true);
279
+
280
+ self.$instance.fadeIn(self.openSpeed);
281
+ self.beforeContent(event);
282
+
283
+ /* Set content and show */
284
+ return $.when($content)
285
+ .always(function($content){
286
+ self.setContent($content);
287
+ self.afterContent(event);
288
+ })
289
+ .then(self.$instance.promise())
290
+ /* Call afterOpen after fadeIn is done */
291
+ .done(function(){ self.afterOpen(event); });
292
+ }
293
+ }
294
+ self.$instance.detach();
295
+ return $.Deferred().reject().promise();
296
+ },
297
+
298
+ /* closes the lightbox. "this" contains $instance with the lightbox, and with the config
299
+ returns a promise, resolved after the lightbox is successfully closed. */
300
+ close: function(event){
301
+ var self = this,
302
+ deferred = $.Deferred();
303
+
304
+ if(self.beforeClose(event) === false) {
305
+ deferred.reject();
306
+ } else {
307
+
308
+ if (0 === pruneOpened(self).length) {
309
+ toggleGlobalEvents(false);
310
+ }
311
+
312
+ self.$instance.fadeOut(self.closeSpeed,function(){
313
+ self.$instance.detach();
314
+ self.afterClose(event);
315
+ deferred.resolve();
316
+ });
317
+ }
318
+ return deferred.promise();
319
+ },
320
+
321
+ /* resizes the content so it fits in visible area and keeps the same aspect ratio.
322
+ Does nothing if either the width or the height is not specified.
323
+ Called automatically on window resize.
324
+ Override if you want different behavior. */
325
+ resize: function(w, h) {
326
+ if (w && h) {
327
+ /* Reset apparent image size first so container grows */
328
+ this.$content.css('width', '').css('height', '');
329
+ /* Calculate the worst ratio so that dimensions fit */
330
+ /* Note: -1 to avoid rounding errors */
331
+ var ratio = Math.max(
332
+ w / (this.$content.parent().width()-1),
333
+ h / (this.$content.parent().height()-1));
334
+ /* Resize content */
335
+ if (ratio > 1) {
336
+ ratio = h / Math.floor(h / ratio); /* Round ratio down so height calc works */
337
+ this.$content.css('width', '' + w / ratio + 'px').css('height', '' + h / ratio + 'px');
338
+ }
339
+ }
340
+ },
341
+
342
+ /* Utility function to chain callbacks
343
+ [Warning: guru-level]
344
+ Used be extensions that want to let users specify callbacks but
345
+ also need themselves to use the callbacks.
346
+ The argument 'chain' has callback names as keys and function(super, event)
347
+ as values. That function is meant to call `super` at some point.
348
+ */
349
+ chainCallbacks: function(chain) {
350
+ for (var name in chain) {
351
+ this[name] = $.proxy(chain[name], this, $.proxy(this[name], this));
352
+ }
353
+ }
354
+ };
355
+
356
+ $.extend(Featherlight, {
357
+ id: 0, /* Used to id single featherlight instances */
358
+ autoBind: '[data-featherlight]', /* Will automatically bind elements matching this selector. Clear or set before onReady */
359
+ defaults: Featherlight.prototype, /* You can access and override all defaults using $.featherlight.defaults, which is just a synonym for $.featherlight.prototype */
360
+ /* Contains the logic to determine content */
361
+ contentFilters: {
362
+ jquery: {
363
+ regex: /^[#.]\w/, /* Anything that starts with a class name or identifiers */
364
+ test: function(elem) { return elem instanceof $ && elem; },
365
+ process: function(elem) { return this.persist !== false ? $(elem) : $(elem).clone(true); }
366
+ },
367
+ image: {
368
+ regex: /\.(png|jpg|jpeg|gif|tiff?|bmp|svg)(\?\S*)?#x2F;i,
369
+ process: function(url) {
370
+ var self = this,
371
+ deferred = $.Deferred(),
372
+ img = new Image(),
373
+ $img = $('<img src="'+url+'" alt="" class="'+self.namespace+'-image" />');
374
+ img.onload = function() {
375
+ /* Store naturalWidth & height for IE8 */
376
+ $img.naturalWidth = img.width; $img.naturalHeight = img.height;
377
+ deferred.resolve( $img );
378
+ };
379
+ img.onerror = function() { deferred.reject($img); };
380
+ img.src = url;
381
+ return deferred.promise();
382
+ }
383
+ },
384
+ html: {
385
+ regex: /^\s*<[\w!][^<]*>/, /* Anything that starts with some kind of valid tag */
386
+ process: function(html) { return $(html); }
387
+ },
388
+ ajax: {
389
+ regex: /./, /* At this point, any content is assumed to be an URL */
390
+ process: function(url) {
391
+ var self = this,
392
+ deferred = $.Deferred();
393
+ /* we are using load so one can specify a target with: url.html #targetelement */
394
+ var $container = $('<div></div>').load(url, function(response, status){
395
+ if ( status !== "error" ) {
396
+ deferred.resolve($container.contents());
397
+ }
398
+ deferred.fail();
399
+ });
400
+ return deferred.promise();
401
+ }
402
+ },
403
+ iframe: {
404
+ process: function(url) {
405
+ var deferred = new $.Deferred();
406
+ var $content = $('<iframe/>');
407
+ var css = parseAttrs(this, 'iframe');
408
+ var attrs = slice(css, iFrameAttributeSet);
409
+ $content.hide()
410
+ .attr('src', url)
411
+ .attr(attrs)
412
+ .css(css)
413
+ .on('load', function() { deferred.resolve($content.show()); })
414
+ // We can't move an <iframe> and avoid reloading it,
415
+ // so let's put it in place ourselves right now:
416
+ .appendTo(this.$instance.find('.' + this.namespace + '-content'));
417
+ return deferred.promise();
418
+ }
419
+ },
420
+ text: {
421
+ process: function(text) { return $('<div>', {text: text}); }
422
+ }
423
+ },
424
+
425
+ functionAttributes: ['beforeOpen', 'afterOpen', 'beforeContent', 'afterContent', 'beforeClose', 'afterClose'],
426
+
427
+ /*** class methods ***/
428
+ /* read element's attributes starting with data-featherlight- */
429
+ readElementConfig: function(element, namespace) {
430
+ var Klass = this,
431
+ regexp = new RegExp('^data-' + namespace + '-(.*)'),
432
+ config = {};
433
+ if (element && element.attributes) {
434
+ $.each(element.attributes, function(){
435
+ var match = this.name.match(regexp);
436
+ if (match) {
437
+ var val = this.value,
438
+ name = $.camelCase(match[1]);
439
+ if ($.inArray(name, Klass.functionAttributes) >= 0) { /* jshint -W054 */
440
+ val = new Function(val); /* jshint +W054 */
441
+ } else {
442
+ try { val = JSON.parse(val); }
443
+ catch(e) {}
444
+ }
445
+ config[name] = val;
446
+ }
447
+ });
448
+ }
449
+ return config;
450
+ },
451
+
452
+ /* Used to create a Featherlight extension
453
+ [Warning: guru-level]
454
+ Creates the extension's prototype that in turn
455
+ inherits Featherlight's prototype.
456
+ Could be used to extend an extension too...
457
+ This is pretty high level wizardy, it comes pretty much straight
458
+ from CoffeeScript and won't teach you anything about Featherlight
459
+ as it's not really specific to this library.
460
+ My suggestion: move along and keep your sanity.
461
+ */
462
+ extend: function(child, defaults) {
463
+ /* Setup class hierarchy, adapted from CoffeeScript */
464
+ var Ctor = function(){ this.constructor = child; };
465
+ Ctor.prototype = this.prototype;
466
+ child.prototype = new Ctor();
467
+ child.__super__ = this.prototype;
468
+ /* Copy class methods & attributes */
469
+ $.extend(child, this, defaults);
470
+ child.defaults = child.prototype;
471
+ return child;
472
+ },
473
+
474
+ attach: function($source, $content, config) {
475
+ var Klass = this;
476
+ if (typeof $content === 'object' && $content instanceof $ === false && !config) {
477
+ config = $content;
478
+ $content = undefined;
479
+ }
480
+ /* make a copy */
481
+ config = $.extend({}, config);
482
+
483
+ /* Only for openTrigger, filter & namespace... */
484
+ var namespace = config.namespace || Klass.defaults.namespace,
485
+ tempConfig = $.extend({}, Klass.defaults, Klass.readElementConfig($source[0], namespace), config),
486
+ sharedPersist;
487
+ var handler = function(event) {
488
+ var $target = $(event.currentTarget);
489
+ /* ... since we might as well compute the config on the actual target */
490
+ var elemConfig = $.extend(
491
+ {$source: $source, $currentTarget: $target},
492
+ Klass.readElementConfig($source[0], tempConfig.namespace),
493
+ Klass.readElementConfig(event.currentTarget, tempConfig.namespace),
494
+ config);
495
+ var fl = sharedPersist || $target.data('featherlight-persisted') || new Klass($content, elemConfig);
496
+ if(fl.persist === 'shared') {
497
+ sharedPersist = fl;
498
+ } else if(fl.persist !== false) {
499
+ $target.data('featherlight-persisted', fl);
500
+ }
501
+ if (elemConfig.$currentTarget.blur) {
502
+ elemConfig.$currentTarget.blur(); // Otherwise 'enter' key might trigger the dialog again
503
+ }
504
+ fl.open(event);
505
+ };
506
+
507
+ $source.on(tempConfig.openTrigger+'.'+tempConfig.namespace, tempConfig.filter, handler);
508
+
509
+ return {filter: tempConfig.filter, handler: handler};
510
+ },
511
+
512
+ current: function() {
513
+ var all = this.opened();
514
+ return all[all.length - 1] || null;
515
+ },
516
+
517
+ opened: function() {
518
+ var klass = this;
519
+ pruneOpened();
520
+ return $.grep(opened, function(fl) { return fl instanceof klass; } );
521
+ },
522
+
523
+ close: function(event) {
524
+ var cur = this.current();
525
+ if(cur) { return cur.close(event); }
526
+ },
527
+
528
+ /* Does the auto binding on startup.
529
+ Meant only to be used by Featherlight and its extensions
530
+ */
531
+ _onReady: function() {
532
+ var Klass = this;
533
+ if(Klass.autoBind){
534
+ var $autobound = $(Klass.autoBind);
535
+ /* Bind existing elements */
536
+ $autobound.each(function(){
537
+ Klass.attach($(this));
538
+ });
539
+ /* If a click propagates to the document level, then we have an item that was added later on */
540
+ $(document).on('click', Klass.autoBind, function(evt) {
541
+ if (evt.isDefaultPrevented()) {
542
+ return;
543
+ }
544
+ var $cur = $(evt.currentTarget);
545
+ var len = $autobound.length;
546
+ $autobound = $autobound.add($cur);
547
+ if(len === $autobound.length) {
548
+ return; /* already bound */
549
+ }
550
+ /* Bind featherlight */
551
+ var data = Klass.attach($cur);
552
+ /* Dispatch event directly */
553
+ if (!data.filter || $(evt.target).parentsUntil($cur, data.filter).length > 0) {
554
+ data.handler(evt);
555
+ }
556
+ });
557
+ }
558
+ },
559
+
560
+ /* Featherlight uses the onKeyUp callback to intercept the escape key.
561
+ Private to Featherlight.
562
+ */
563
+ _callbackChain: {
564
+ onKeyUp: function(_super, event){
565
+ if(27 === event.keyCode) {
566
+ if (this.closeOnEsc) {
567
+ $.featherlight.close(event);
568
+ }
569
+ return false;
570
+ } else {
571
+ return _super(event);
572
+ }
573
+ },
574
+
575
+ beforeOpen: function(_super, event) {
576
+ // Used to disable scrolling
577
+ $(document.documentElement).addClass('with-featherlight');
578
+
579
+ // Remember focus:
580
+ this._previouslyActive = document.activeElement;
581
+
582
+ // Disable tabbing:
583
+ // See http://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus
584
+ this._$previouslyTabbable = $("a, input, select, textarea, iframe, button, iframe, [contentEditable=true]")
585
+ .not('[tabindex]')
586
+ .not(this.$instance.find('button'));
587
+
588
+ this._$previouslyWithTabIndex = $('[tabindex]').not('[tabindex="-1"]');
589
+ this._previousWithTabIndices = this._$previouslyWithTabIndex.map(function(_i, elem) {
590
+ return $(elem).attr('tabindex');
591
+ });
592
+
593
+ this._$previouslyWithTabIndex.add(this._$previouslyTabbable).attr('tabindex', -1);
594
+
595
+ if (document.activeElement.blur) {
596
+ document.activeElement.blur();
597
+ }
598
+ return _super(event);
599
+ },
600
+
601
+ afterClose: function(_super, event) {
602
+ var r = _super(event);
603
+ // Restore focus
604
+ var self = this;
605
+ this._$previouslyTabbable.removeAttr('tabindex');
606
+ this._$previouslyWithTabIndex.each(function(i, elem) {
607
+ $(elem).attr('tabindex', self._previousWithTabIndices[i]);
608
+ });
609
+ this._previouslyActive.focus();
610
+ // Restore scroll
611
+ if(Featherlight.opened().length === 0) {
612
+ $(document.documentElement).removeClass('with-featherlight');
613
+ }
614
+ return r;
615
+ },
616
+
617
+ onResize: function(_super, event){
618
+ this.resize(this.$content.naturalWidth, this.$content.naturalHeight);
619
+ return _super(event);
620
+ },
621
+
622
+ afterContent: function(_super, event){
623
+ var r = _super(event);
624
+ this.$instance.find('[autofocus]:not([disabled])').focus();
625
+ this.onResize(event);
626
+ return r;
627
+ }
628
+ }
629
+ });
630
+
631
+ $.featherlight = Featherlight;
632
+
633
+ /* bind jQuery elements to trigger featherlight */
634
+ $.fn.featherlight = function($content, config) {
635
+ Featherlight.attach(this, $content, config);
636
+ return this;
637
+ };
638
+
639
+ /* bind featherlight on ready if config autoBind is set */
640
+ $(document).ready(function(){ Featherlight._onReady(); });
641
+ }(jQuery));
assets/featherlight/featherlight.min.css CHANGED
@@ -1,8 +1,8 @@
1
- /**
2
- * Featherlight - ultra slim jQuery lightbox
3
- * Version 1.7.12 - http://noelboss.github.io/featherlight/
4
- *
5
- * Copyright 2017, Noël Raoul Bossart (http://www.noelboss.com)
6
- * MIT Licensed.
7
- **/
8
- @media all{html.with-featherlight{overflow:hidden}.featherlight{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:2147483647;text-align:center;white-space:nowrap;cursor:pointer;background:#333;background:rgba(0,0,0,0)}.featherlight:last-of-type{background:rgba(0,0,0,.8)}.featherlight:before{content:'';display:inline-block;height:100%;vertical-align:middle}.featherlight .featherlight-content{position:relative;text-align:left;vertical-align:middle;display:inline-block;overflow:auto;padding:25px 25px 0;border-bottom:25px solid transparent;margin-left:5%;margin-right:5%;max-height:95%;background:#fff;cursor:auto;white-space:normal}.featherlight .featherlight-inner{display:block}.featherlight link.featherlight-inner,.featherlight script.featherlight-inner,.featherlight style.featherlight-inner{display:none}.featherlight .featherlight-close-icon{position:absolute;z-index:9999;top:0;right:0;line-height:25px;width:25px;cursor:pointer;text-align:center;font-family:Arial,sans-serif;background:#fff;background:rgba(255,255,255,.3);color:#000;border:0;padding:0}.featherlight .featherlight-close-icon::-moz-focus-inner{border:0;padding:0}.featherlight .featherlight-image{width:100%}.featherlight-iframe .featherlight-content{border-bottom:0;padding:0;-webkit-overflow-scrolling:touch;overflow-y:scroll}.featherlight iframe{border:0}.featherlight *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}}@media only screen and (max-width:1024px){.featherlight .featherlight-content{margin-left:0;margin-right:0;max-height:98%;padding:10px 10px 0;border-bottom:10px solid transparent}}@media print{html.with-featherlight>*>:not(.featherlight){display:none}}
1
+ /**
2
+ * Featherlight - ultra slim jQuery lightbox
3
+ * Version 1.7.13 - http://noelboss.github.io/featherlight/
4
+ *
5
+ * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
6
+ * MIT Licensed.
7
+ **/
8
+ html.with-featherlight{overflow:hidden}.featherlight{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:2147483647;text-align:center;white-space:nowrap;cursor:pointer;background:#333;background:rgba(0,0,0,0)}.featherlight:last-of-type{background:rgba(0,0,0,.8)}.featherlight:before{content:'';display:inline-block;height:100%;vertical-align:middle}.featherlight .featherlight-content{position:relative;text-align:left;vertical-align:middle;display:inline-block;overflow:auto;padding:25px 25px 0;border-bottom:25px solid transparent;margin-left:5%;margin-right:5%;max-height:95%;background:#fff;cursor:auto;white-space:normal}.featherlight .featherlight-inner{display:block}.featherlight link.featherlight-inner,.featherlight script.featherlight-inner,.featherlight style.featherlight-inner{display:none}.featherlight .featherlight-close-icon{position:absolute;z-index:9999;top:0;right:0;line-height:25px;width:25px;cursor:pointer;text-align:center;font-family:Arial,sans-serif;background:#fff;background:rgba(255,255,255,.3);color:#000;border:0;padding:0}.featherlight .featherlight-close-icon::-moz-focus-inner{border:0;padding:0}.featherlight .featherlight-image{width:100%}.featherlight-iframe .featherlight-content{border-bottom:0;padding:0;-webkit-overflow-scrolling:touch}.featherlight iframe{border:0}.featherlight *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@media only screen and (max-width:1024px){.featherlight .featherlight-content{margin-left:0;margin-right:0;max-height:98%;padding:10px 10px 0;border-bottom:10px solid transparent}}@media print{html.with-featherlight>*>:not(.featherlight){display:none}}
assets/featherlight/featherlight.min.js CHANGED
@@ -1,8 +1,8 @@
1
- /**
2
- * Featherlight - ultra slim jQuery lightbox
3
- * Version 1.7.12 - http://noelboss.github.io/featherlight/
4
- *
5
- * Copyright 2017, Noël Raoul Bossart (http://www.noelboss.com)
6
- * MIT Licensed.
7
- **/
8
- !function(a){"use strict";function b(a,c){if(!(this instanceof b)){var d=new b(a,c);return d.open(),d}this.id=b.id++,this.setup(a,c),this.chainCallbacks(b._callbackChain)}function c(a,b){var c={};for(var d in a)d in b&&(c[d]=a[d],delete a[d]);return c}function d(a,b){var c={},d=new RegExp("^"+b+"([A-Z])(.*)");for(var e in a){var f=e.match(d);if(f){var g=(f[1]+f[2].replace(/([A-Z])/g,"-$1")).toLowerCase();c[g]=a[e]}}return c}if("undefined"==typeof a)return void("console"in window&&window.console.info("Too much lightness, Featherlight needs jQuery."));if(a.fn.jquery.match(/-ajax/))return void("console"in window&&window.console.info("Featherlight needs regular jQuery, not the slim version."));var e=[],f=function(b){return e=a.grep(e,function(a){return a!==b&&a.$instance.closest("body").length>0})},g={allowfullscreen:1,frameborder:1,height:1,longdesc:1,marginheight:1,marginwidth:1,name:1,referrerpolicy:1,scrolling:1,sandbox:1,src:1,srcdoc:1,width:1},h={keyup:"onKeyUp",resize:"onResize"},i=function(c){a.each(b.opened().reverse(),function(){return c.isDefaultPrevented()||!1!==this[h[c.type]](c)?void 0:(c.preventDefault(),c.stopPropagation(),!1)})},j=function(c){if(c!==b._globalHandlerInstalled){b._globalHandlerInstalled=c;var d=a.map(h,function(a,c){return c+"."+b.prototype.namespace}).join(" ");a(window)[c?"on":"off"](d,i)}};b.prototype={constructor:b,namespace:"featherlight",targetAttr:"data-featherlight",variant:null,resetCss:!1,background:null,openTrigger:"click",closeTrigger:"click",filter:null,root:"body",openSpeed:250,closeSpeed:250,closeOnClick:"background",closeOnEsc:!0,closeIcon:"&#10005;",loading:"",persist:!1,otherClose:null,beforeOpen:a.noop,beforeContent:a.noop,beforeClose:a.noop,afterOpen:a.noop,afterContent:a.noop,afterClose:a.noop,onKeyUp:a.noop,onResize:a.noop,type:null,contentFilters:["jquery","image","html","ajax","iframe","text"],setup:function(b,c){"object"!=typeof b||b instanceof a!=!1||c||(c=b,b=void 0);var d=a.extend(this,c,{target:b}),e=d.resetCss?d.namespace+"-reset":d.namespace,f=a(d.background||['<div class="'+e+"-loading "+e+'">','<div class="'+e+'-content">','<button class="'+e+"-close-icon "+d.namespace+'-close" aria-label="Close">',d.closeIcon,"</button>",'<div class="'+d.namespace+'-inner">'+d.loading+"</div>","</div>","</div>"].join("")),g="."+d.namespace+"-close"+(d.otherClose?","+d.otherClose:"");return d.$instance=f.clone().addClass(d.variant),d.$instance.on(d.closeTrigger+"."+d.namespace,function(b){if(!b.isDefaultPrevented()){var c=a(b.target);("background"===d.closeOnClick&&c.is("."+d.namespace)||"anywhere"===d.closeOnClick||c.closest(g).length)&&(d.close(b),b.preventDefault())}}),this},getContent:function(){if(this.persist!==!1&&this.$content)return this.$content;var b=this,c=this.constructor.contentFilters,d=function(a){return b.$currentTarget&&b.$currentTarget.attr(a)},e=d(b.targetAttr),f=b.target||e||"",g=c[b.type];if(!g&&f in c&&(g=c[f],f=b.target&&e),f=f||d("href")||"",!g)for(var h in c)b[h]&&(g=c[h],f=b[h]);if(!g){var i=f;if(f=null,a.each(b.contentFilters,function(){return g=c[this],g.test&&(f=g.test(i)),!f&&g.regex&&i.match&&i.match(g.regex)&&(f=i),!f}),!f)return"console"in window&&window.console.error("Featherlight: no content filter found "+(i?' for "'+i+'"':" (no target specified)")),!1}return g.process.call(b,f)},setContent:function(b){return this.$instance.removeClass(this.namespace+"-loading"),this.$instance.toggleClass(this.namespace+"-iframe",b.is("iframe")),this.$instance.find("."+this.namespace+"-inner").not(b).slice(1).remove().end().replaceWith(a.contains(this.$instance[0],b[0])?"":b),this.$content=b.addClass(this.namespace+"-inner"),this},open:function(b){var c=this;if(c.$instance.hide().appendTo(c.root),!(b&&b.isDefaultPrevented()||c.beforeOpen(b)===!1)){b&&b.preventDefault();var d=c.getContent();if(d)return e.push(c),j(!0),c.$instance.fadeIn(c.openSpeed),c.beforeContent(b),a.when(d).always(function(a){c.setContent(a),c.afterContent(b)}).then(c.$instance.promise()).done(function(){c.afterOpen(b)})}return c.$instance.detach(),a.Deferred().reject().promise()},close:function(b){var c=this,d=a.Deferred();return c.beforeClose(b)===!1?d.reject():(0===f(c).length&&j(!1),c.$instance.fadeOut(c.closeSpeed,function(){c.$instance.detach(),c.afterClose(b),d.resolve()})),d.promise()},resize:function(a,b){if(a&&b){this.$content.css("width","").css("height","");var c=Math.max(a/(this.$content.parent().width()-1),b/(this.$content.parent().height()-1));c>1&&(c=b/Math.floor(b/c),this.$content.css("width",""+a/c+"px").css("height",""+b/c+"px"))}},chainCallbacks:function(b){for(var c in b)this[c]=a.proxy(b[c],this,a.proxy(this[c],this))}},a.extend(b,{id:0,autoBind:"[data-featherlight]",defaults:b.prototype,contentFilters:{jquery:{regex:/^[#.]\w/,test:function(b){return b instanceof a&&b},process:function(b){return this.persist!==!1?a(b):a(b).clone(!0)}},image:{regex:/\.(png|jpg|jpeg|gif|tiff?|bmp|svg)(\?\S*)?#x2F;i,process:function(b){var c=this,d=a.Deferred(),e=new Image,f=a('<img src="'+b+'" alt="" class="'+c.namespace+'-image" />');return e.onload=function(){f.naturalWidth=e.width,f.naturalHeight=e.height,d.resolve(f)},e.onerror=function(){d.reject(f)},e.src=b,d.promise()}},html:{regex:/^\s*<[\w!][^<]*>/,process:function(b){return a(b)}},ajax:{regex:/./,process:function(b){var c=a.Deferred(),d=a("<div></div>").load(b,function(a,b){"error"!==b&&c.resolve(d.contents()),c.fail()});return c.promise()}},iframe:{process:function(b){var e=new a.Deferred,f=a("<iframe/>"),h=d(this,"iframe"),i=c(h,g);return f.hide().attr("src",b).attr(i).css(h).on("load",function(){e.resolve(f.show())}).appendTo(this.$instance.find("."+this.namespace+"-content")),e.promise()}},text:{process:function(b){return a("<div>",{text:b})}}},functionAttributes:["beforeOpen","afterOpen","beforeContent","afterContent","beforeClose","afterClose"],readElementConfig:function(b,c){var d=this,e=new RegExp("^data-"+c+"-(.*)"),f={};return b&&b.attributes&&a.each(b.attributes,function(){var b=this.name.match(e);if(b){var c=this.value,g=a.camelCase(b[1]);if(a.inArray(g,d.functionAttributes)>=0)c=new Function(c);else try{c=JSON.parse(c)}catch(h){}f[g]=c}}),f},extend:function(b,c){var d=function(){this.constructor=b};return d.prototype=this.prototype,b.prototype=new d,b.__super__=this.prototype,a.extend(b,this,c),b.defaults=b.prototype,b},attach:function(b,c,d){var e=this;"object"!=typeof c||c instanceof a!=!1||d||(d=c,c=void 0),d=a.extend({},d);var f,g=d.namespace||e.defaults.namespace,h=a.extend({},e.defaults,e.readElementConfig(b[0],g),d),i=function(g){var i=a(g.currentTarget),j=a.extend({$source:b,$currentTarget:i},e.readElementConfig(b[0],h.namespace),e.readElementConfig(g.currentTarget,h.namespace),d),k=f||i.data("featherlight-persisted")||new e(c,j);"shared"===k.persist?f=k:k.persist!==!1&&i.data("featherlight-persisted",k),j.$currentTarget.blur&&j.$currentTarget.blur(),k.open(g)};return b.on(h.openTrigger+"."+h.namespace,h.filter,i),i},current:function(){var a=this.opened();return a[a.length-1]||null},opened:function(){var b=this;return f(),a.grep(e,function(a){return a instanceof b})},close:function(a){var b=this.current();return b?b.close(a):void 0},_onReady:function(){var b=this;b.autoBind&&(a(b.autoBind).each(function(){b.attach(a(this))}),a(document).on("click",b.autoBind,function(c){if(!c.isDefaultPrevented()){var d=b.attach(a(c.currentTarget));d(c)}}))},_callbackChain:{onKeyUp:function(b,c){return 27===c.keyCode?(this.closeOnEsc&&a.featherlight.close(c),!1):b(c)},beforeOpen:function(b,c){return a(document.documentElement).addClass("with-featherlight"),this._previouslyActive=document.activeElement,this._$previouslyTabbable=a("a, input, select, textarea, iframe, button, iframe, [contentEditable=true]").not("[tabindex]").not(this.$instance.find("button")),this._$previouslyWithTabIndex=a("[tabindex]").not('[tabindex="-1"]'),this._previousWithTabIndices=this._$previouslyWithTabIndex.map(function(b,c){return a(c).attr("tabindex")}),this._$previouslyWithTabIndex.add(this._$previouslyTabbable).attr("tabindex",-1),document.activeElement.blur&&document.activeElement.blur(),b(c)},afterClose:function(c,d){var e=c(d),f=this;return this._$previouslyTabbable.removeAttr("tabindex"),this._$previouslyWithTabIndex.each(function(b,c){a(c).attr("tabindex",f._previousWithTabIndices[b])}),this._previouslyActive.focus(),0===b.opened().length&&a(document.documentElement).removeClass("with-featherlight"),e},onResize:function(a,b){return this.resize(this.$content.naturalWidth,this.$content.naturalHeight),a(b)},afterContent:function(a,b){var c=a(b);return this.$instance.find("[autofocus]:not([disabled])").focus(),this.onResize(b),c}}}),a.featherlight=b,a.fn.featherlight=function(a,c){return b.attach(this,a,c),this},a(document).ready(function(){b._onReady()})}(jQuery);
1
+ /**
2
+ * Featherlight - ultra slim jQuery lightbox
3
+ * Version 1.7.13 - http://noelboss.github.io/featherlight/
4
+ *
5
+ * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com)
6
+ * MIT Licensed.
7
+ **/
8
+ !function(a){"use strict";function b(a,c){if(!(this instanceof b)){var d=new b(a,c);return d.open(),d}this.id=b.id++,this.setup(a,c),this.chainCallbacks(b._callbackChain)}function c(a,b){var c={};for(var d in a)d in b&&(c[d]=a[d],delete a[d]);return c}function d(a,b){var c={},d=new RegExp("^"+b+"([A-Z])(.*)");for(var e in a){var f=e.match(d);if(f){var g=(f[1]+f[2].replace(/([A-Z])/g,"-$1")).toLowerCase();c[g]=a[e]}}return c}if("undefined"==typeof a)return void("console"in window&&window.console.info("Too much lightness, Featherlight needs jQuery."));if(a.fn.jquery.match(/-ajax/))return void("console"in window&&window.console.info("Featherlight needs regular jQuery, not the slim version."));var e=[],f=function(b){return e=a.grep(e,function(a){return a!==b&&a.$instance.closest("body").length>0})},g={allow:1,allowfullscreen:1,frameborder:1,height:1,longdesc:1,marginheight:1,marginwidth:1,mozallowfullscreen:1,name:1,referrerpolicy:1,sandbox:1,scrolling:1,src:1,srcdoc:1,style:1,webkitallowfullscreen:1,width:1},h={keyup:"onKeyUp",resize:"onResize"},i=function(c){a.each(b.opened().reverse(),function(){return c.isDefaultPrevented()||!1!==this[h[c.type]](c)?void 0:(c.preventDefault(),c.stopPropagation(),!1)})},j=function(c){if(c!==b._globalHandlerInstalled){b._globalHandlerInstalled=c;var d=a.map(h,function(a,c){return c+"."+b.prototype.namespace}).join(" ");a(window)[c?"on":"off"](d,i)}};b.prototype={constructor:b,namespace:"featherlight",targetAttr:"data-featherlight",variant:null,resetCss:!1,background:null,openTrigger:"click",closeTrigger:"click",filter:null,root:"body",openSpeed:250,closeSpeed:250,closeOnClick:"background",closeOnEsc:!0,closeIcon:"&#10005;",loading:"",persist:!1,otherClose:null,beforeOpen:a.noop,beforeContent:a.noop,beforeClose:a.noop,afterOpen:a.noop,afterContent:a.noop,afterClose:a.noop,onKeyUp:a.noop,onResize:a.noop,type:null,contentFilters:["jquery","image","html","ajax","iframe","text"],setup:function(b,c){"object"!=typeof b||b instanceof a!=!1||c||(c=b,b=void 0);var d=a.extend(this,c,{target:b}),e=d.resetCss?d.namespace+"-reset":d.namespace,f=a(d.background||['<div class="'+e+"-loading "+e+'">','<div class="'+e+'-content">','<button class="'+e+"-close-icon "+d.namespace+'-close" aria-label="Close">',d.closeIcon,"</button>",'<div class="'+d.namespace+'-inner">'+d.loading+"</div>","</div>","</div>"].join("")),g="."+d.namespace+"-close"+(d.otherClose?","+d.otherClose:"");return d.$instance=f.clone().addClass(d.variant),d.$instance.on(d.closeTrigger+"."+d.namespace,function(b){if(!b.isDefaultPrevented()){var c=a(b.target);("background"===d.closeOnClick&&c.is("."+d.namespace)||"anywhere"===d.closeOnClick||c.closest(g).length)&&(d.close(b),b.preventDefault())}}),this},getContent:function(){if(this.persist!==!1&&this.$content)return this.$content;var b=this,c=this.constructor.contentFilters,d=function(a){return b.$currentTarget&&b.$currentTarget.attr(a)},e=d(b.targetAttr),f=b.target||e||"",g=c[b.type];if(!g&&f in c&&(g=c[f],f=b.target&&e),f=f||d("href")||"",!g)for(var h in c)b[h]&&(g=c[h],f=b[h]);if(!g){var i=f;if(f=null,a.each(b.contentFilters,function(){return g=c[this],g.test&&(f=g.test(i)),!f&&g.regex&&i.match&&i.match(g.regex)&&(f=i),!f}),!f)return"console"in window&&window.console.error("Featherlight: no content filter found "+(i?' for "'+i+'"':" (no target specified)")),!1}return g.process.call(b,f)},setContent:function(b){return this.$instance.removeClass(this.namespace+"-loading"),this.$instance.toggleClass(this.namespace+"-iframe",b.is("iframe")),this.$instance.find("."+this.namespace+"-inner").not(b).slice(1).remove().end().replaceWith(a.contains(this.$instance[0],b[0])?"":b),this.$content=b.addClass(this.namespace+"-inner"),this},open:function(b){var c=this;if(c.$instance.hide().appendTo(c.root),!(b&&b.isDefaultPrevented()||c.beforeOpen(b)===!1)){b&&b.preventDefault();var d=c.getContent();if(d)return e.push(c),j(!0),c.$instance.fadeIn(c.openSpeed),c.beforeContent(b),a.when(d).always(function(a){c.setContent(a),c.afterContent(b)}).then(c.$instance.promise()).done(function(){c.afterOpen(b)})}return c.$instance.detach(),a.Deferred().reject().promise()},close:function(b){var c=this,d=a.Deferred();return c.beforeClose(b)===!1?d.reject():(0===f(c).length&&j(!1),c.$instance.fadeOut(c.closeSpeed,function(){c.$instance.detach(),c.afterClose(b),d.resolve()})),d.promise()},resize:function(a,b){if(a&&b){this.$content.css("width","").css("height","");var c=Math.max(a/(this.$content.parent().width()-1),b/(this.$content.parent().height()-1));c>1&&(c=b/Math.floor(b/c),this.$content.css("width",""+a/c+"px").css("height",""+b/c+"px"))}},chainCallbacks:function(b){for(var c in b)this[c]=a.proxy(b[c],this,a.proxy(this[c],this))}},a.extend(b,{id:0,autoBind:"[data-featherlight]",defaults:b.prototype,contentFilters:{jquery:{regex:/^[#.]\w/,test:function(b){return b instanceof a&&b},process:function(b){return this.persist!==!1?a(b):a(b).clone(!0)}},image:{regex:/\.(png|jpg|jpeg|gif|tiff?|bmp|svg)(\?\S*)?#x2F;i,process:function(b){var c=this,d=a.Deferred(),e=new Image,f=a('<img src="'+b+'" alt="" class="'+c.namespace+'-image" />');return e.onload=function(){f.naturalWidth=e.width,f.naturalHeight=e.height,d.resolve(f)},e.onerror=function(){d.reject(f)},e.src=b,d.promise()}},html:{regex:/^\s*<[\w!][^<]*>/,process:function(b){return a(b)}},ajax:{regex:/./,process:function(b){var c=a.Deferred(),d=a("<div></div>").load(b,function(a,b){"error"!==b&&c.resolve(d.contents()),c.fail()});return c.promise()}},iframe:{process:function(b){var e=new a.Deferred,f=a("<iframe/>"),h=d(this,"iframe"),i=c(h,g);return f.hide().attr("src",b).attr(i).css(h).on("load",function(){e.resolve(f.show())}).appendTo(this.$instance.find("."+this.namespace+"-content")),e.promise()}},text:{process:function(b){return a("<div>",{text:b})}}},functionAttributes:["beforeOpen","afterOpen","beforeContent","afterContent","beforeClose","afterClose"],readElementConfig:function(b,c){var d=this,e=new RegExp("^data-"+c+"-(.*)"),f={};return b&&b.attributes&&a.each(b.attributes,function(){var b=this.name.match(e);if(b){var c=this.value,g=a.camelCase(b[1]);if(a.inArray(g,d.functionAttributes)>=0)c=new Function(c);else try{c=JSON.parse(c)}catch(h){}f[g]=c}}),f},extend:function(b,c){var d=function(){this.constructor=b};return d.prototype=this.prototype,b.prototype=new d,b.__super__=this.prototype,a.extend(b,this,c),b.defaults=b.prototype,b},attach:function(b,c,d){var e=this;"object"!=typeof c||c instanceof a!=!1||d||(d=c,c=void 0),d=a.extend({},d);var f,g=d.namespace||e.defaults.namespace,h=a.extend({},e.defaults,e.readElementConfig(b[0],g),d),i=function(g){var i=a(g.currentTarget),j=a.extend({$source:b,$currentTarget:i},e.readElementConfig(b[0],h.namespace),e.readElementConfig(g.currentTarget,h.namespace),d),k=f||i.data("featherlight-persisted")||new e(c,j);"shared"===k.persist?f=k:k.persist!==!1&&i.data("featherlight-persisted",k),j.$currentTarget.blur&&j.$currentTarget.blur(),k.open(g)};return b.on(h.openTrigger+"."+h.namespace,h.filter,i),{filter:h.filter,handler:i}},current:function(){var a=this.opened();return a[a.length-1]||null},opened:function(){var b=this;return f(),a.grep(e,function(a){return a instanceof b})},close:function(a){var b=this.current();return b?b.close(a):void 0},_onReady:function(){var b=this;if(b.autoBind){var c=a(b.autoBind);c.each(function(){b.attach(a(this))}),a(document).on("click",b.autoBind,function(d){if(!d.isDefaultPrevented()){var e=a(d.currentTarget),f=c.length;if(c=c.add(e),f!==c.length){var g=b.attach(e);(!g.filter||a(d.target).parentsUntil(e,g.filter).length>0)&&g.handler(d)}}})}},_callbackChain:{onKeyUp:function(b,c){return 27===c.keyCode?(this.closeOnEsc&&a.featherlight.close(c),!1):b(c)},beforeOpen:function(b,c){return a(document.documentElement).addClass("with-featherlight"),this._previouslyActive=document.activeElement,this._$previouslyTabbable=a("a, input, select, textarea, iframe, button, iframe, [contentEditable=true]").not("[tabindex]").not(this.$instance.find("button")),this._$previouslyWithTabIndex=a("[tabindex]").not('[tabindex="-1"]'),this._previousWithTabIndices=this._$previouslyWithTabIndex.map(function(b,c){return a(c).attr("tabindex")}),this._$previouslyWithTabIndex.add(this._$previouslyTabbable).attr("tabindex",-1),document.activeElement.blur&&document.activeElement.blur(),b(c)},afterClose:function(c,d){var e=c(d),f=this;return this._$previouslyTabbable.removeAttr("tabindex"),this._$previouslyWithTabIndex.each(function(b,c){a(c).attr("tabindex",f._previousWithTabIndices[b])}),this._previouslyActive.focus(),0===b.opened().length&&a(document.documentElement).removeClass("with-featherlight"),e},onResize:function(a,b){return this.resize(this.$content.naturalWidth,this.$content.naturalHeight),a(b)},afterContent:function(a,b){var c=a(b);return this.$instance.find("[autofocus]:not([disabled])").focus(),this.onResize(b),c}}}),a.featherlight=b,a.fn.featherlight=function(a,c){return b.attach(this,a,c),this},a(document).ready(function(){b._onReady()})}(jQuery);
assets/imagelightbox/css/imagelightbox.css CHANGED
@@ -1,6 +1,8 @@
1
- #imagelightbox {
2
- position: fixed;
3
- z-index: 9999;
4
- -ms-touch-action: none;
5
- touch-action: none;
6
}
1
+ #imagelightbox
2
+ {
3
+ position: fixed;
4
+ z-index: 9999;
5
+
6
+ -ms-touch-action: none;
7
+ touch-action: none;
8
}
assets/imagelightbox/css/imagelightbox.min.css DELETED
@@ -1 +0,0 @@
1
- #imagelightbox{position:fixed;z-index:9999;-ms-touch-action:none;touch-action:none}
assets/imagelightbox/js/imagelightbox.js DELETED
@@ -1,315 +0,0 @@
1
-
2
- /*
3
- By Osvaldas Valutis, www.osvaldas.info
4
- Available for use under the MIT License
5
- */
6
-
7
- ;( function( $, window, document, undefined )
8
- {
9
- 'use strict';
10
-
11
- var cssTransitionSupport = function()
12
- {
13
- var s = document.body || document.documentElement, s = s.style;
14
- if( s.WebkitTransition == '' ) return '-webkit-';
15
- if( s.MozTransition == '' ) return '-moz-';
16
- if( s.OTransition == '' ) return '-o-';
17
- if( s.transition == '' ) return '';
18
- return false;
19
- },
20
-
21
- isCssTransitionSupport = cssTransitionSupport() === false ? false : true,
22
-
23
- cssTransitionTranslateX = function( element, positionX, speed )
24
- {
25
- var options = {}, prefix = cssTransitionSupport();
26
- options[ prefix + 'transform' ] = 'translateX(' + positionX + ')';
27
- options[ prefix + 'transition' ] = prefix + 'transform ' + speed + 's linear';
28
- element.css( options );
29
- },
30
-
31
- hasTouch = ( 'ontouchstart' in window ),
32
- hasPointers = window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
33
- wasTouched = function( event )
34
- {
35
- if( hasTouch )
36
- return true;
37
-
38
- if( !hasPointers || typeof event === 'undefined' || typeof event.pointerType === 'undefined' )
39
- return false;
40
-
41
- if( typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined' )
42
- {
43
- if( event.MSPOINTER_TYPE_MOUSE != event.pointerType )
44
- return true;
45
- }
46
- else
47
- if( event.pointerType != 'mouse' )
48
- return true;
49
-
50
- return false;
51
- };
52
-
53
- $.fn.imageLightbox = function( options )
54
- {
55
- var options = $.extend(
56
- {
57
- selector: 'id="imagelightbox"',
58
- animationSpeed: 250,
59
- preloadNext: true,
60
- enableKeyboard: true,
61
- quitOnEnd: false,
62
- quitOnImgClick: false,
63
- quitOnDocClick: true,
64
- onStart: false,
65
- onEnd: false,
66
- onLoadStart: false,
67
- onLoadEnd: false
68
- },
69
- options ),
70
-
71
- targets = $([]),
72
- target = $(),
73
- image = $(),
74
- imageWidth = 0,
75
- imageHeight = 0,
76
- swipeDiff = 0,
77
- inProgress = false,
78
-
79
- setImage = function()
80
- {
81
- if( !image.length ) return true;
82
-
83
- var screenWidth = $( window ).width() * 0.8,
84
- screenHeight = $( window ).height() * 0.9,
85
- tmpImage = new Image();
86
-
87
- tmpImage.src = image.attr( 'src' );
88
- tmpImage.onload = function()
89
- {
90
- imageWidth = tmpImage.width;
91
- imageHeight = tmpImage.height;
92
-
93
- if( imageWidth > screenWidth || imageHeight > screenHeight )
94
- {
95
- var ratio = imageWidth / imageHeight > screenWidth / screenHeight ? imageWidth / screenWidth : imageHeight / screenHeight;
96
- imageWidth /= ratio;
97
- imageHeight /= ratio;
98
- }
99
-
100
- image.css(
101
- {
102
- 'width': imageWidth + 'px',
103
- 'height': imageHeight + 'px',
104
- 'top': ( $( window ).height() - imageHeight ) / 2 + 'px',
105
- 'left': ( $( window ).width() - imageWidth ) / 2 + 'px'
106
- });
107
- };
108
- },
109
-
110
- loadImage = function( direction )
111
- {
112
- if( inProgress ) return false;
113
-
114
- direction = typeof direction === 'undefined' ? false : direction == 'left' ? 1 : -1;
115
-
116
- if( image.length )
117
- {
118
- if( direction !== false && ( targets.length < 2 || ( options.quitOnEnd === true && ( ( direction === -1 && targets.index( target ) == 0 ) || ( direction === 1 && targets.index( target ) == targets.length - 1 ) ) ) ) )
119
- {
120
- quitLightbox();
121
- return false;
122
- }
123
- var params = { 'opacity': 0 };
124
- if( isCssTransitionSupport ) cssTransitionTranslateX( image, ( 100 * direction ) - swipeDiff + 'px', options.animationSpeed / 1000 );
125
- else params.left = parseInt( image.css( 'left' ) ) + 100 * direction + 'px';
126
- image.animate( params, options.animationSpeed, function(){ removeImage(); });
127
- swipeDiff = 0;
128
- }
129
-
130
- inProgress = true;
131
- if( options.onLoadStart !== false ) options.onLoadStart();
132
-
133
- setTimeout( function()
134
- {
135
- image = $( '<img ' + options.selector + ' />' )
136
- .attr( 'src', target.attr( 'href' ) )
137
- .on( 'load', function()
138
- {
139
- image.appendTo( 'body' );
140
- setImage();
141
-
142
- var params = { 'opacity': 1 };
143
-
144
- image.css( 'opacity', 0 );
145
- if( isCssTransitionSupport )
146
- {
147
- cssTransitionTranslateX( image, -100 * direction + 'px', 0 );
148
- setTimeout( function(){ cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ) }, 50 );
149
- }
150
- else
151
- {
152
- var imagePosLeft = parseInt( image.css( 'left' ) );
153
- params.left = imagePosLeft + 'px';
154
- image.css( 'left', imagePosLeft - 100 * direction + 'px' );
155
- }
156
-
157
- image.animate( params, options.animationSpeed, function()
158
- {
159
- inProgress = false;
160
- if( options.onLoadEnd !== false ) options.onLoadEnd();
161
- });
162
- if( options.preloadNext )
163
- {
164
- var nextTarget = targets.eq( targets.index( target ) + 1 );
165
- if( !nextTarget.length ) nextTarget = targets.eq( 0 );
166
- $( '<img />' ).attr( 'src', nextTarget.attr( 'href' ) );
167
- }
168
- })
169
- .on( 'error', function()
170
- {
171
- if( options.onLoadEnd !== false ) options.onLoadEnd();
172
- });
173
-
174
- var swipeStart = 0,
175
- swipeEnd = 0,
176
- imagePosLeft = 0;
177
-
178
- image.on( hasPointers ? 'pointerup MSPointerUp' : 'click', function( e )
179
- {
180
- e.preventDefault();
181
- if( options.quitOnImgClick )
182
- {
183
- quitLightbox();
184
- return false;
185
- }
186
- if( wasTouched( e.originalEvent ) ) return true;
187
- var posX = ( e.pageX || e.originalEvent.pageX ) - e.target.offsetLeft;
188
- target = targets.eq( targets.index( target ) - ( imageWidth / 2 > posX ? 1 : -1 ) );
189
- if( !target.length ) target = targets.eq( imageWidth / 2 > posX ? targets.length : 0 );
190
- loadImage( imageWidth / 2 > posX ? 'left' : 'right' );
191
- })
192
- .on( 'touchstart pointerdown MSPointerDown', function( e )
193
- {
194
- if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true;
195
- if( isCssTransitionSupport ) imagePosLeft = parseInt( image.css( 'left' ) );
196
- swipeStart = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX;
197
- })
198
- .on( 'touchmove pointermove MSPointerMove', function( e )
199
- {
200
- if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true;
201
- e.preventDefault();
202
- swipeEnd = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX;
203
- swipeDiff = swipeStart - swipeEnd;
204
- if( isCssTransitionSupport ) cssTransitionTranslateX( image, -swipeDiff + 'px', 0 );
205
- else image.css( 'left', imagePosLeft - swipeDiff + 'px' );
206
- })
207
- .on( 'touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel', function( e )
208
- {
209
- if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true;
210
- if( Math.abs( swipeDiff ) > 50 )
211
- {
212
- target = targets.eq( targets.index( target ) - ( swipeDiff < 0 ? 1 : -1 ) );
213
- if( !target.length ) target = targets.eq( swipeDiff < 0 ? targets.length : 0 );
214
- loadImage( swipeDiff > 0 ? 'right' : 'left' );
215
- }
216
- else
217
- {
218
- if( isCssTransitionSupport ) cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 );
219
- else image.animate({ 'left': imagePosLeft + 'px' }, options.animationSpeed / 2 );
220
- }
221
- });
222
-
223
- }, options.animationSpeed + 100 );
224
- },
225
-
226
- removeImage = function()
227
- {
228
- if( !image.length ) return false;
229
- image.remove();
230
- image = $();
231
- },
232
-
233
- quitLightbox = function()
234
- {
235
- if( !image.length ) return false;
236
- image.animate({ 'opacity': 0 }, options.animationSpeed, function()
237
- {
238
- removeImage();
239
- inProgress = false;
240
- if( options.onEnd !== false ) options.onEnd();
241
- });
242
- },
243
-
244
- addTargets = function( newTargets )
245
- {
246
- newTargets.each( function()
247
- {
248
- targets = targets.add( $( this ) );
249
- });
250
-
251
- newTargets.on( 'click.imageLightbox', function( e )
252
- {
253
- e.preventDefault();
254
- if( inProgress ) return false;
255
- inProgress = false;
256
- if( options.onStart !== false ) options.onStart();
257
- target = $( this );
258
- loadImage();
259
- });
260
- };
261
-
262
- $( window ).on( 'resize', setImage );
263
-
264
- if( options.quitOnDocClick )
265
- {
266
- $( document ).on( hasTouch ? 'touchend' : 'click', function( e )
267
- {
268
- if( image.length && !$( e.target ).is( image ) ) quitLightbox();
269
- });
270
- }
271
-
272
- if( options.enableKeyboard )
273
- {
274
- $( document ).on( 'keyup', function( e )
275
- {
276
- if( !image.length ) return true;
277
- e.preventDefault();
278
- if( e.keyCode == 27 ) quitLightbox();
279
- if( e.keyCode == 37 || e.keyCode == 39 )
280
- {
281
- target = targets.eq( targets.index( target ) - ( e.keyCode == 37 ? 1 : -1 ) );
282
- if( !target.length ) target = targets.eq( e.keyCode == 37 ? targets.length : 0 );
283
- loadImage( e.keyCode == 37 ? 'left' : 'right' );
284
- }
285
- });
286
- }
287
-
288
- addTargets( $( this ) );
289
-
290
- this.switchImageLightbox = function( index )
291
- {
292
- var tmpTarget = targets.eq( index );
293
- if( tmpTarget.length )
294
- {
295
- var currentIndex = targets.index( target );
296
- target = tmpTarget;
297
- loadImage( index < currentIndex ? 'left' : 'right' );
298
- }
299
- return this;
300
- };
301
-
302
- this.addToImageLightbox = function( newTargets )
303
- {
304
- addTargets( newTargets );
305
- };
306
-
307
- this.quitImageLightbox = function()
308
- {
309
- quitLightbox();
310
- return this;
311
- };
312
-
313
- return this;
314
- };
315
- })( jQuery, window, document );