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