blacklight-gallery 6.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env +2 -0
- data/.github/workflows/ruby.yml +10 -26
- data/Gemfile +5 -12
- data/README.md +3 -5
- data/Rakefile +53 -32
- data/app/assets/config/blacklight_gallery/manifest.js +0 -1
- data/app/assets/javascripts/blacklight_gallery/blacklight-gallery.esm.js +959 -484
- data/app/assets/javascripts/blacklight_gallery/blacklight-gallery.esm.js.map +1 -1
- data/app/assets/javascripts/blacklight_gallery/blacklight-gallery.js +959 -484
- data/app/assets/javascripts/blacklight_gallery/blacklight-gallery.js.map +1 -1
- data/app/assets/stylesheets/blacklight_gallery/masonry.css +9 -3
- data/app/assets/stylesheets/blacklight_gallery/slideshow.css +2 -13
- data/app/components/blacklight/gallery/document_component.html.erb +1 -5
- data/app/components/blacklight/gallery/document_component.rb +0 -4
- data/app/components/blacklight/gallery/openseadragon_embed_component.rb +4 -5
- data/app/components/blacklight/gallery/slideshow_component.html.erb +1 -1
- data/app/components/blacklight/gallery/slideshow_component.rb +3 -6
- data/app/{views/catalog/_slideshow_modal.html.erb → components/blacklight/gallery/slideshow_modal_component.html.erb} +2 -3
- data/app/components/blacklight/gallery/slideshow_modal_component.rb +6 -0
- data/app/components/blacklight/gallery/slideshow_presenter_component.html.erb +14 -0
- data/app/components/blacklight/gallery/slideshow_presenter_component.rb +17 -0
- data/app/components/blacklight/gallery/slideshow_preview_component.html.erb +1 -5
- data/app/components/blacklight/gallery/slideshow_preview_component.rb +0 -13
- data/app/javascript/blacklight-gallery/grid-lanes-polyfill.js +1067 -0
- data/app/javascript/blacklight-gallery/index.js +18 -4
- data/app/views/catalog/_document_gallery.html.erb +1 -1
- data/app/views/catalog/_document_masonry.html.erb +1 -1
- data/app/views/catalog/_document_slideshow.html.erb +5 -25
- data/app/views/catalog/_openseadragon_default.html.erb +1 -1
- data/blacklight-gallery.gemspec +19 -20
- data/compose.yaml +18 -0
- data/config/importmap.rb +0 -1
- data/config/locales/blacklight-gallery.ar.yml +0 -3
- data/config/locales/blacklight-gallery.de.yml +3 -0
- data/config/locales/blacklight-gallery.en.yml +0 -3
- data/config/locales/blacklight-gallery.es.yml +3 -3
- data/config/locales/blacklight-gallery.fr.yml +3 -3
- data/config/locales/blacklight-gallery.it.yml +3 -3
- data/config/locales/blacklight-gallery.pt-BR.yml +3 -3
- data/config/locales/blacklight-gallery.zh.yml +3 -3
- data/lib/blacklight/gallery/version.rb +1 -1
- data/lib/generators/blacklight_gallery/install_generator.rb +15 -29
- data/package.json +2 -4
- data/rollup.config.js +13 -16
- data/spec/components/blacklight/gallery/document_component_spec.rb +2 -10
- data/spec/components/blacklight/gallery/openseadragon_embed_component_spec.rb +1 -6
- data/spec/components/blacklight/gallery/slideshow_component_spec.rb +28 -25
- data/spec/components/blacklight/gallery/slideshow_preview_component_spec.rb +3 -12
- data/spec/features/slideshow_spec.rb +23 -1
- data/spec/views/catalog/_document_slideshow.html.erb_spec.rb +6 -10
- metadata +49 -53
- data/app/components/blacklight/gallery/icons/pause_slideshow_component.rb +0 -18
- data/app/components/blacklight/gallery/icons/start_slideshow_component.rb +0 -18
- data/app/javascript/blacklight-gallery/masonry.js +0 -12
- data/app/javascript/blacklight-gallery/slideshow.js +0 -122
- data/vendor/assets/javascripts/imagesloaded.pkgd.js +0 -441
- data/vendor/assets/javascripts/masonry.min.js +0 -9
|
@@ -1,587 +1,1062 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* imagesLoaded PACKAGED v5.0.0
|
|
3
|
-
* JavaScript is all like "You images are done yet or what?"
|
|
4
|
-
* MIT License
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
1
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
2
|
+
* CSS Grid Lanes Polyfill
|
|
3
|
+
*
|
|
4
|
+
* Polyfills the new `display: grid-lanes` CSS feature for browsers
|
|
5
|
+
* that don't support it natively. Based on the WebKit implementation
|
|
6
|
+
* described at: https://webkit.org/blog/17660/introducing-css-grid-lanes/
|
|
7
|
+
*
|
|
8
|
+
* Features supported:
|
|
9
|
+
* - display: grid-lanes
|
|
10
|
+
* - grid-template-columns / grid-template-rows for lane definition
|
|
11
|
+
* - gap, column-gap, row-gap
|
|
12
|
+
* - --flow-tolerance for placement sensitivity
|
|
13
|
+
* - Spanning items (grid-column: span N)
|
|
14
|
+
* - Explicit placement (grid-column: N / M)
|
|
15
|
+
* - Responsive auto-fill/auto-fit with minmax()
|
|
16
|
+
* - Both waterfall (columns) and brick (rows) layouts
|
|
17
|
+
*
|
|
18
|
+
* Features that do not work:
|
|
19
|
+
* - fr units with grid-template-rows
|
|
20
|
+
*
|
|
21
|
+
* @version 1.0.0
|
|
22
|
+
* @author Simon Willison
|
|
23
|
+
* @author ninjamar
|
|
24
|
+
* @license MIT
|
|
11
25
|
*/
|
|
12
26
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// CommonJS - Browserify, Webpack
|
|
17
|
-
module.exports = factory();
|
|
18
|
-
} else {
|
|
19
|
-
// Browser globals
|
|
20
|
-
global.EvEmitter = factory();
|
|
21
|
-
}
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// CONSTANTS & STATE
|
|
29
|
+
// ============================================================================
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
const POLYFILL_NAME = "GridLanesPolyfill";
|
|
32
|
+
const POLYFILL_ATTR = "data-grid-lanes-polyfilled";
|
|
33
|
+
const DEFAULT_TOLERANCE = 16; // ~1em in pixels
|
|
24
34
|
|
|
25
|
-
|
|
35
|
+
// Cache computed styles to reduce redundant calls
|
|
36
|
+
let styleMap = new WeakMap(); // Not const because map has no clear meaning it has to be initialized later
|
|
26
37
|
|
|
27
|
-
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// FEATURE DETECTION
|
|
40
|
+
// ============================================================================
|
|
28
41
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
let listeners = events[ eventName ] = events[ eventName ] || [];
|
|
36
|
-
// only add once
|
|
37
|
-
if ( !listeners.includes( listener ) ) {
|
|
38
|
-
listeners.push( listener );
|
|
42
|
+
/**
|
|
43
|
+
* Check if the browser natively supports display: grid-lanes
|
|
44
|
+
*/
|
|
45
|
+
function supportsGridLanes() {
|
|
46
|
+
if (typeof CSS === "undefined" || !CSS.supports) {
|
|
47
|
+
return false
|
|
39
48
|
}
|
|
49
|
+
return CSS.supports("display", "grid-lanes")
|
|
50
|
+
}
|
|
40
51
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
proto.once = function( eventName, listener ) {
|
|
45
|
-
if ( !eventName || !listener ) return this;
|
|
46
|
-
|
|
47
|
-
// add event
|
|
48
|
-
this.on( eventName, listener );
|
|
49
|
-
// set once flag
|
|
50
|
-
// set onceEvents hash
|
|
51
|
-
let onceEvents = this._onceEvents = this._onceEvents || {};
|
|
52
|
-
// set onceListeners object
|
|
53
|
-
let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
|
|
54
|
-
// set flag
|
|
55
|
-
onceListeners[ listener ] = true;
|
|
56
|
-
|
|
57
|
-
return this;
|
|
58
|
-
};
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// PARSING UTILITIES
|
|
54
|
+
// ============================================================================
|
|
59
55
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Parse a CSS length value to pixels
|
|
58
|
+
*/
|
|
59
|
+
function parseLengthToPixels(
|
|
60
|
+
value,
|
|
61
|
+
containerSize,
|
|
62
|
+
fontSize = 16,
|
|
63
|
+
rootFontSize = 16
|
|
64
|
+
) {
|
|
65
|
+
if (!value || value === "auto" || value === "none") return null
|
|
66
|
+
|
|
67
|
+
const num = parseFloat(value);
|
|
68
|
+
if (isNaN(num)) return null
|
|
69
|
+
|
|
70
|
+
if (value.endsWith("px")) return num
|
|
71
|
+
if (value.endsWith("rem")) return num * rootFontSize
|
|
72
|
+
if (value.endsWith("em")) return num * fontSize
|
|
73
|
+
if (value.endsWith("ch")) return num * fontSize * 0.5 // Approximate
|
|
74
|
+
if (value.endsWith("lh")) return num * fontSize * 1.2 // Approximate line-height
|
|
75
|
+
if (value.endsWith("%")) return (num / 100) * containerSize
|
|
76
|
+
if (value.endsWith("vw")) return (num / 100) * window.innerWidth
|
|
77
|
+
if (value.endsWith("vh")) return (num / 100) * window.innerHeight
|
|
78
|
+
if (value.endsWith("vmin"))
|
|
79
|
+
return (num / 100) * Math.min(window.innerWidth, window.innerHeight)
|
|
80
|
+
if (value.endsWith("vmax"))
|
|
81
|
+
return (num / 100) * Math.max(window.innerWidth, window.innerHeight)
|
|
82
|
+
if (value.endsWith("fr")) return null // Handled separately
|
|
83
|
+
|
|
84
|
+
// Unitless number treated as pixels
|
|
85
|
+
if (!isNaN(num) && value === String(num)) return num
|
|
86
|
+
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
63
89
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Parse minmax() function
|
|
92
|
+
*/
|
|
93
|
+
function parseMinMax(value) {
|
|
94
|
+
const match = value.match(/minmax\(\s*([^,]+)\s*,\s*([^)]+)\s*\)/);
|
|
95
|
+
if (!match) return null
|
|
96
|
+
return {
|
|
97
|
+
min: match[1].trim(),
|
|
98
|
+
max: match[2].trim()
|
|
67
99
|
}
|
|
100
|
+
}
|
|
68
101
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
args = args || [];
|
|
79
|
-
// once stuff
|
|
80
|
-
let onceListeners = this._onceEvents && this._onceEvents[ eventName ];
|
|
81
|
-
|
|
82
|
-
for ( let listener of listeners ) {
|
|
83
|
-
let isOnce = onceListeners && onceListeners[ listener ];
|
|
84
|
-
if ( isOnce ) {
|
|
85
|
-
// remove listener
|
|
86
|
-
// remove before trigger to prevent recursion
|
|
87
|
-
this.off( eventName, listener );
|
|
88
|
-
// unset once flag
|
|
89
|
-
delete onceListeners[ listener ];
|
|
90
|
-
}
|
|
91
|
-
// trigger listener
|
|
92
|
-
listener.apply( this, args );
|
|
102
|
+
/**
|
|
103
|
+
* Parse repeat() function
|
|
104
|
+
*/
|
|
105
|
+
function parseRepeat(value) {
|
|
106
|
+
const match = value.match(/repeat\(\s*([^,]+)\s*,\s*(.+)\s*\)/);
|
|
107
|
+
if (!match) return null
|
|
108
|
+
return {
|
|
109
|
+
count: match[1].trim(),
|
|
110
|
+
pattern: match[2].trim()
|
|
93
111
|
}
|
|
112
|
+
}
|
|
94
113
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
proto.allOff = function() {
|
|
99
|
-
delete this._events;
|
|
100
|
-
delete this._onceEvents;
|
|
101
|
-
return this;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
return EvEmitter;
|
|
105
|
-
|
|
106
|
-
} ) );
|
|
107
|
-
/*!
|
|
108
|
-
* imagesLoaded v5.0.0
|
|
109
|
-
* JavaScript is all like "You images are done yet or what?"
|
|
110
|
-
* MIT License
|
|
114
|
+
/**
|
|
115
|
+
* Tokenize a grid template string
|
|
111
116
|
*/
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
function tokenizeTemplate(template) {
|
|
118
|
+
const tokens = [];
|
|
119
|
+
let current = "";
|
|
120
|
+
let parenDepth = 0;
|
|
121
|
+
|
|
122
|
+
for (let i = 0; i < template.length; i++) {
|
|
123
|
+
const char = template[i];
|
|
124
|
+
|
|
125
|
+
if (char === "(") {
|
|
126
|
+
parenDepth++;
|
|
127
|
+
current += char;
|
|
128
|
+
} else if (char === ")") {
|
|
129
|
+
parenDepth--;
|
|
130
|
+
current += char;
|
|
131
|
+
} else if (char === " " && parenDepth === 0) {
|
|
132
|
+
if (current.trim()) {
|
|
133
|
+
tokens.push(current.trim());
|
|
134
|
+
}
|
|
135
|
+
current = "";
|
|
136
|
+
} else {
|
|
137
|
+
current += char;
|
|
138
|
+
}
|
|
121
139
|
}
|
|
122
140
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
let $ = window.jQuery;
|
|
127
|
-
let console = window.console;
|
|
128
|
-
|
|
129
|
-
// -------------------------- helpers -------------------------- //
|
|
130
|
-
|
|
131
|
-
// turn element or nodeList into an array
|
|
132
|
-
function makeArray( obj ) {
|
|
133
|
-
// use object if already an array
|
|
134
|
-
if ( Array.isArray( obj ) ) return obj;
|
|
135
|
-
|
|
136
|
-
let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
|
|
137
|
-
// convert nodeList to array
|
|
138
|
-
if ( isArrayLike ) return [ ...obj ];
|
|
141
|
+
if (current.trim()) {
|
|
142
|
+
tokens.push(current.trim());
|
|
143
|
+
}
|
|
139
144
|
|
|
140
|
-
|
|
141
|
-
return [ obj ];
|
|
145
|
+
return tokens
|
|
142
146
|
}
|
|
143
147
|
|
|
144
|
-
// -------------------------- imagesLoaded -------------------------- //
|
|
145
|
-
|
|
146
148
|
/**
|
|
147
|
-
*
|
|
148
|
-
* @param {[Object, Function]} options - if function, use as callback
|
|
149
|
-
* @param {Function} onAlways - callback function
|
|
150
|
-
* @returns {ImagesLoaded}
|
|
149
|
+
* Calculate lane sizes from grid-template-columns/rows
|
|
151
150
|
*/
|
|
152
|
-
function
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
// bail if bad element
|
|
163
|
-
if ( !queryElem ) {
|
|
164
|
-
console.error(`Bad element for imagesLoaded ${queryElem || elem}`);
|
|
165
|
-
return;
|
|
151
|
+
function calculateLaneSizes(
|
|
152
|
+
template,
|
|
153
|
+
containerSize,
|
|
154
|
+
gap,
|
|
155
|
+
fontSize,
|
|
156
|
+
rootFontSize
|
|
157
|
+
) {
|
|
158
|
+
if (!template || template === "none" || template === "auto") {
|
|
159
|
+
return null
|
|
166
160
|
}
|
|
167
161
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
162
|
+
const availableSpace = containerSize;
|
|
163
|
+
let lanes = [];
|
|
164
|
+
let totalFr = 0;
|
|
165
|
+
let fixedSpace = 0;
|
|
166
|
+
|
|
167
|
+
// Parse the template
|
|
168
|
+
const tokens = tokenizeTemplate(template);
|
|
169
|
+
|
|
170
|
+
for (const token of tokens) {
|
|
171
|
+
// Handle repeat()
|
|
172
|
+
const repeatInfo = parseRepeat(token);
|
|
173
|
+
if (repeatInfo) {
|
|
174
|
+
const { count, pattern } = repeatInfo;
|
|
175
|
+
const patternTokens = tokenizeTemplate(pattern);
|
|
176
|
+
|
|
177
|
+
if (count === "auto-fill" || count === "auto-fit") {
|
|
178
|
+
// Calculate how many repetitions fit
|
|
179
|
+
let minSize = 0;
|
|
180
|
+
|
|
181
|
+
for (const pt of patternTokens) {
|
|
182
|
+
const minmax = parseMinMax(pt);
|
|
183
|
+
if (minmax) {
|
|
184
|
+
const minVal = parseLengthToPixels(
|
|
185
|
+
minmax.min,
|
|
186
|
+
containerSize,
|
|
187
|
+
fontSize,
|
|
188
|
+
rootFontSize
|
|
189
|
+
);
|
|
190
|
+
if (minmax.min === "max-content" || minmax.min === "min-content") {
|
|
191
|
+
minSize += 100; // Fallback estimate
|
|
192
|
+
} else if (minVal !== null) {
|
|
193
|
+
minSize += minVal;
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
const size = parseLengthToPixels(
|
|
197
|
+
pt,
|
|
198
|
+
containerSize,
|
|
199
|
+
fontSize,
|
|
200
|
+
rootFontSize
|
|
201
|
+
);
|
|
202
|
+
if (size !== null) {
|
|
203
|
+
minSize += size;
|
|
204
|
+
} else if (pt.endsWith("fr")) {
|
|
205
|
+
minSize += 100; // Minimum fallback for fr units
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Calculate repetitions
|
|
211
|
+
const patternCount = patternTokens.length;
|
|
212
|
+
const gapCount = patternCount - 1;
|
|
213
|
+
const minPatternSize = minSize + gapCount * gap;
|
|
214
|
+
|
|
215
|
+
let reps = Math.max(
|
|
216
|
+
1,
|
|
217
|
+
Math.floor((availableSpace + gap) / (minPatternSize + gap))
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// Expand pattern
|
|
221
|
+
for (let i = 0; i < reps; i++) {
|
|
222
|
+
for (const pt of patternTokens) {
|
|
223
|
+
const minmax = parseMinMax(pt);
|
|
224
|
+
if (minmax) {
|
|
225
|
+
const minVal = parseLengthToPixels(
|
|
226
|
+
minmax.min,
|
|
227
|
+
containerSize,
|
|
228
|
+
fontSize,
|
|
229
|
+
rootFontSize
|
|
230
|
+
);
|
|
231
|
+
const maxVal = minmax.max.endsWith("fr")
|
|
232
|
+
? { fr: parseFloat(minmax.max) }
|
|
233
|
+
: parseLengthToPixels(
|
|
234
|
+
minmax.max,
|
|
235
|
+
containerSize,
|
|
236
|
+
fontSize,
|
|
237
|
+
rootFontSize
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
lanes.push({
|
|
241
|
+
min: minVal || 0,
|
|
242
|
+
max: maxVal,
|
|
243
|
+
size: 0
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
if (typeof maxVal === "object" && maxVal.fr) {
|
|
247
|
+
totalFr += maxVal.fr;
|
|
248
|
+
} else {
|
|
249
|
+
// Only add to fixedSpace if max is NOT fr (non-flexible tracks)
|
|
250
|
+
fixedSpace += minVal || 0;
|
|
251
|
+
}
|
|
252
|
+
} else if (pt.endsWith("fr")) {
|
|
253
|
+
const fr = parseFloat(pt);
|
|
254
|
+
lanes.push({ min: 0, max: { fr }, size: 0 });
|
|
255
|
+
totalFr += fr;
|
|
256
|
+
} else {
|
|
257
|
+
const size =
|
|
258
|
+
parseLengthToPixels(
|
|
259
|
+
pt,
|
|
260
|
+
containerSize,
|
|
261
|
+
fontSize,
|
|
262
|
+
rootFontSize
|
|
263
|
+
) || 0;
|
|
264
|
+
lanes.push({ min: size, max: size, size });
|
|
265
|
+
fixedSpace += size;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
// Fixed repeat count
|
|
271
|
+
const reps = parseInt(count, 10);
|
|
272
|
+
for (let i = 0; i < reps; i++) {
|
|
273
|
+
for (const pt of patternTokens) {
|
|
274
|
+
const size = parseLengthToPixels(
|
|
275
|
+
pt,
|
|
276
|
+
containerSize,
|
|
277
|
+
fontSize,
|
|
278
|
+
rootFontSize
|
|
279
|
+
);
|
|
280
|
+
if (pt.endsWith("fr")) {
|
|
281
|
+
const fr = parseFloat(pt);
|
|
282
|
+
lanes.push({ min: 0, max: { fr }, size: 0 });
|
|
283
|
+
totalFr += fr;
|
|
284
|
+
} else if (size !== null) {
|
|
285
|
+
lanes.push({ min: size, max: size, size });
|
|
286
|
+
fixedSpace += size;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
continue
|
|
292
|
+
}
|
|
176
293
|
|
|
177
|
-
|
|
294
|
+
// Handle minmax()
|
|
295
|
+
const minmax = parseMinMax(token);
|
|
296
|
+
if (minmax) {
|
|
297
|
+
const minVal = parseLengthToPixels(
|
|
298
|
+
minmax.min,
|
|
299
|
+
containerSize,
|
|
300
|
+
fontSize,
|
|
301
|
+
rootFontSize
|
|
302
|
+
);
|
|
303
|
+
const maxVal = minmax.max.endsWith("fr")
|
|
304
|
+
? { fr: parseFloat(minmax.max) }
|
|
305
|
+
: parseLengthToPixels(minmax.max, containerSize, fontSize, rootFontSize);
|
|
306
|
+
|
|
307
|
+
lanes.push({ min: minVal || 0, max: maxVal, size: 0 });
|
|
308
|
+
if (typeof maxVal === "object" && maxVal.fr) {
|
|
309
|
+
totalFr += maxVal.fr;
|
|
310
|
+
} else {
|
|
311
|
+
// Only add to fixedSpace if max is NOT fr (non-flexible tracks)
|
|
312
|
+
fixedSpace += minVal || 0;
|
|
313
|
+
}
|
|
314
|
+
continue
|
|
315
|
+
}
|
|
178
316
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
317
|
+
// Handle fr units
|
|
318
|
+
if (token.endsWith("fr")) {
|
|
319
|
+
const fr = parseFloat(token);
|
|
320
|
+
lanes.push({ min: 0, max: { fr }, size: 0 });
|
|
321
|
+
totalFr += fr;
|
|
322
|
+
continue
|
|
323
|
+
}
|
|
182
324
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
325
|
+
// Handle fixed sizes
|
|
326
|
+
const size = parseLengthToPixels(
|
|
327
|
+
token,
|
|
328
|
+
containerSize,
|
|
329
|
+
fontSize,
|
|
330
|
+
rootFontSize
|
|
331
|
+
);
|
|
332
|
+
if (size !== null) {
|
|
333
|
+
lanes.push({ min: size, max: size, size });
|
|
334
|
+
fixedSpace += size;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
186
337
|
|
|
187
|
-
|
|
338
|
+
// Calculate final sizes
|
|
339
|
+
const totalGaps = Math.max(0, lanes.length - 1) * gap;
|
|
340
|
+
const flexSpace = Math.max(0, availableSpace - fixedSpace - totalGaps);
|
|
341
|
+
const frUnit = totalFr > 0 ? flexSpace / totalFr : 0;
|
|
188
342
|
|
|
189
|
-
|
|
190
|
-
|
|
343
|
+
for (const lane of lanes) {
|
|
344
|
+
if (typeof lane.max === "object" && lane.max.fr) {
|
|
345
|
+
lane.size = lane.min + frUnit * lane.max.fr;
|
|
346
|
+
} else {
|
|
347
|
+
lane.size = lane.min;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
191
350
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
};
|
|
351
|
+
return lanes.map(l => l.size)
|
|
352
|
+
}
|
|
195
353
|
|
|
196
|
-
|
|
354
|
+
// ============================================================================
|
|
355
|
+
// STYLE & ITEM UTILITIES
|
|
356
|
+
// ============================================================================
|
|
197
357
|
|
|
198
358
|
/**
|
|
199
|
-
*
|
|
359
|
+
* Get computed styles for grid-lanes properties
|
|
200
360
|
*/
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
361
|
+
function getGridLanesStyles(element) {
|
|
362
|
+
const computed = window.getComputedStyle(element);
|
|
363
|
+
const fontSize = parseFloat(computed.getPropertyValue("font-size")) || 16;
|
|
364
|
+
const rootFontSize =
|
|
365
|
+
parseFloat(
|
|
366
|
+
window
|
|
367
|
+
.getComputedStyle(document.documentElement)
|
|
368
|
+
.getPropertyValue("font-size")
|
|
369
|
+
) || 16;
|
|
370
|
+
|
|
371
|
+
// Get gap values
|
|
372
|
+
let gap =
|
|
373
|
+
computed.getPropertyValue("gap") ||
|
|
374
|
+
computed.getPropertyValue("grid-gap") ||
|
|
375
|
+
"0px";
|
|
376
|
+
let columnGap =
|
|
377
|
+
computed.getPropertyValue("column-gap") ||
|
|
378
|
+
computed.getPropertyValue("grid-column-gap") ||
|
|
379
|
+
gap;
|
|
380
|
+
let rowGap =
|
|
381
|
+
computed.getPropertyValue("row-gap") ||
|
|
382
|
+
computed.getPropertyValue("grid-row-gap") ||
|
|
383
|
+
gap;
|
|
384
|
+
|
|
385
|
+
// Handle combined gap shorthand like "24px 16px"
|
|
386
|
+
if (gap.includes(" ")) {
|
|
387
|
+
const [rg, cg] = gap.split(/\s+/);
|
|
388
|
+
rowGap = rg;
|
|
389
|
+
columnGap = cg;
|
|
209
390
|
}
|
|
210
391
|
|
|
211
|
-
//
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
392
|
+
// Parse flow-tolerance
|
|
393
|
+
let tolerance = DEFAULT_TOLERANCE;
|
|
394
|
+
const toleranceValue = computed.getPropertyValue("--flow-tolerance").trim();
|
|
395
|
+
|
|
396
|
+
if (toleranceValue) {
|
|
397
|
+
const parsed = parseLengthToPixels(
|
|
398
|
+
toleranceValue,
|
|
399
|
+
0,
|
|
400
|
+
fontSize,
|
|
401
|
+
rootFontSize
|
|
402
|
+
);
|
|
403
|
+
if (parsed !== null) tolerance = parsed;
|
|
404
|
+
}
|
|
215
405
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
406
|
+
return {
|
|
407
|
+
gridTemplateColumns: computed.getPropertyValue("grid-template-columns"),
|
|
408
|
+
gridTemplateRows: computed.getPropertyValue("grid-template-rows"),
|
|
409
|
+
columnGap:
|
|
410
|
+
parseLengthToPixels(
|
|
411
|
+
String(columnGap).split(" ")[0],
|
|
412
|
+
0,
|
|
413
|
+
fontSize,
|
|
414
|
+
rootFontSize
|
|
415
|
+
) || 0,
|
|
416
|
+
rowGap:
|
|
417
|
+
parseLengthToPixels(
|
|
418
|
+
String(rowGap).split(" ")[0],
|
|
419
|
+
0,
|
|
420
|
+
fontSize,
|
|
421
|
+
rootFontSize
|
|
422
|
+
) || 0,
|
|
423
|
+
fontSize,
|
|
424
|
+
rootFontSize,
|
|
425
|
+
tolerance
|
|
220
426
|
}
|
|
427
|
+
}
|
|
221
428
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
429
|
+
/**
|
|
430
|
+
* Get item placement properties
|
|
431
|
+
*/
|
|
432
|
+
function getItemStyles(element) {
|
|
433
|
+
const computed = window.getComputedStyle(element);
|
|
434
|
+
const gridColumn = computed.gridColumn || computed.gridColumnStart;
|
|
435
|
+
const gridRow = computed.gridRow || computed.gridRowStart;
|
|
436
|
+
|
|
437
|
+
let columnSpan = 1;
|
|
438
|
+
let columnStart = null;
|
|
439
|
+
let columnEnd = null;
|
|
440
|
+
let rowSpan = 1;
|
|
441
|
+
let rowStart = null;
|
|
442
|
+
let rowEnd = null;
|
|
443
|
+
|
|
444
|
+
// Parse grid-column
|
|
445
|
+
if (gridColumn && gridColumn !== "auto") {
|
|
446
|
+
const spanMatch = gridColumn.match(/span\s+(\d+)/);
|
|
447
|
+
if (spanMatch) {
|
|
448
|
+
columnSpan = parseInt(spanMatch[1], 10);
|
|
449
|
+
} else if (gridColumn.includes("/")) {
|
|
450
|
+
const [start, end] = gridColumn.split("/").map(s => s.trim());
|
|
451
|
+
columnStart = parseInt(start, 10);
|
|
452
|
+
columnEnd = parseInt(end, 10);
|
|
453
|
+
if (!isNaN(columnStart) && !isNaN(columnEnd)) {
|
|
454
|
+
columnSpan = Math.abs(columnEnd - columnStart);
|
|
455
|
+
}
|
|
456
|
+
} else {
|
|
457
|
+
const num = parseInt(gridColumn, 10);
|
|
458
|
+
if (!isNaN(num)) {
|
|
459
|
+
columnStart = num;
|
|
460
|
+
}
|
|
227
461
|
}
|
|
228
462
|
}
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
const reURL = /url\((['"])?(.*?)\1\)/gi;
|
|
232
463
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
464
|
+
// Parse grid-row
|
|
465
|
+
if (gridRow && gridRow !== "auto") {
|
|
466
|
+
const spanMatch = gridRow.match(/span\s+(\d+)/);
|
|
467
|
+
if (spanMatch) {
|
|
468
|
+
rowSpan = parseInt(spanMatch[1], 10);
|
|
469
|
+
} else if (gridRow.includes("/")) {
|
|
470
|
+
const [start, end] = gridRow.split("/").map(s => s.trim());
|
|
471
|
+
rowStart = parseInt(start, 10);
|
|
472
|
+
rowEnd = parseInt(end, 10);
|
|
473
|
+
if (!isNaN(rowStart) && !isNaN(rowEnd)) {
|
|
474
|
+
rowSpan = Math.abs(rowEnd - rowStart);
|
|
475
|
+
}
|
|
476
|
+
} else {
|
|
477
|
+
const num = parseInt(gridRow, 10);
|
|
478
|
+
if (!isNaN(num)) {
|
|
479
|
+
rowStart = num;
|
|
480
|
+
}
|
|
244
481
|
}
|
|
245
|
-
matches = reURL.exec( style.backgroundImage );
|
|
246
482
|
}
|
|
247
|
-
};
|
|
248
483
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
ImagesLoaded.prototype.addBackground = function( url, elem ) {
|
|
258
|
-
let background = new Background( url, elem );
|
|
259
|
-
this.images.push( background );
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
ImagesLoaded.prototype.check = function() {
|
|
263
|
-
this.progressedCount = 0;
|
|
264
|
-
this.hasAnyBroken = false;
|
|
265
|
-
// complete if no images
|
|
266
|
-
if ( !this.images.length ) {
|
|
267
|
-
this.complete();
|
|
268
|
-
return;
|
|
484
|
+
return {
|
|
485
|
+
columnSpan,
|
|
486
|
+
columnStart,
|
|
487
|
+
columnEnd,
|
|
488
|
+
rowSpan,
|
|
489
|
+
rowStart,
|
|
490
|
+
rowEnd
|
|
269
491
|
}
|
|
492
|
+
}
|
|
270
493
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
setTimeout( () => {
|
|
275
|
-
this.progress( image, elem, message );
|
|
276
|
-
} );
|
|
277
|
-
};
|
|
494
|
+
// ============================================================================
|
|
495
|
+
// STYLE CACHE MANAGEMENT
|
|
496
|
+
// ============================================================================
|
|
278
497
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
ImagesLoaded.prototype.progress = function( image, elem, message ) {
|
|
286
|
-
this.progressedCount++;
|
|
287
|
-
this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
|
|
288
|
-
// progress event
|
|
289
|
-
this.emitEvent( 'progress', [ this, image, elem ] );
|
|
290
|
-
if ( this.jqDeferred && this.jqDeferred.notify ) {
|
|
291
|
-
this.jqDeferred.notify( this, image );
|
|
292
|
-
}
|
|
293
|
-
// check if completed
|
|
294
|
-
if ( this.progressedCount === this.images.length ) {
|
|
295
|
-
this.complete();
|
|
498
|
+
/**
|
|
499
|
+
* Get computed style with caching to reduce redundant calls
|
|
500
|
+
*/
|
|
501
|
+
function catchedGetComputedStyle(elem, useCatch = true) {
|
|
502
|
+
if (useCatch && styleMap.has(elem)) {
|
|
503
|
+
return styleMap.get(elem)
|
|
296
504
|
}
|
|
505
|
+
const style = window.getComputedStyle(elem);
|
|
506
|
+
styleMap.set(elem, style);
|
|
507
|
+
return style
|
|
508
|
+
}
|
|
297
509
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
let eventName = this.hasAnyBroken ? 'fail' : 'done';
|
|
305
|
-
this.isComplete = true;
|
|
306
|
-
this.emitEvent( eventName, [ this ] );
|
|
307
|
-
this.emitEvent( 'always', [ this ] );
|
|
308
|
-
if ( this.jqDeferred ) {
|
|
309
|
-
let jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
|
|
310
|
-
this.jqDeferred[ jqMethod ]( this );
|
|
311
|
-
}
|
|
312
|
-
};
|
|
510
|
+
/**
|
|
511
|
+
* Clear cached style for an element
|
|
512
|
+
*/
|
|
513
|
+
function removeCachedStyle(elem) {
|
|
514
|
+
styleMap.delete(elem);
|
|
515
|
+
}
|
|
313
516
|
|
|
314
|
-
//
|
|
517
|
+
// ============================================================================
|
|
518
|
+
// DOM UTILITIES
|
|
519
|
+
// ============================================================================
|
|
315
520
|
|
|
316
|
-
|
|
317
|
-
|
|
521
|
+
/**
|
|
522
|
+
* Check if element has the grid-lanes polyfill marker
|
|
523
|
+
*/
|
|
524
|
+
function hasGridLanesProperty(elem) {
|
|
525
|
+
return (
|
|
526
|
+
catchedGetComputedStyle(elem)
|
|
527
|
+
.getPropertyValue("--grid-lanes-polyfill")
|
|
528
|
+
.trim() === "1"
|
|
529
|
+
)
|
|
318
530
|
}
|
|
319
531
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
532
|
+
/**
|
|
533
|
+
* Find all elements with --grid-lanes-polyfill down to the granular level.
|
|
534
|
+
* Prefers children over parent elements. Note: nested grid-lanes are not
|
|
535
|
+
* supported because the custom property cascades to all descendants.
|
|
536
|
+
*
|
|
537
|
+
* Uses TreeWalker for efficient traversal and routes through hasGridLanesProperty()
|
|
538
|
+
* to leverage the catchedGetComputedStyle cache. Correctly handles subtree skipping.
|
|
539
|
+
*/
|
|
540
|
+
function findElements(root = document.body) {
|
|
541
|
+
const results = [];
|
|
542
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
|
|
543
|
+
|
|
544
|
+
let node = walker.nextNode(); // start from first child, skip root itself
|
|
545
|
+
while (node) {
|
|
546
|
+
if (hasGridLanesProperty(node)) {
|
|
547
|
+
results.push(node);
|
|
548
|
+
// Skip the entire subtree of this match by finding the next
|
|
549
|
+
// node outside of it: try nextSibling, then bubble up ancestors.
|
|
550
|
+
let next = null;
|
|
551
|
+
let ancestor = node;
|
|
552
|
+
while (ancestor && ancestor !== root) {
|
|
553
|
+
walker.currentNode = ancestor;
|
|
554
|
+
next = walker.nextSibling();
|
|
555
|
+
if (next) break
|
|
556
|
+
ancestor = ancestor.parentElement;
|
|
557
|
+
}
|
|
558
|
+
node = next; // null means no more nodes in tree
|
|
559
|
+
} else {
|
|
560
|
+
node = walker.nextNode();
|
|
561
|
+
}
|
|
330
562
|
}
|
|
563
|
+
return results
|
|
564
|
+
}
|
|
331
565
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
this.img.addEventListener( 'load', this );
|
|
342
|
-
this.img.addEventListener( 'error', this );
|
|
343
|
-
this.proxyImage.src = this.img.currentSrc || this.img.src;
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
LoadingImage.prototype.getIsImageComplete = function() {
|
|
347
|
-
// check for non-zero, non-undefined naturalWidth
|
|
348
|
-
// fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671
|
|
349
|
-
return this.img.complete && this.img.naturalWidth;
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
LoadingImage.prototype.confirm = function( isLoaded, message ) {
|
|
353
|
-
this.isLoaded = isLoaded;
|
|
354
|
-
let { parentNode } = this.img;
|
|
355
|
-
// emit progress with parent <picture> or self <img>
|
|
356
|
-
let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;
|
|
357
|
-
this.emitEvent( 'progress', [ this, elem, message ] );
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
// ----- events ----- //
|
|
361
|
-
|
|
362
|
-
// trigger specified handler for event type
|
|
363
|
-
LoadingImage.prototype.handleEvent = function( event ) {
|
|
364
|
-
let method = 'on' + event.type;
|
|
365
|
-
if ( this[ method ] ) {
|
|
366
|
-
this[ method ]( event );
|
|
566
|
+
/**
|
|
567
|
+
* Process a subtree for grid-lanes containers
|
|
568
|
+
*/
|
|
569
|
+
function processSubtree(root, instances, options) {
|
|
570
|
+
const containers = findElements(root);
|
|
571
|
+
for (const container of containers) {
|
|
572
|
+
if (!instances.has(container) && !container.hasAttribute(POLYFILL_ATTR)) {
|
|
573
|
+
instances.set(container, new GridLanesLayout(container, options));
|
|
574
|
+
}
|
|
367
575
|
}
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
LoadingImage.prototype.onload = function() {
|
|
371
|
-
this.confirm( true, 'onload' );
|
|
372
|
-
this.unbindEvents();
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
LoadingImage.prototype.onerror = function() {
|
|
376
|
-
this.confirm( false, 'onerror' );
|
|
377
|
-
this.unbindEvents();
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
LoadingImage.prototype.unbindEvents = function() {
|
|
381
|
-
this.proxyImage.removeEventListener( 'load', this );
|
|
382
|
-
this.proxyImage.removeEventListener( 'error', this );
|
|
383
|
-
this.img.removeEventListener( 'load', this );
|
|
384
|
-
this.img.removeEventListener( 'error', this );
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
// -------------------------- Background -------------------------- //
|
|
388
|
-
|
|
389
|
-
function Background( url, element ) {
|
|
390
|
-
this.url = url;
|
|
391
|
-
this.element = element;
|
|
392
|
-
this.img = new Image();
|
|
393
576
|
}
|
|
394
577
|
|
|
395
|
-
//
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
Background.prototype.check = function() {
|
|
399
|
-
this.img.addEventListener( 'load', this );
|
|
400
|
-
this.img.addEventListener( 'error', this );
|
|
401
|
-
this.img.src = this.url;
|
|
402
|
-
// check if image is already complete
|
|
403
|
-
let isComplete = this.getIsImageComplete();
|
|
404
|
-
if ( isComplete ) {
|
|
405
|
-
this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
|
|
406
|
-
this.unbindEvents();
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
Background.prototype.unbindEvents = function() {
|
|
411
|
-
this.img.removeEventListener( 'load', this );
|
|
412
|
-
this.img.removeEventListener( 'error', this );
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
Background.prototype.confirm = function( isLoaded, message ) {
|
|
416
|
-
this.isLoaded = isLoaded;
|
|
417
|
-
this.emitEvent( 'progress', [ this, this.element, message ] );
|
|
418
|
-
};
|
|
419
|
-
|
|
420
|
-
// -------------------------- jQuery -------------------------- //
|
|
421
|
-
|
|
422
|
-
ImagesLoaded.makeJQueryPlugin = function( jQuery ) {
|
|
423
|
-
jQuery = jQuery || window.jQuery;
|
|
424
|
-
if ( !jQuery ) return;
|
|
425
|
-
|
|
426
|
-
// set local variable
|
|
427
|
-
$ = jQuery;
|
|
428
|
-
// $().imagesLoaded()
|
|
429
|
-
$.fn.imagesLoaded = function( options, onAlways ) {
|
|
430
|
-
let instance = new ImagesLoaded( this, options, onAlways );
|
|
431
|
-
return instance.jqDeferred.promise( $( this ) );
|
|
432
|
-
};
|
|
433
|
-
};
|
|
434
|
-
// try making plugin
|
|
435
|
-
ImagesLoaded.makeJQueryPlugin();
|
|
578
|
+
// ============================================================================
|
|
579
|
+
// GRID LANES LAYOUT CLASS
|
|
580
|
+
// ============================================================================
|
|
436
581
|
|
|
437
|
-
|
|
582
|
+
/**
|
|
583
|
+
* Main Grid Lanes layout class
|
|
584
|
+
*/
|
|
585
|
+
class GridLanesLayout {
|
|
586
|
+
constructor(container, options = {}) {
|
|
587
|
+
this.container = container;
|
|
588
|
+
this.options = options;
|
|
589
|
+
this.isVertical = true; // true = waterfall (columns), false = brick (rows)
|
|
590
|
+
this.lanes = [];
|
|
591
|
+
this.laneHeights = [];
|
|
592
|
+
this.resizeObserver = null;
|
|
593
|
+
this.mutationObserver = null;
|
|
438
594
|
|
|
439
|
-
|
|
595
|
+
this.init();
|
|
596
|
+
}
|
|
440
597
|
|
|
441
|
-
|
|
598
|
+
init() {
|
|
599
|
+
// Mark as polyfilled
|
|
600
|
+
this.container.setAttribute(POLYFILL_ATTR, "true");
|
|
442
601
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
* https://masonry.desandro.com
|
|
447
|
-
* MIT License
|
|
448
|
-
* by David DeSandro
|
|
449
|
-
*/
|
|
602
|
+
// Set up container styles
|
|
603
|
+
this.container.style.position = "relative";
|
|
604
|
+
this.container.style.display = "block";
|
|
450
605
|
|
|
451
|
-
!function(t,e){"function"==typeof define&&define.amd?define("jquery-bridget/jquery-bridget",["jquery"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("jquery")):t.jQueryBridget=e(t,t.jQuery);}(window,function(t,e){function i(i,r,a){function h(t,e,n){var o,r="$()."+i+'("'+e+'")';return t.each(function(t,h){var u=a.data(h,i);if(!u)return void s(i+" not initialized. Cannot call methods, i.e. "+r);var d=u[e];if(!d||"_"==e.charAt(0))return void s(r+" is not a valid method");var l=d.apply(u,n);o=void 0===o?l:o;}),void 0!==o?o:t}function u(t,e){t.each(function(t,n){var o=a.data(n,i);o?(o.option(e),o._init()):(o=new r(n,e),a.data(n,i,o));});}a=a||e||t.jQuery,a&&(r.prototype.option||(r.prototype.option=function(t){a.isPlainObject(t)&&(this.options=a.extend(true,this.options,t));}),a.fn[i]=function(t){if("string"==typeof t){var e=o.call(arguments,1);return h(this,t,e)}return u(this,t),this},n(a));}function n(t){!t||t&&t.bridget||(t.bridget=i);}var o=Array.prototype.slice,r=t.console,s="undefined"==typeof r?function(){}:function(t){r.error(t);};return n(e||t.jQuery),i}),function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e();}("undefined"!=typeof window?window:undefined,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return -1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||{};return n[e]=true,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return -1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){i=i.slice(0),e=e||[];for(var n=this._onceEvents&&this._onceEvents[t],o=0;o<i.length;o++){var r=i[o],s=n&&n[r];s&&(this.off(t,r),delete n[r]),r.apply(this,e);}return this}},e.allOff=function(){delete this._events,delete this._onceEvents;},t}),function(t,e){"function"==typeof define&&define.amd?define("get-size/get-size",e):"object"==typeof module&&module.exports?module.exports=e():t.getSize=e();}(window,function(){function t(t){var e=parseFloat(t),i=-1==t.indexOf("%")&&!isNaN(e);return i&&e}function e(){}function i(){for(var t={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},e=0;u>e;e++){var i=h[e];t[i]=0;}return t}function n(t){var e=getComputedStyle(t);return e||a("Style returned "+e+". Are you running this code in a hidden iframe on Firefox? See https://bit.ly/getsizebug1"),e}function o(){if(!d){d=true;var e=document.createElement("div");e.style.width="200px",e.style.padding="1px 2px 3px 4px",e.style.borderStyle="solid",e.style.borderWidth="1px 2px 3px 4px",e.style.boxSizing="border-box";var i=document.body||document.documentElement;i.appendChild(e);var o=n(e);s=200==Math.round(t(o.width)),r.isBoxSizeOuter=s,i.removeChild(e);}}function r(e){if(o(),"string"==typeof e&&(e=document.querySelector(e)),e&&"object"==typeof e&&e.nodeType){var r=n(e);if("none"==r.display)return i();var a={};a.width=e.offsetWidth,a.height=e.offsetHeight;for(var d=a.isBorderBox="border-box"==r.boxSizing,l=0;u>l;l++){var c=h[l],f=r[c],m=parseFloat(f);a[c]=isNaN(m)?0:m;}var p=a.paddingLeft+a.paddingRight,g=a.paddingTop+a.paddingBottom,y=a.marginLeft+a.marginRight,v=a.marginTop+a.marginBottom,_=a.borderLeftWidth+a.borderRightWidth,z=a.borderTopWidth+a.borderBottomWidth,E=d&&s,b=t(r.width);b!==false&&(a.width=b+(E?0:p+_));var x=t(r.height);return x!==false&&(a.height=x+(E?0:g+z)),a.innerWidth=a.width-(p+_),a.innerHeight=a.height-(g+z),a.outerWidth=a.width+y,a.outerHeight=a.height+v,a}}var s,a="undefined"==typeof console?e:function(t){console.error(t);},h=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"],u=h.length,d=false;return r}),function(t,e){"function"==typeof define&&define.amd?define("desandro-matches-selector/matches-selector",e):"object"==typeof module&&module.exports?module.exports=e():t.matchesSelector=e();}(window,function(){var t=function(){var t=window.Element.prototype;if(t.matches)return "matches";if(t.matchesSelector)return "matchesSelector";for(var e=["webkit","moz","ms","o"],i=0;i<e.length;i++){var n=e[i],o=n+"MatchesSelector";if(t[o])return o}}();return function(e,i){return e[t](i)}}),function(t,e){"function"==typeof define&&define.amd?define("fizzy-ui-utils/utils",["desandro-matches-selector/matches-selector"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("desandro-matches-selector")):t.fizzyUIUtils=e(t,t.matchesSelector);}(window,function(t,e){var i={};i.extend=function(t,e){for(var i in e)t[i]=e[i];return t},i.modulo=function(t,e){return (t%e+e)%e};var n=Array.prototype.slice;i.makeArray=function(t){if(Array.isArray(t))return t;if(null===t||void 0===t)return [];var e="object"==typeof t&&"number"==typeof t.length;return e?n.call(t):[t]},i.removeFrom=function(t,e){var i=t.indexOf(e);-1!=i&&t.splice(i,1);},i.getParent=function(t,i){for(;t.parentNode&&t!=document.body;)if(t=t.parentNode,e(t,i))return t},i.getQueryElement=function(t){return "string"==typeof t?document.querySelector(t):t},i.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t);},i.filterFindElements=function(t,n){t=i.makeArray(t);var o=[];return t.forEach(function(t){if(t instanceof HTMLElement){if(!n)return void o.push(t);e(t,n)&&o.push(t);for(var i=t.querySelectorAll(n),r=0;r<i.length;r++)o.push(i[r]);}}),o},i.debounceMethod=function(t,e,i){i=i||100;var n=t.prototype[e],o=e+"Timeout";t.prototype[e]=function(){var t=this[o];clearTimeout(t);var e=arguments,r=this;this[o]=setTimeout(function(){n.apply(r,e),delete r[o];},i);};},i.docReady=function(t){var e=document.readyState;"complete"==e||"interactive"==e?setTimeout(t):document.addEventListener("DOMContentLoaded",t);},i.toDashed=function(t){return t.replace(/(.)([A-Z])/g,function(t,e,i){return e+"-"+i}).toLowerCase()};var o=t.console;return i.htmlInit=function(e,n){i.docReady(function(){var r=i.toDashed(n),s="data-"+r,a=document.querySelectorAll("["+s+"]"),h=document.querySelectorAll(".js-"+r),u=i.makeArray(a).concat(i.makeArray(h)),d=s+"-options",l=t.jQuery;u.forEach(function(t){var i,r=t.getAttribute(s)||t.getAttribute(d);try{i=r&&JSON.parse(r);}catch(a){return void(o&&o.error("Error parsing "+s+" on "+t.className+": "+a))}var h=new e(t,i);l&&l.data(t,n,h);});});},i}),function(t,e){"function"==typeof define&&define.amd?define("outlayer/item",["ev-emitter/ev-emitter","get-size/get-size"],e):"object"==typeof module&&module.exports?module.exports=e(require("ev-emitter"),require("get-size")):(t.Outlayer={},t.Outlayer.Item=e(t.EvEmitter,t.getSize));}(window,function(t,e){function i(t){for(var e in t)return false;return e=null,true}function n(t,e){t&&(this.element=t,this.layout=e,this.position={x:0,y:0},this._create());}function o(t){return t.replace(/([A-Z])/g,function(t){return "-"+t.toLowerCase()})}var r=document.documentElement.style,s="string"==typeof r.transition?"transition":"WebkitTransition",a="string"==typeof r.transform?"transform":"WebkitTransform",h={WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[s],u={transform:a,transition:s,transitionDuration:s+"Duration",transitionProperty:s+"Property",transitionDelay:s+"Delay"},d=n.prototype=Object.create(t.prototype);d.constructor=n,d._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"});},d.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t);},d.getSize=function(){this.size=e(this.element);},d.css=function(t){var e=this.element.style;for(var i in t){var n=u[i]||i;e[n]=t[i];}},d.getPosition=function(){var t=getComputedStyle(this.element),e=this.layout._getOption("originLeft"),i=this.layout._getOption("originTop"),n=t[e?"left":"right"],o=t[i?"top":"bottom"],r=parseFloat(n),s=parseFloat(o),a=this.layout.size;-1!=n.indexOf("%")&&(r=r/100*a.width),-1!=o.indexOf("%")&&(s=s/100*a.height),r=isNaN(r)?0:r,s=isNaN(s)?0:s,r-=e?a.paddingLeft:a.paddingRight,s-=i?a.paddingTop:a.paddingBottom,this.position.x=r,this.position.y=s;},d.layoutPosition=function(){var t=this.layout.size,e={},i=this.layout._getOption("originLeft"),n=this.layout._getOption("originTop"),o=i?"paddingLeft":"paddingRight",r=i?"left":"right",s=i?"right":"left",a=this.position.x+t[o];e[r]=this.getXValue(a),e[s]="";var h=n?"paddingTop":"paddingBottom",u=n?"top":"bottom",d=n?"bottom":"top",l=this.position.y+t[h];e[u]=this.getYValue(l),e[d]="",this.css(e),this.emitEvent("layout",[this]);},d.getXValue=function(t){var e=this.layout._getOption("horizontal");return this.layout.options.percentPosition&&!e?t/this.layout.size.width*100+"%":t+"px"},d.getYValue=function(t){var e=this.layout._getOption("horizontal");return this.layout.options.percentPosition&&e?t/this.layout.size.height*100+"%":t+"px"},d._transitionTo=function(t,e){this.getPosition();var i=this.position.x,n=this.position.y,o=t==this.position.x&&e==this.position.y;if(this.setPosition(t,e),o&&!this.isTransitioning)return void this.layoutPosition();var r=t-i,s=e-n,a={};a.transform=this.getTranslate(r,s),this.transition({to:a,onTransitionEnd:{transform:this.layoutPosition},isCleaning:true});},d.getTranslate=function(t,e){var i=this.layout._getOption("originLeft"),n=this.layout._getOption("originTop");return t=i?t:-t,e=n?e:-e,"translate3d("+t+"px, "+e+"px, 0)"},d.goTo=function(t,e){this.setPosition(t,e),this.layoutPosition();},d.moveTo=d._transitionTo,d.setPosition=function(t,e){this.position.x=parseFloat(t),this.position.y=parseFloat(e);},d._nonTransition=function(t){this.css(t.to),t.isCleaning&&this._removeStyles(t.to);for(var e in t.onTransitionEnd)t.onTransitionEnd[e].call(this);},d.transition=function(t){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(t);var e=this._transn;for(var i in t.onTransitionEnd)e.onEnd[i]=t.onTransitionEnd[i];for(i in t.to)e.ingProperties[i]=true,t.isCleaning&&(e.clean[i]=true);if(t.from){this.css(t.from);this.element.offsetHeight;}this.enableTransition(t.to),this.css(t.to),this.isTransitioning=true;};var l="opacity,"+o(a);d.enableTransition=function(){if(!this.isTransitioning){var t=this.layout.options.transitionDuration;t="number"==typeof t?t+"ms":t,this.css({transitionProperty:l,transitionDuration:t,transitionDelay:this.staggerDelay||0}),this.element.addEventListener(h,this,false);}},d.onwebkitTransitionEnd=function(t){this.ontransitionend(t);},d.onotransitionend=function(t){this.ontransitionend(t);};var c={"-webkit-transform":"transform"};d.ontransitionend=function(t){if(t.target===this.element){var e=this._transn,n=c[t.propertyName]||t.propertyName;if(delete e.ingProperties[n],i(e.ingProperties)&&this.disableTransition(),n in e.clean&&(this.element.style[t.propertyName]="",delete e.clean[n]),n in e.onEnd){var o=e.onEnd[n];o.call(this),delete e.onEnd[n];}this.emitEvent("transitionEnd",[this]);}},d.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(h,this,false),this.isTransitioning=false;},d._removeStyles=function(t){var e={};for(var i in t)e[i]="";this.css(e);};var f={transitionProperty:"",transitionDuration:"",transitionDelay:""};return d.removeTransitionStyles=function(){this.css(f);},d.stagger=function(t){t=isNaN(t)?0:t,this.staggerDelay=t+"ms";},d.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:""}),this.emitEvent("remove",[this]);},d.remove=function(){return s&&parseFloat(this.layout.options.transitionDuration)?(this.once("transitionEnd",function(){this.removeElem();}),void this.hide()):void this.removeElem()},d.reveal=function(){delete this.isHidden,this.css({display:""});var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("visibleStyle");e[i]=this.onRevealTransitionEnd,this.transition({from:t.hiddenStyle,to:t.visibleStyle,isCleaning:true,onTransitionEnd:e});},d.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent("reveal");},d.getHideRevealTransitionEndProperty=function(t){var e=this.layout.options[t];if(e.opacity)return "opacity";for(var i in e)return i},d.hide=function(){this.isHidden=true,this.css({display:""});var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("hiddenStyle");e[i]=this.onHideTransitionEnd,this.transition({from:t.visibleStyle,to:t.hiddenStyle,isCleaning:true,onTransitionEnd:e});},d.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:"none"}),this.emitEvent("hide"));},d.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""});},n}),function(t,e){"function"==typeof define&&define.amd?define("outlayer/outlayer",["ev-emitter/ev-emitter","get-size/get-size","fizzy-ui-utils/utils","./item"],function(i,n,o,r){return e(t,i,n,o,r)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter"),require("get-size"),require("fizzy-ui-utils"),require("./item")):t.Outlayer=e(t,t.EvEmitter,t.getSize,t.fizzyUIUtils,t.Outlayer.Item);}(window,function(t,e,i,n,o){function r(t,e){var i=n.getQueryElement(t);if(!i)return void(h&&h.error("Bad element for "+this.constructor.namespace+": "+(i||t)));this.element=i,u&&(this.$element=u(this.element)),this.options=n.extend({},this.constructor.defaults),this.option(e);var o=++l;this.element.outlayerGUID=o,c[o]=this,this._create();var r=this._getOption("initLayout");r&&this.layout();}function s(t){function e(){t.apply(this,arguments);}return e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e}function a(t){if("number"==typeof t)return t;var e=t.match(/(^\d*\.?\d*)(\w*)/),i=e&&e[1],n=e&&e[2];if(!i.length)return 0;i=parseFloat(i);var o=m[n]||1;return i*o}var h=t.console,u=t.jQuery,d=function(){},l=0,c={};r.namespace="outlayer",r.Item=o,r.defaults={containerStyle:{position:"relative"},initLayout:true,originLeft:true,originTop:true,resize:true,resizeContainer:true,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}};var f=r.prototype;n.extend(f,e.prototype),f.option=function(t){n.extend(this.options,t);},f._getOption=function(t){var e=this.constructor.compatOptions[t];return e&&void 0!==this.options[e]?this.options[e]:this.options[t]},r.compatOptions={initLayout:"isInitLayout",horizontal:"isHorizontal",layoutInstant:"isLayoutInstant",originLeft:"isOriginLeft",originTop:"isOriginTop",resize:"isResizeBound",resizeContainer:"isResizingContainer"},f._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),n.extend(this.element.style,this.options.containerStyle);var t=this._getOption("resize");t&&this.bindResize();},f.reloadItems=function(){this.items=this._itemize(this.element.children);},f._itemize=function(t){for(var e=this._filterFindItemElements(t),i=this.constructor.Item,n=[],o=0;o<e.length;o++){var r=e[o],s=new i(r,this);n.push(s);}return n},f._filterFindItemElements=function(t){return n.filterFindElements(t,this.options.itemSelector)},f.getItemElements=function(){return this.items.map(function(t){return t.element})},f.layout=function(){this._resetLayout(),this._manageStamps();var t=this._getOption("layoutInstant"),e=void 0!==t?t:!this._isLayoutInited;this.layoutItems(this.items,e),this._isLayoutInited=true;},f._init=f.layout,f._resetLayout=function(){this.getSize();},f.getSize=function(){this.size=i(this.element);},f._getMeasurement=function(t,e){var n,o=this.options[t];o?("string"==typeof o?n=this.element.querySelector(o):o instanceof HTMLElement&&(n=o),this[t]=n?i(n)[e]:o):this[t]=0;},f.layoutItems=function(t,e){t=this._getItemsForLayout(t),this._layoutItems(t,e),this._postLayout();},f._getItemsForLayout=function(t){return t.filter(function(t){return !t.isIgnored})},f._layoutItems=function(t,e){if(this._emitCompleteOnItems("layout",t),t&&t.length){var i=[];t.forEach(function(t){var n=this._getItemLayoutPosition(t);n.item=t,n.isInstant=e||t.isLayoutInstant,i.push(n);},this),this._processLayoutQueue(i);}},f._getItemLayoutPosition=function(){return {x:0,y:0}},f._processLayoutQueue=function(t){this.updateStagger(),t.forEach(function(t,e){this._positionItem(t.item,t.x,t.y,t.isInstant,e);},this);},f.updateStagger=function(){var t=this.options.stagger;return null===t||void 0===t?void(this.stagger=0):(this.stagger=a(t),this.stagger)},f._positionItem=function(t,e,i,n,o){n?t.goTo(e,i):(t.stagger(o*this.stagger),t.moveTo(e,i));},f._postLayout=function(){this.resizeContainer();},f.resizeContainer=function(){var t=this._getOption("resizeContainer");if(t){var e=this._getContainerSize();e&&(this._setContainerMeasure(e.width,true),this._setContainerMeasure(e.height,false));}},f._getContainerSize=d,f._setContainerMeasure=function(t,e){if(void 0!==t){var i=this.size;i.isBorderBox&&(t+=e?i.paddingLeft+i.paddingRight+i.borderLeftWidth+i.borderRightWidth:i.paddingBottom+i.paddingTop+i.borderTopWidth+i.borderBottomWidth),t=Math.max(t,0),this.element.style[e?"width":"height"]=t+"px";}},f._emitCompleteOnItems=function(t,e){function i(){o.dispatchEvent(t+"Complete",null,[e]);}function n(){s++,s==r&&i();}var o=this,r=e.length;if(!e||!r)return void i();var s=0;e.forEach(function(e){e.once(t,n);});},f.dispatchEvent=function(t,e,i){var n=e?[e].concat(i):i;if(this.emitEvent(t,n),u)if(this.$element=this.$element||u(this.element),e){var o=u.Event(e);o.type=t,this.$element.trigger(o,i);}else this.$element.trigger(t,i);},f.ignore=function(t){var e=this.getItem(t);e&&(e.isIgnored=true);},f.unignore=function(t){var e=this.getItem(t);e&&delete e.isIgnored;},f.stamp=function(t){t=this._find(t),t&&(this.stamps=this.stamps.concat(t),t.forEach(this.ignore,this));},f.unstamp=function(t){t=this._find(t),t&&t.forEach(function(t){n.removeFrom(this.stamps,t),this.unignore(t);},this);},f._find=function(t){return t?("string"==typeof t&&(t=this.element.querySelectorAll(t)),t=n.makeArray(t)):void 0},f._manageStamps=function(){this.stamps&&this.stamps.length&&(this._getBoundingRect(),this.stamps.forEach(this._manageStamp,this));},f._getBoundingRect=function(){var t=this.element.getBoundingClientRect(),e=this.size;this._boundingRect={left:t.left+e.paddingLeft+e.borderLeftWidth,top:t.top+e.paddingTop+e.borderTopWidth,right:t.right-(e.paddingRight+e.borderRightWidth),bottom:t.bottom-(e.paddingBottom+e.borderBottomWidth)};},f._manageStamp=d,f._getElementOffset=function(t){var e=t.getBoundingClientRect(),n=this._boundingRect,o=i(t),r={left:e.left-n.left-o.marginLeft,top:e.top-n.top-o.marginTop,right:n.right-e.right-o.marginRight,bottom:n.bottom-e.bottom-o.marginBottom};return r},f.handleEvent=n.handleEvent,f.bindResize=function(){t.addEventListener("resize",this),this.isResizeBound=true;},f.unbindResize=function(){t.removeEventListener("resize",this),this.isResizeBound=false;},f.onresize=function(){this.resize();},n.debounceMethod(r,"onresize",100),f.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout();},f.needsResizeLayout=function(){var t=i(this.element),e=this.size&&t;return e&&t.innerWidth!==this.size.innerWidth},f.addItems=function(t){var e=this._itemize(t);return e.length&&(this.items=this.items.concat(e)),e},f.appended=function(t){var e=this.addItems(t);e.length&&(this.layoutItems(e,true),this.reveal(e));},f.prepended=function(t){var e=this._itemize(t);if(e.length){var i=this.items.slice(0);this.items=e.concat(i),this._resetLayout(),this._manageStamps(),this.layoutItems(e,true),this.reveal(e),this.layoutItems(i);}},f.reveal=function(t){if(this._emitCompleteOnItems("reveal",t),t&&t.length){var e=this.updateStagger();t.forEach(function(t,i){t.stagger(i*e),t.reveal();});}},f.hide=function(t){if(this._emitCompleteOnItems("hide",t),t&&t.length){var e=this.updateStagger();t.forEach(function(t,i){t.stagger(i*e),t.hide();});}},f.revealItemElements=function(t){var e=this.getItems(t);this.reveal(e);},f.hideItemElements=function(t){var e=this.getItems(t);this.hide(e);},f.getItem=function(t){for(var e=0;e<this.items.length;e++){var i=this.items[e];if(i.element==t)return i}},f.getItems=function(t){t=n.makeArray(t);var e=[];return t.forEach(function(t){var i=this.getItem(t);i&&e.push(i);},this),e},f.remove=function(t){var e=this.getItems(t);this._emitCompleteOnItems("remove",e),e&&e.length&&e.forEach(function(t){t.remove(),n.removeFrom(this.items,t);},this);},f.destroy=function(){var t=this.element.style;t.height="",t.position="",t.width="",this.items.forEach(function(t){t.destroy();}),this.unbindResize();var e=this.element.outlayerGUID;delete c[e],delete this.element.outlayerGUID,u&&u.removeData(this.element,this.constructor.namespace);},r.data=function(t){t=n.getQueryElement(t);var e=t&&t.outlayerGUID;return e&&c[e]},r.create=function(t,e){var i=s(r);return i.defaults=n.extend({},r.defaults),n.extend(i.defaults,e),i.compatOptions=n.extend({},r.compatOptions),i.namespace=t,i.data=r.data,i.Item=s(o),n.htmlInit(i,t),u&&u.bridget&&u.bridget(t,i),i};var m={ms:1,s:1e3};return r.Item=o,r}),function(t,e){"function"==typeof define&&define.amd?define(["outlayer/outlayer","get-size/get-size"],e):"object"==typeof module&&module.exports?module.exports=e(require("outlayer"),require("get-size")):t.Masonry=e(t.Outlayer,t.getSize);}(window,function(t,e){var i=t.create("masonry");i.compatOptions.fitWidth="isFitWidth";var n=i.prototype;return n._resetLayout=function(){this.getSize(),this._getMeasurement("columnWidth","outerWidth"),this._getMeasurement("gutter","outerWidth"),this.measureColumns(),this.colYs=[];for(var t=0;t<this.cols;t++)this.colYs.push(0);this.maxY=0,this.horizontalColIndex=0;},n.measureColumns=function(){if(this.getContainerWidth(),!this.columnWidth){var t=this.items[0],i=t&&t.element;this.columnWidth=i&&e(i).outerWidth||this.containerWidth;}var n=this.columnWidth+=this.gutter,o=this.containerWidth+this.gutter,r=o/n,s=n-o%n,a=s&&1>s?"round":"floor";r=Math[a](r),this.cols=Math.max(r,1);},n.getContainerWidth=function(){var t=this._getOption("fitWidth"),i=t?this.element.parentNode:this.element,n=e(i);this.containerWidth=n&&n.innerWidth;},n._getItemLayoutPosition=function(t){t.getSize();var e=t.size.outerWidth%this.columnWidth,i=e&&1>e?"round":"ceil",n=Math[i](t.size.outerWidth/this.columnWidth);n=Math.min(n,this.cols);for(var o=this.options.horizontalOrder?"_getHorizontalColPosition":"_getTopColPosition",r=this[o](n,t),s={x:this.columnWidth*r.col,y:r.y},a=r.y+t.size.outerHeight,h=n+r.col,u=r.col;h>u;u++)this.colYs[u]=a;return s},n._getTopColPosition=function(t){var e=this._getTopColGroup(t),i=Math.min.apply(Math,e);return {col:e.indexOf(i),y:i}},n._getTopColGroup=function(t){if(2>t)return this.colYs;for(var e=[],i=this.cols+1-t,n=0;i>n;n++)e[n]=this._getColGroupY(n,t);return e},n._getColGroupY=function(t,e){if(2>e)return this.colYs[t];var i=this.colYs.slice(t,t+e);return Math.max.apply(Math,i)},n._getHorizontalColPosition=function(t,e){var i=this.horizontalColIndex%this.cols,n=t>1&&i+t>this.cols;i=n?0:i;var o=e.size.outerWidth&&e.size.outerHeight;return this.horizontalColIndex=o?i+t:this.horizontalColIndex,{col:i,y:this._getColGroupY(i,t)}},n._manageStamp=function(t){var i=e(t),n=this._getElementOffset(t),o=this._getOption("originLeft"),r=o?n.left:n.right,s=r+i.outerWidth,a=Math.floor(r/this.columnWidth);a=Math.max(0,a);var h=Math.floor(s/this.columnWidth);h-=s%this.columnWidth?0:1,h=Math.min(this.cols-1,h);for(var u=this._getOption("originTop"),d=(u?n.top:n.bottom)+i.outerHeight,l=a;h>=l;l++)this.colYs[l]=Math.max(d,this.colYs[l]);},n._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var t={height:this.maxY};return this._getOption("fitWidth")&&(t.width=this._getContainerFitWidth()),t},n._getContainerFitWidth=function(){for(var t=0,e=this.cols;--e&&0===this.colYs[e];)t++;return (this.cols-t)*this.columnWidth-this.gutter},n.needsResizeLayout=function(){var t=this.containerWidth;return this.getContainerWidth(),t!=this.containerWidth},i});
|
|
606
|
+
// Initial layout
|
|
607
|
+
this.layout();
|
|
452
608
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
this.options = options;
|
|
457
|
-
this.paused = false;
|
|
458
|
-
this.activeIndex = 0;
|
|
609
|
+
// Set up observers
|
|
610
|
+
this.setupObservers();
|
|
611
|
+
}
|
|
459
612
|
|
|
460
|
-
|
|
461
|
-
|
|
613
|
+
setupObservers() {
|
|
614
|
+
// Debounce layout calls to avoid excessive recalculations
|
|
615
|
+
let layoutTimeout = null;
|
|
616
|
+
const debouncedLayout = () => {
|
|
617
|
+
if (layoutTimeout) clearTimeout(layoutTimeout);
|
|
618
|
+
layoutTimeout = setTimeout(() => this.layout(), 16);
|
|
462
619
|
};
|
|
463
620
|
|
|
464
|
-
|
|
465
|
-
this.
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
621
|
+
// Resize observer for responsive layouts AND child size changes
|
|
622
|
+
this.resizeObserver = new ResizeObserver(entries => {
|
|
623
|
+
// Check if it's the container or a child that resized
|
|
624
|
+
for (const entry of entries) {
|
|
625
|
+
if (
|
|
626
|
+
entry.target === this.container ||
|
|
627
|
+
entry.target.parentElement === this.container
|
|
628
|
+
) {
|
|
629
|
+
debouncedLayout();
|
|
630
|
+
break
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
this.resizeObserver.observe(this.container);
|
|
635
|
+
|
|
636
|
+
// Observe all direct children for size changes
|
|
637
|
+
for (const child of this.container.children) {
|
|
638
|
+
if (child.nodeType === Node.ELEMENT_NODE) {
|
|
639
|
+
this.resizeObserver.observe(child);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
470
642
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
643
|
+
// Mutation observer for dynamic content
|
|
644
|
+
this.mutationObserver = new MutationObserver(mutations => {
|
|
645
|
+
let shouldRelayout = false;
|
|
646
|
+
for (const mutation of mutations) {
|
|
647
|
+
if (mutation.type === "childList") {
|
|
648
|
+
// Observe new children
|
|
649
|
+
for (const node of mutation.addedNodes) {
|
|
650
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
651
|
+
this.resizeObserver.observe(node);
|
|
652
|
+
// Also watch for images in new nodes
|
|
653
|
+
this.observeImages(node);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
shouldRelayout = true;
|
|
657
|
+
} else if (
|
|
658
|
+
mutation.type === "attributes" &&
|
|
659
|
+
mutation.attributeName === "style"
|
|
660
|
+
) {
|
|
661
|
+
shouldRelayout = true;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
if (shouldRelayout) {
|
|
665
|
+
debouncedLayout();
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
this.mutationObserver.observe(this.container, {
|
|
669
|
+
childList: true,
|
|
670
|
+
subtree: false,
|
|
671
|
+
attributes: true,
|
|
672
|
+
attributeFilter: ["style", "class"]
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
// Observe all images for load events
|
|
676
|
+
this.observeImages(this.container);
|
|
677
|
+
}
|
|
474
678
|
|
|
475
|
-
|
|
476
|
-
|
|
679
|
+
observeImages(root) {
|
|
680
|
+
const images = root.querySelectorAll("img");
|
|
681
|
+
for (const img of images) {
|
|
682
|
+
if (!img.complete) {
|
|
683
|
+
img.addEventListener("load", () => this.layout(), { once: true });
|
|
684
|
+
img.addEventListener("error", () => this.layout(), { once: true });
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
477
688
|
|
|
478
|
-
|
|
479
|
-
|
|
689
|
+
layout() {
|
|
690
|
+
const styles = getGridLanesStyles(this.container);
|
|
691
|
+
const containerRect = this.container.getBoundingClientRect();
|
|
692
|
+
|
|
693
|
+
// Determine direction based on which template is defined
|
|
694
|
+
const hasColumns =
|
|
695
|
+
styles.gridTemplateColumns &&
|
|
696
|
+
styles.gridTemplateColumns !== "none" &&
|
|
697
|
+
!styles.gridTemplateColumns.startsWith("auto");
|
|
698
|
+
const hasRows =
|
|
699
|
+
styles.gridTemplateRows &&
|
|
700
|
+
styles.gridTemplateRows !== "none" &&
|
|
701
|
+
!styles.gridTemplateRows.startsWith("auto");
|
|
702
|
+
|
|
703
|
+
this.isVertical = hasColumns || !hasRows;
|
|
704
|
+
|
|
705
|
+
// Calculate lane sizes
|
|
706
|
+
if (this.isVertical) {
|
|
707
|
+
this.lanes = calculateLaneSizes(
|
|
708
|
+
styles.gridTemplateColumns,
|
|
709
|
+
containerRect.width,
|
|
710
|
+
styles.columnGap,
|
|
711
|
+
styles.fontSize,
|
|
712
|
+
styles.rootFontSize
|
|
713
|
+
) || [containerRect.width];
|
|
714
|
+
} else {
|
|
715
|
+
this.lanes = calculateLaneSizes(
|
|
716
|
+
styles.gridTemplateRows,
|
|
717
|
+
containerRect.height,
|
|
718
|
+
styles.rowGap,
|
|
719
|
+
styles.fontSize,
|
|
720
|
+
styles.rootFontSize
|
|
721
|
+
) || [containerRect.height];
|
|
722
|
+
}
|
|
480
723
|
|
|
481
|
-
|
|
724
|
+
// Initialize lane positions (heights for vertical, widths for horizontal)
|
|
725
|
+
this.laneHeights = new Array(this.lanes.length).fill(0);
|
|
726
|
+
|
|
727
|
+
// Get all direct children
|
|
728
|
+
const items = Array.from(this.container.children).filter(
|
|
729
|
+
el =>
|
|
730
|
+
el.nodeType === Node.ELEMENT_NODE &&
|
|
731
|
+
window.getComputedStyle(el).display !== "none"
|
|
732
|
+
);
|
|
733
|
+
|
|
734
|
+
// Separate explicitly placed items from auto-placed items
|
|
735
|
+
const explicitItems = [];
|
|
736
|
+
const autoItems = [];
|
|
737
|
+
|
|
738
|
+
for (const item of items) {
|
|
739
|
+
const itemStyles = getItemStyles(item);
|
|
740
|
+
if (this.isVertical && itemStyles.columnStart !== null) {
|
|
741
|
+
explicitItems.push({ element: item, styles: itemStyles });
|
|
742
|
+
} else if (!this.isVertical && itemStyles.rowStart !== null) {
|
|
743
|
+
explicitItems.push({ element: item, styles: itemStyles });
|
|
744
|
+
} else {
|
|
745
|
+
autoItems.push({ element: item, styles: itemStyles });
|
|
746
|
+
}
|
|
747
|
+
}
|
|
482
748
|
|
|
483
|
-
|
|
484
|
-
}
|
|
749
|
+
// Place explicitly positioned items first
|
|
750
|
+
for (const { element, styles: itemStyles } of explicitItems) {
|
|
751
|
+
this.placeExplicitItem(element, itemStyles, styles);
|
|
752
|
+
}
|
|
485
753
|
|
|
486
|
-
|
|
487
|
-
|
|
754
|
+
// Place auto-positioned items
|
|
755
|
+
for (const { element, styles: itemStyles } of autoItems) {
|
|
756
|
+
this.placeAutoItem(element, itemStyles, styles);
|
|
757
|
+
}
|
|
488
758
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}
|
|
759
|
+
// Set container height
|
|
760
|
+
const containerHeight = Math.max(...this.laneHeights);
|
|
761
|
+
this.container.style.minHeight = `${containerHeight}px`;
|
|
762
|
+
}
|
|
492
763
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
764
|
+
placeExplicitItem(element, itemStyles, containerStyles) {
|
|
765
|
+
const gap = this.isVertical
|
|
766
|
+
? containerStyles.columnGap
|
|
767
|
+
: containerStyles.rowGap;
|
|
768
|
+
const crossGap = this.isVertical
|
|
769
|
+
? containerStyles.rowGap
|
|
770
|
+
: containerStyles.columnGap;
|
|
771
|
+
|
|
772
|
+
let laneIndex;
|
|
773
|
+
let span;
|
|
774
|
+
|
|
775
|
+
if (this.isVertical) {
|
|
776
|
+
// Handle negative indices
|
|
777
|
+
laneIndex = itemStyles.columnStart;
|
|
778
|
+
if (laneIndex < 0) {
|
|
779
|
+
laneIndex = this.lanes.length + laneIndex + 1;
|
|
780
|
+
}
|
|
781
|
+
laneIndex = Math.max(0, Math.min(laneIndex - 1, this.lanes.length - 1));
|
|
782
|
+
span = itemStyles.columnSpan;
|
|
783
|
+
} else {
|
|
784
|
+
laneIndex = itemStyles.rowStart;
|
|
785
|
+
if (laneIndex < 0) {
|
|
786
|
+
laneIndex = this.lanes.length + laneIndex + 1;
|
|
787
|
+
}
|
|
788
|
+
laneIndex = Math.max(0, Math.min(laneIndex - 1, this.lanes.length - 1));
|
|
789
|
+
span = itemStyles.rowSpan;
|
|
790
|
+
}
|
|
496
791
|
|
|
497
|
-
|
|
498
|
-
|
|
792
|
+
// Calculate position
|
|
793
|
+
let position = 0;
|
|
794
|
+
for (let i = 0; i < laneIndex; i++) {
|
|
795
|
+
position += this.lanes[i] + gap;
|
|
796
|
+
}
|
|
499
797
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
798
|
+
// Calculate width (for spanning)
|
|
799
|
+
let size = 0;
|
|
800
|
+
const endLane = Math.min(laneIndex + span, this.lanes.length);
|
|
801
|
+
for (let i = laneIndex; i < endLane; i++) {
|
|
802
|
+
size += this.lanes[i];
|
|
803
|
+
if (i < endLane - 1) size += gap;
|
|
804
|
+
}
|
|
503
805
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
806
|
+
// Get the tallest lane in the span
|
|
807
|
+
let maxHeight = 0;
|
|
808
|
+
for (let i = laneIndex; i < endLane; i++) {
|
|
809
|
+
maxHeight = Math.max(maxHeight, this.laneHeights[i]);
|
|
810
|
+
}
|
|
507
811
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
812
|
+
// Position the element
|
|
813
|
+
element.style.position = "absolute";
|
|
814
|
+
|
|
815
|
+
if (this.isVertical) {
|
|
816
|
+
element.style.left = `${position}px`;
|
|
817
|
+
element.style.top = `${maxHeight > 0 ? maxHeight + crossGap : 0}px`;
|
|
818
|
+
element.style.width = `${size}px`;
|
|
819
|
+
} else {
|
|
820
|
+
element.style.top = `${position}px`;
|
|
821
|
+
element.style.left = `${maxHeight > 0 ? maxHeight + crossGap : 0}px`;
|
|
822
|
+
element.style.height = `${size}px`;
|
|
823
|
+
element.style.width = "";
|
|
824
|
+
}
|
|
511
825
|
|
|
512
|
-
|
|
513
|
-
|
|
826
|
+
// Update lane heights
|
|
827
|
+
const itemRect = element.getBoundingClientRect();
|
|
828
|
+
const itemSize = this.isVertical ? itemRect.height : itemRect.width;
|
|
829
|
+
const newHeight = maxHeight + (maxHeight > 0 ? crossGap : 0) + itemSize;
|
|
514
830
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
831
|
+
for (let i = laneIndex; i < endLane; i++) {
|
|
832
|
+
this.laneHeights[i] = newHeight;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
518
835
|
|
|
519
|
-
|
|
520
|
-
|
|
836
|
+
placeAutoItem(element, itemStyles, containerStyles) {
|
|
837
|
+
const gap = this.isVertical
|
|
838
|
+
? containerStyles.columnGap
|
|
839
|
+
: containerStyles.rowGap;
|
|
840
|
+
const crossGap = this.isVertical
|
|
841
|
+
? containerStyles.rowGap
|
|
842
|
+
: containerStyles.columnGap;
|
|
843
|
+
const tolerance = containerStyles.tolerance;
|
|
844
|
+
const span = Math.min(
|
|
845
|
+
this.isVertical ? itemStyles.columnSpan : itemStyles.rowSpan,
|
|
846
|
+
this.lanes.length
|
|
847
|
+
);
|
|
848
|
+
|
|
849
|
+
// Find the best lane(s) considering tolerance
|
|
850
|
+
let bestLane = 0;
|
|
851
|
+
let bestHeight = Infinity;
|
|
852
|
+
|
|
853
|
+
for (let i = 0; i <= this.lanes.length - span; i++) {
|
|
854
|
+
// Get the max height across the span
|
|
855
|
+
let maxHeight = 0;
|
|
856
|
+
for (let j = i; j < i + span; j++) {
|
|
857
|
+
maxHeight = Math.max(maxHeight, this.laneHeights[j]);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// Use tolerance to determine if this is meaningfully better
|
|
861
|
+
if (bestHeight - maxHeight > tolerance) {
|
|
862
|
+
bestHeight = maxHeight;
|
|
863
|
+
bestLane = i;
|
|
864
|
+
}
|
|
865
|
+
// Within tolerance: keep the current (earlier) bestLane — spec prefers earliest equivalent lane
|
|
866
|
+
}
|
|
521
867
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
868
|
+
// Calculate position
|
|
869
|
+
let position = 0;
|
|
870
|
+
for (let i = 0; i < bestLane; i++) {
|
|
871
|
+
position += this.lanes[i] + gap;
|
|
872
|
+
}
|
|
525
873
|
|
|
526
|
-
|
|
527
|
-
|
|
874
|
+
// Calculate size (for spanning)
|
|
875
|
+
let size = 0;
|
|
876
|
+
const endLane = Math.min(bestLane + span, this.lanes.length);
|
|
877
|
+
for (let i = bestLane; i < endLane; i++) {
|
|
878
|
+
size += this.lanes[i];
|
|
879
|
+
if (i < endLane - 1) size += gap;
|
|
880
|
+
}
|
|
528
881
|
|
|
529
|
-
|
|
530
|
-
|
|
882
|
+
// Position the element
|
|
883
|
+
element.style.position = "absolute";
|
|
884
|
+
|
|
885
|
+
if (this.isVertical) {
|
|
886
|
+
element.style.left = `${position}px`;
|
|
887
|
+
element.style.top = `${bestHeight > 0 ? bestHeight + crossGap : 0}px`;
|
|
888
|
+
element.style.width = `${size}px`;
|
|
889
|
+
} else {
|
|
890
|
+
element.style.top = `${position}px`;
|
|
891
|
+
element.style.left = `${bestHeight > 0 ? bestHeight + crossGap : 0}px`;
|
|
892
|
+
element.style.height = `${size}px`;
|
|
893
|
+
element.style.width = "";
|
|
894
|
+
}
|
|
531
895
|
|
|
532
|
-
|
|
533
|
-
|
|
896
|
+
// Update lane heights
|
|
897
|
+
const itemRect = element.getBoundingClientRect();
|
|
898
|
+
const itemSize = this.isVertical ? itemRect.height : itemRect.width;
|
|
899
|
+
const newHeight = bestHeight + (bestHeight > 0 ? crossGap : 0) + itemSize;
|
|
534
900
|
|
|
535
|
-
|
|
536
|
-
|
|
901
|
+
for (let i = bestLane; i < endLane; i++) {
|
|
902
|
+
this.laneHeights[i] = newHeight;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
537
905
|
|
|
538
|
-
|
|
539
|
-
|
|
906
|
+
destroy() {
|
|
907
|
+
if (this.resizeObserver) {
|
|
908
|
+
this.resizeObserver.disconnect();
|
|
909
|
+
}
|
|
910
|
+
if (this.mutationObserver) {
|
|
911
|
+
this.mutationObserver.disconnect();
|
|
912
|
+
}
|
|
540
913
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
914
|
+
this.container.removeAttribute(POLYFILL_ATTR);
|
|
915
|
+
this.container.style.position = "";
|
|
916
|
+
this.container.style.display = "";
|
|
917
|
+
this.container.style.minHeight = "";
|
|
918
|
+
|
|
919
|
+
// Reset item styles
|
|
920
|
+
for (const item of this.container.children) {
|
|
921
|
+
if (item.nodeType === Node.ELEMENT_NODE) {
|
|
922
|
+
item.style.position = "";
|
|
923
|
+
item.style.left = "";
|
|
924
|
+
item.style.top = "";
|
|
925
|
+
item.style.width = "";
|
|
926
|
+
item.style.height = "";
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
544
930
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
931
|
+
refresh() {
|
|
932
|
+
this.layout();
|
|
933
|
+
}
|
|
934
|
+
}
|
|
548
935
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
};
|
|
936
|
+
// ============================================================================
|
|
937
|
+
// PUBLIC API
|
|
938
|
+
// ============================================================================
|
|
555
939
|
|
|
940
|
+
/**
|
|
941
|
+
* Initialize the polyfill on all grid-lanes elements in the document
|
|
942
|
+
*/
|
|
943
|
+
function init(options = {}) {
|
|
944
|
+
// Check if native support exists
|
|
945
|
+
if (supportsGridLanes() && !options.force) {
|
|
946
|
+
console.log(
|
|
947
|
+
`${POLYFILL_NAME}: Native support detected, polyfill not needed.`
|
|
948
|
+
);
|
|
949
|
+
return { supported: true, instances: [] }
|
|
950
|
+
}
|
|
556
951
|
|
|
557
|
-
|
|
558
|
-
autoPlay: false,
|
|
559
|
-
interval: 5000 // in milliseconds
|
|
560
|
-
};
|
|
952
|
+
const instances = new Map();
|
|
561
953
|
|
|
954
|
+
// Process existing containers
|
|
955
|
+
const containers = findElements();
|
|
562
956
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
957
|
+
for (const container of containers) {
|
|
958
|
+
if (!container.hasAttribute(POLYFILL_ATTR)) {
|
|
959
|
+
instances.set(container, new GridLanesLayout(container, options));
|
|
960
|
+
}
|
|
961
|
+
}
|
|
568
962
|
|
|
569
|
-
|
|
570
|
-
|
|
963
|
+
// Watch for new stylesheets and elements
|
|
964
|
+
// Debounce for ancestor attribute changes to avoid excessive relayouts
|
|
965
|
+
let ancestorLayoutTimeout = null;
|
|
966
|
+
const pendingAncestorInstances = new Map();
|
|
967
|
+
const debouncedRelayoutAll = () => {
|
|
968
|
+
if (ancestorLayoutTimeout) clearTimeout(ancestorLayoutTimeout);
|
|
969
|
+
ancestorLayoutTimeout = setTimeout(() => {
|
|
970
|
+
for (const [container, instance] of pendingAncestorInstances) {
|
|
971
|
+
if (instances.has(container)) {
|
|
972
|
+
removeCachedStyle(container);
|
|
973
|
+
instance.refresh();
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
pendingAncestorInstances.clear();
|
|
977
|
+
}, 16);
|
|
571
978
|
};
|
|
572
979
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
(
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
980
|
+
const observer = new MutationObserver(mutations => {
|
|
981
|
+
for (const mutation of mutations) {
|
|
982
|
+
if (mutation.type === "attributes") {
|
|
983
|
+
removeCachedStyle(mutation.target);
|
|
984
|
+
// If the changed node is an ancestor of (or is) a container,
|
|
985
|
+
// cascaded/inherited styles on the container may have changed.
|
|
986
|
+
for (const [container] of instances) {
|
|
987
|
+
if (mutation.target.contains(container)) {
|
|
988
|
+
pendingAncestorInstances.set(container, instances.get(container));
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
if (pendingAncestorInstances.size > 0) {
|
|
992
|
+
debouncedRelayoutAll();
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
if (mutation.type === "childList") {
|
|
997
|
+
for (const node of mutation.addedNodes) {
|
|
998
|
+
if (node.nodeType !== node.ELEMENT_NODE) continue
|
|
999
|
+
|
|
1000
|
+
processSubtree(node, instances, options);
|
|
1001
|
+
}
|
|
1002
|
+
for (const node of mutation.removedNodes) {
|
|
1003
|
+
if (node.nodeType !== node.ELEMENT_NODE) continue
|
|
1004
|
+
if (instances.has(node)) {
|
|
1005
|
+
instances.get(node).destroy();
|
|
1006
|
+
instances.delete(node);
|
|
1007
|
+
}
|
|
1008
|
+
styleMap.delete(node);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
582
1011
|
}
|
|
583
|
-
};
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
observer.observe(document.documentElement, {
|
|
1015
|
+
childList: true,
|
|
1016
|
+
subtree: true,
|
|
1017
|
+
attributes: true,
|
|
1018
|
+
attributeFilter: ["style", "class"]
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
console.log(
|
|
1022
|
+
`${POLYFILL_NAME}: Initialized, ${instances.size} container(s) found.`
|
|
1023
|
+
);
|
|
1024
|
+
|
|
1025
|
+
return {
|
|
1026
|
+
supported: false,
|
|
1027
|
+
instances,
|
|
1028
|
+
observer,
|
|
1029
|
+
refresh() {
|
|
1030
|
+
for (const instance of instances.values()) {
|
|
1031
|
+
instance.refresh();
|
|
1032
|
+
}
|
|
1033
|
+
},
|
|
1034
|
+
destroy() {
|
|
1035
|
+
observer.disconnect();
|
|
1036
|
+
for (const instance of instances.values()) {
|
|
1037
|
+
instance.destroy();
|
|
1038
|
+
}
|
|
1039
|
+
instances.clear();
|
|
1040
|
+
// TODO: Ensure GC is triggered
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
584
1044
|
|
|
585
|
-
|
|
586
|
-
|
|
1045
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
1046
|
+
if (!supportsGridLanes()) {
|
|
1047
|
+
init({ force: true });
|
|
1048
|
+
}
|
|
1049
|
+
});
|
|
1050
|
+
|
|
1051
|
+
// When a thumbnail opens the slideshow modal, show the slide for that thumbnail.
|
|
1052
|
+
// Bootstrap's carousel reads the current slide from the DOM, so moving the
|
|
1053
|
+
// active class before the modal is shown is enough.
|
|
1054
|
+
document.addEventListener("show.bs.modal", (event) => {
|
|
1055
|
+
const slideTo = event.relatedTarget?.dataset.bsSlideTo;
|
|
1056
|
+
const items = event.target.querySelectorAll(".carousel-item");
|
|
1057
|
+
if (slideTo === undefined || !items[slideTo]) return
|
|
1058
|
+
|
|
1059
|
+
items.forEach((item) => item.classList.remove("active"));
|
|
1060
|
+
items[slideTo].classList.add("active");
|
|
1061
|
+
});
|
|
587
1062
|
//# sourceMappingURL=blacklight-gallery.esm.js.map
|