smartphoto 2.1.4 → 2.1.7
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.
- package/README.md +13 -5
- package/css/smartphoto.css +29 -18
- package/css/smartphoto.min.css +1 -1
- package/js/jquery-smartphoto.js +129 -20
- package/js/jquery-smartphoto.min.js +2 -2
- package/js/smartphoto.js +129 -20
- package/js/smartphoto.min.js +2 -2
- package/lib/smartphoto.js +127 -19
- package/lib/smartphoto.mjs +127 -19
- package/lib/types/core/index.d.ts +9 -5
- package/lib/types/core/state.d.ts +6 -6
- package/lib/types/core/types.d.ts +13 -11
- package/lib/types/core/view.d.ts +2 -2
- package/lib/types/index.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,6 +70,14 @@ document.addEventListener('DOMContentLoaded',function(){
|
|
|
70
70
|
</script>
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
When SmartPhoto is constructed with a CSS selector string (as above), clicks are handled via a single delegated listener, so elements added to the page **after** construction (e.g. by Ajax/infinite scroll) are picked up automatically just by clicking them — no need to call `addItem()`/`addNewItem()` manually. Right before a photo is opened, SmartPhoto also reconciles that photo's group against the current DOM: newly appended matching elements are added, and elements that have since been removed from the DOM are dropped from the group (remaining indices are recalculated). This auto-detection only applies to the selector-string form; when a `NodeList`/`Element[]` is passed (or in data source mode below), add/remove items explicitly via `addItem()`/`addNewItem()`.
|
|
74
|
+
|
|
75
|
+
A few things to keep in mind:
|
|
76
|
+
- Reconciliation only happens **right before a photo is opened** (via a click, `show()`, or hash restoration) — not continuously. If an element disappears from the DOM while the viewer is already open and you `next()`/`prev()` through the same session, that removal isn't reflected until the viewer is opened again.
|
|
77
|
+
- It does not support replacing an entire container's `innerHTML` (which recreates existing elements too, as brand-new DOM nodes) — that produces duplicate items, since the old and new elements aren't recognized as the same one. Only *appending*/*removing* individual elements is supported; if you regenerate the whole container, call `destroy()` and construct a new instance instead.
|
|
78
|
+
- Changing `data-group` on an element that has already been opened/registered has no effect (the group is fixed at first registration). Changing it before the element is first interacted with is picked up correctly.
|
|
79
|
+
- If multiple instances are built with overlapping selectors, avoid relying on distinguishing exactly which instance handles a click for elements that could match either.
|
|
80
|
+
|
|
73
81
|
### Programmatic usage (data source mode)
|
|
74
82
|
|
|
75
83
|
Instead of scanning `<a>` elements in the page, you can pass an array of slide objects directly (inspired by [yet-another-react-lightbox](https://yet-another-react-lightbox.com/)). This is useful when your images come from an API or a JS-rendered list.
|
|
@@ -211,7 +219,7 @@ Slide fields:
|
|
|
211
219
|
<tr>
|
|
212
220
|
<td>animationSpeed</td>
|
|
213
221
|
<td>animation speed (ms) when switching/opening/closing images</td>
|
|
214
|
-
<td>
|
|
222
|
+
<td>450</td>
|
|
215
223
|
</tr>
|
|
216
224
|
<tr>
|
|
217
225
|
<td>forceInterval</td>
|
|
@@ -337,7 +345,7 @@ photo.on('zoomout',function(){
|
|
|
337
345
|
</tr>
|
|
338
346
|
<tr>
|
|
339
347
|
<td><code>addNewItem(element)</code></td>
|
|
340
|
-
<td>register a new <code><a></code> thumbnail element (HTML mode)</td>
|
|
348
|
+
<td>register a new <code><a></code> thumbnail element (HTML mode). Only needed when constructed with a <code>NodeList</code>/<code>Element[]</code> or otherwise not using a selector string — with a selector string, elements added later are auto-detected on click (see above)</td>
|
|
341
349
|
</tr>
|
|
342
350
|
<tr>
|
|
343
351
|
<td><code>show(indexOrId?, options?)</code></td>
|
|
@@ -353,7 +361,7 @@ photo.on('zoomout',function(){
|
|
|
353
361
|
</tr>
|
|
354
362
|
<tr>
|
|
355
363
|
<td><code>addItem(slideOrElement)</code></td>
|
|
356
|
-
<td>add a new item. Accepts a slide object (data source mode) or an <code>Element</code> (HTML mode, same as <code>addNewItem</code>)</td>
|
|
364
|
+
<td>add a new item. Accepts a slide object (data source mode, where explicit registration is always required) or an <code>Element</code> (HTML mode, same caveat as <code>addNewItem</code>)</td>
|
|
357
365
|
</tr>
|
|
358
366
|
<tr>
|
|
359
367
|
<td><code>currentIndex</code></td>
|
|
@@ -372,7 +380,7 @@ photo.on('zoomout',function(){
|
|
|
372
380
|
<tr>
|
|
373
381
|
<td>--smartphoto-animation-speed</td>
|
|
374
382
|
<td>animation speed when switching/opening/closing images. Overridden per-instance by the <code>animationSpeed</code> JS option</td>
|
|
375
|
-
<td>
|
|
383
|
+
<td>450ms</td>
|
|
376
384
|
</tr>
|
|
377
385
|
<tr>
|
|
378
386
|
<td>--smartphoto-animation-function</td>
|
|
@@ -395,7 +403,7 @@ Set these on `.smartphoto` (or `:root`) to override the defaults, no rebuild req
|
|
|
395
403
|
|
|
396
404
|
```css
|
|
397
405
|
.smartphoto {
|
|
398
|
-
--smartphoto-animation-speed:
|
|
406
|
+
--smartphoto-animation-speed: 450ms;
|
|
399
407
|
--smartphoto-animation-function: ease-in-out;
|
|
400
408
|
--smartphoto-backdrop-color: rgba(0, 0, 0, 0.9);
|
|
401
409
|
--smartphoto-header-color: rgba(0, 0, 0, 0.4);
|
package/css/smartphoto.css
CHANGED
|
@@ -110,15 +110,26 @@
|
|
|
110
110
|
* 対象に加えることで、opacity のフェードが完了するまでその適用を1フレーム分
|
|
111
111
|
* 遅らせ、閉じる瞬間に「ぱっと」消えず滑らかにフェードアウトするようにする */
|
|
112
112
|
transition:
|
|
113
|
-
opacity var(--smartphoto-animation-speed, 0.
|
|
114
|
-
display var(--smartphoto-animation-speed, 0.
|
|
115
|
-
overlay var(--smartphoto-animation-speed, 0.
|
|
113
|
+
opacity var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out),
|
|
114
|
+
display var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out) allow-discrete,
|
|
115
|
+
overlay var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out) allow-discrete;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
.smartphoto:not([open]) {
|
|
119
119
|
opacity: 0;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
/* ブラウザ標準の dialog:not([open]) { display: none } は、Bootstrap4 系の
|
|
123
|
+
* reboot.css 等が互換性維持のために `dialog { display: block; }` のような
|
|
124
|
+
* 要素セレクタ単体のルールを読み込んでいる場合、後勝ちで上書きされてしまう。
|
|
125
|
+
* 上書きされると閉じている dialog(position:fixed; inset:0)が画面全体に
|
|
126
|
+
* 残ったままクリックを吸収し続けるため、クラスセレクタを含めて詳細度を上げた
|
|
127
|
+
* フォールバックを明示しておく(要素セレクタ単体より詳細度が高いため、
|
|
128
|
+
* 読み込み順に関係なく確実に勝てる) */
|
|
129
|
+
dialog.smartphoto:not([open]) {
|
|
130
|
+
display: none !important;
|
|
131
|
+
}
|
|
132
|
+
|
|
122
133
|
.smartphoto::backdrop {
|
|
123
134
|
background-color: var(--smartphoto-backdrop-color, rgba(0, 0, 0, 1));
|
|
124
135
|
}
|
|
@@ -127,11 +138,11 @@
|
|
|
127
138
|
* ルート要素(html)の子として扱われ、dialog に設定した --smartphoto-animation-speed を
|
|
128
139
|
* 継承しない。そのため JS 側では document.documentElement にも同じ変数を設定しており、
|
|
129
140
|
* ここではその値を参照する。指定がなければブラウザ既定(実装依存, 概ね0.25s前後で
|
|
130
|
-
* 速すぎるとの声があった)の代わりに 0.
|
|
141
|
+
* 速すぎるとの声があった)の代わりに 0.45s を使う */
|
|
131
142
|
::view-transition-group(smartphoto-hero),
|
|
132
143
|
::view-transition-old(smartphoto-hero),
|
|
133
144
|
::view-transition-new(smartphoto-hero) {
|
|
134
|
-
animation-duration: var(--smartphoto-animation-speed, 0.
|
|
145
|
+
animation-duration: var(--smartphoto-animation-speed, 0.45s);
|
|
135
146
|
animation-timing-function: var(--smartphoto-animation-function, ease-out);
|
|
136
147
|
}
|
|
137
148
|
|
|
@@ -213,7 +224,7 @@
|
|
|
213
224
|
-moz-user-select: none;
|
|
214
225
|
-ms-user-select: none;
|
|
215
226
|
user-select: none;
|
|
216
|
-
transition: transform var(--smartphoto-animation-speed, 0.
|
|
227
|
+
transition: transform var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out);
|
|
217
228
|
|
|
218
229
|
-webkit-user-drag: none;
|
|
219
230
|
}
|
|
@@ -229,7 +240,7 @@
|
|
|
229
240
|
}
|
|
230
241
|
|
|
231
242
|
.smartphoto-img-elasticmove {
|
|
232
|
-
transition: transform var(--smartphoto-animation-speed, 0.
|
|
243
|
+
transition: transform var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out);
|
|
233
244
|
}
|
|
234
245
|
|
|
235
246
|
.smartphoto-img-wrap {
|
|
@@ -237,13 +248,13 @@
|
|
|
237
248
|
opacity: 1;
|
|
238
249
|
/* Pointer Events(ピンチ/ドラッグ)がブラウザ既定のスクロール・ズームと衝突しないようにする */
|
|
239
250
|
touch-action: none;
|
|
240
|
-
-webkit-transition: opacity var(--smartphoto-animation-speed, 0.
|
|
241
|
-
-moz-transition: opacity var(--smartphoto-animation-speed, 0.
|
|
242
|
-
-ms-transition: opacity var(--smartphoto-animation-speed, 0.
|
|
243
|
-
-o-transition: opacity var(--smartphoto-animation-speed, 0.
|
|
244
|
-
transition: opacity var(--smartphoto-animation-speed, 0.
|
|
251
|
+
-webkit-transition: opacity var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out);
|
|
252
|
+
-moz-transition: opacity var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out);
|
|
253
|
+
-ms-transition: opacity var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out);
|
|
254
|
+
-o-transition: opacity var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out);
|
|
255
|
+
transition: opacity var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out);
|
|
245
256
|
animation-name: smartphoto-img-wrap;
|
|
246
|
-
animation-duration: var(--smartphoto-animation-speed, 0.
|
|
257
|
+
animation-duration: var(--smartphoto-animation-speed, 0.45s);
|
|
247
258
|
animation-timing-function: var(--smartphoto-animation-function, ease-out);
|
|
248
259
|
}
|
|
249
260
|
|
|
@@ -265,7 +276,7 @@
|
|
|
265
276
|
left: 0;
|
|
266
277
|
opacity: 1;
|
|
267
278
|
animation-name: smartphoto-appear;
|
|
268
|
-
animation-duration: var(--smartphoto-animation-speed, 0.
|
|
279
|
+
animation-duration: var(--smartphoto-animation-speed, 0.45s);
|
|
269
280
|
animation-timing-function: var(--smartphoto-animation-function, ease-out);
|
|
270
281
|
}
|
|
271
282
|
|
|
@@ -282,7 +293,7 @@
|
|
|
282
293
|
height: 30px;
|
|
283
294
|
margin-top: -20px;
|
|
284
295
|
box-sizing: content-box;
|
|
285
|
-
animation-duration: var(--smartphoto-animation-speed, 0.
|
|
296
|
+
animation-duration: var(--smartphoto-animation-speed, 0.45s);
|
|
286
297
|
animation-timing-function: var(--smartphoto-animation-function, ease-out);
|
|
287
298
|
animation-name: smartphoto-appear;
|
|
288
299
|
}
|
|
@@ -341,7 +352,7 @@
|
|
|
341
352
|
width: 100%;
|
|
342
353
|
opacity: 1;
|
|
343
354
|
animation-name: smartphoto-appear;
|
|
344
|
-
animation-duration: var(--smartphoto-animation-speed, 0.
|
|
355
|
+
animation-duration: var(--smartphoto-animation-speed, 0.45s);
|
|
345
356
|
animation-timing-function: var(--smartphoto-animation-function, ease-out);
|
|
346
357
|
}
|
|
347
358
|
|
|
@@ -417,7 +428,7 @@
|
|
|
417
428
|
left: 0;
|
|
418
429
|
width: 100%;
|
|
419
430
|
height: 100%;
|
|
420
|
-
transition: all var(--smartphoto-animation-speed, 0.
|
|
431
|
+
transition: all var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out);
|
|
421
432
|
}
|
|
422
433
|
|
|
423
434
|
.smartphoto-list li:focus {
|
|
@@ -485,7 +496,7 @@
|
|
|
485
496
|
z-index: 100;
|
|
486
497
|
top: 0;
|
|
487
498
|
left: 0;
|
|
488
|
-
transition: all var(--smartphoto-animation-speed, 0.
|
|
499
|
+
transition: all var(--smartphoto-animation-speed, 0.45s) var(--smartphoto-animation-function, ease-out);
|
|
489
500
|
}
|
|
490
501
|
|
|
491
502
|
.smartphoto-sr-only {
|
package/css/smartphoto.min.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@keyframes smartphoto{0%{opacity:0}to{opacity:1}}@keyframes smartphoto-img-wrap{0%{opacity:0}to{opacity:1}}@keyframes smartphoto-inner{0%{transform:translateY(100px)}to{transform:translate(0)}}@keyframes smartphoto-loader{0%{opacity:.4;transform:rotate(0deg)}50%{opacity:1;transform:rotate(180deg)}to{opacity:.4;transform:rotate(1turn)}}@keyframes smartphoto-appear{0%{opacity:0}to{opacity:1}}@keyframes smartphoto-hide{0%{opacity:1}to{opacity:0}}:root:has(dialog.smartphoto[open]){overflow:hidden}.smartphoto{border:none;background:transparent;padding:0;margin:0;outline:none;position:fixed;inset:0;width:100%;height:100%;max-width:100%;max-height:100%;overflow:hidden;height:var(--smartphoto-vh,100dvh);max-height:var(--smartphoto-vh,100dvh);background-color:var(--smartphoto-backdrop-color,#000);opacity:1;font-family:sans-serif;cursor:pointer;transition:opacity var(--smartphoto-animation-speed,.
|
|
1
|
+
@keyframes smartphoto{0%{opacity:0}to{opacity:1}}@keyframes smartphoto-img-wrap{0%{opacity:0}to{opacity:1}}@keyframes smartphoto-inner{0%{transform:translateY(100px)}to{transform:translate(0)}}@keyframes smartphoto-loader{0%{opacity:.4;transform:rotate(0deg)}50%{opacity:1;transform:rotate(180deg)}to{opacity:.4;transform:rotate(1turn)}}@keyframes smartphoto-appear{0%{opacity:0}to{opacity:1}}@keyframes smartphoto-hide{0%{opacity:1}to{opacity:0}}:root:has(dialog.smartphoto[open]){overflow:hidden}.smartphoto{border:none;background:transparent;padding:0;margin:0;outline:none;position:fixed;inset:0;width:100%;height:100%;max-width:100%;max-height:100%;overflow:hidden;height:var(--smartphoto-vh,100dvh);max-height:var(--smartphoto-vh,100dvh);background-color:var(--smartphoto-backdrop-color,#000);opacity:1;font-family:sans-serif;cursor:pointer;transition:opacity var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out),display var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out) allow-discrete,overlay var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out) allow-discrete}.smartphoto:not([open]){opacity:0}dialog.smartphoto:not([open]){display:none!important}.smartphoto::backdrop{background-color:var(--smartphoto-backdrop-color,#000)}::view-transition-group(smartphoto-hero),::view-transition-new(smartphoto-hero),::view-transition-old(smartphoto-hero){animation-duration:var(--smartphoto-animation-speed,.45s);animation-timing-function:var(--smartphoto-animation-function,ease-out)}.smartphoto-close{opacity:0}.smartphoto-count{display:inline-block;color:#fff;font-size:16px}.smartphoto-header{display:block;box-sizing:border-box;position:fixed;z-index:102;top:0;left:0;width:100%;height:50px;padding:15px;background-color:var(--smartphoto-header-color,rgba(0,0,0,.2))}.smartphoto-content{display:block;position:absolute;top:0;left:0;width:100%;height:100%;touch-action:none}.smartphoto-dismiss{display:block;position:absolute;top:15px;right:10px;width:20px;height:20px;padding:0;border:none;background-color:transparent;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHZpZXdCb3g9IjAgMCAyODM0LjY1IDI4MzQuNjUiPjx0aXRsZT5pY29uPC90aXRsZT48cGF0aCBkPSJNMTU3Ni40MiAxNDA2Ljc2IDI3ODQgMTk5LjE5YTU2Ljg2IDU2Ljg2IDAgMCAwIDAtODAuMThsLTc4LjkyLTc4LjkyYTU2Ljg2IDU2Ljg2IDAgMCAwLTgwLjE4IDBMMTQxNy4zMiAxMjQ3LjY2IDIwOS43NSA0MC4wOWE1Ni44NiA1Ni44NiAwIDAgMC04MC4xOCAwTDUwLjY1IDExOWE1Ni44NiA1Ni44NiAwIDAgMCAwIDgwLjE4bDEyMDcuNTggMTIwNy41OEw1MC42NSAyNjE0LjM0YTU2Ljg2IDU2Ljg2IDAgMCAwIDAgODAuMThsNzguOTIgNzguOTJhNTYuODYgNTYuODYgMCAwIDAgODAuMTggMGwxMjA3LjU3LTEyMDcuNThMMjYyNC45IDI3NzMuNDRhNTYuODYgNTYuODYgMCAwIDAgODAuMTggMGw3OC45Mi03OC45MmE1Ni44NiA1Ni44NiAwIDAgMCAwLTgwLjE4WiIvPjwvc3ZnPg==);text-shadow:0 1px 0 #fff;color:#fff;font-size:30px;text-decoration:none;cursor:pointer;line-height:1}.smartphoto-body{z-index:102;margin:0 auto}.smartphoto-body,.smartphoto-inner{position:relative;width:100%;height:100%}.smartphoto-inner{vertical-align:top}.smartphoto-img{display:none;max-width:none;width:auto;height:auto;cursor:zoom-in;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition:transform var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out);-webkit-user-drag:none}.smartphoto-img.active{display:block}.smartphoto-img-onmove{cursor:grab;cursor:-webkit-grab;transition:none}.smartphoto-img-elasticmove{transition:transform var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out)}.smartphoto-img-wrap{display:inline-block;opacity:1;touch-action:none;-webkit-transition:opacity var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out);-moz-transition:opacity var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out);-ms-transition:opacity var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out);-o-transition:opacity var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out);transition:opacity var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out);animation-name:smartphoto-img-wrap;animation-duration:var(--smartphoto-animation-speed,.45s);animation-timing-function:var(--smartphoto-animation-function,ease-out)}.smartphoto-img-left{transform:translateX(150%)!important}.smartphoto-img-right{transform:translateX(-150%)!important}.smartphoto-arrows{list-style-type:none;margin:0;padding:0;position:relative;z-index:1002;top:50%;left:0;opacity:1;animation-name:smartphoto-appear;animation-duration:var(--smartphoto-animation-speed,.45s);animation-timing-function:var(--smartphoto-animation-function,ease-out)}.smartphoto-arrows[aria-hidden=true]{animation-name:smartphoto-hide;display:none}.smartphoto-arrows li{display:block;position:absolute;top:50%;width:30px;height:30px;margin-top:-20px;box-sizing:content-box;animation-duration:var(--smartphoto-animation-speed,.45s);animation-timing-function:var(--smartphoto-animation-function,ease-out);animation-name:smartphoto-appear}.smartphoto-arrows li:focus{outline:none}.smartphoto-arrows [aria-hidden=true]{animation-name:smartphoto-hide;display:none}.smartphoto-arrows button{appearance:none;display:block;width:100%;height:100%;margin:0;padding:0;border:none;background-color:transparent;cursor:pointer}.smartphoto-arrow-right{right:0;padding:5px 0;background-color:rgba(0,0,0,.5)}.smartphoto-arrow-right button{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHZpZXdCb3g9IjAgMCAyODM0LjY1IDI4MzQuNjUiPjx0aXRsZT5pY29uPC90aXRsZT48cGF0aCBkPSJNMTgzNy44OCAxNDE3LjMyIDY0My41OSAyMjNhNzIuMjEgNzIuMjEgMCAwIDEgMC0xMDEuODJMNzQzLjgyIDIxYTcyLjIxIDcyLjIxIDAgMCAxIDEwMS44MiAwbDEyNDUuMTkgMTI0NS4xOSAxMDAuMjMgMTAwLjIzYTcyLjIxIDcyLjIxIDAgMCAxIDAgMTAxLjgyTDg0NS42NCAyODEzLjY1YTcyLjIxIDcyLjIxIDAgMCAxLTEwMS44MiAwbC0xMDAuMjMtMTAwLjIzYTcyLjIxIDcyLjIxIDAgMCAxIDAtMTAxLjgyWiIvPjwvc3ZnPg==)}.smartphoto-arrow-left{left:0;padding:5px 0;background-color:rgba(0,0,0,.5)}.smartphoto-arrow-left button{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiNmZmYiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHZpZXdCb3g9IjAgMCAyODM0LjY1IDI4MzQuNjUiPjx0aXRsZT5pY29uPC90aXRsZT48cGF0aCBkPSJNOTk2Ljc3IDE0MTcuMzIgMjE5MS4wNiAyMjNhNzIuMjEgNzIuMjEgMCAwIDAgMC0xMDEuODJMMjA5MC44MyAyMUE3Mi4yMSA3Mi4yMSAwIDAgMCAxOTg5IDIxTDc0My44MiAxMjY2LjE5bC0xMDAuMjMgMTAwLjIzYTcyLjIxIDcyLjIxIDAgMCAwIDAgMTAxLjgyTDE5ODkgMjgxMy42NWE3Mi4yMSA3Mi4yMSAwIDAgMCAxMDEuODIgMGwxMDAuMjMtMTAwLjIzYTcyLjIxIDcyLjIxIDAgMCAwIDAtMTAxLjgyWiIvPjwvc3ZnPg==)}.smartPhotoArrowHideIcon{display:none}.smartphoto-nav{position:absolute;bottom:0;left:0;width:100%;opacity:1;animation-name:smartphoto-appear;animation-duration:var(--smartphoto-animation-speed,.45s);animation-timing-function:var(--smartphoto-animation-function,ease-out)}.smartphoto-nav[aria-hidden=true]{animation-name:smartphoto-hide;display:none}.smartphoto-nav ul{display:block;overflow-x:auto;list-style:none;margin:0;padding:0;text-align:center;white-space:nowrap;-webkit-overflow-scrolling:touch}.smartphoto-nav li{display:inline-block;overflow:hidden;width:50px;height:50px}.smartphoto-nav button{appearance:none;display:block;width:100%;height:100%;margin:0;padding:0;border:none;background-color:#fff;background-position:50%;background-size:cover;opacity:.5;cursor:pointer}.smartphoto-nav button:focus{opacity:.8}.smartphoto-nav button.current{opacity:1}.smartphoto-nav img{width:auto;height:100%}.smartphoto-list{list-style-type:none;position:absolute;z-index:101;top:0;left:0;margin:0;padding:0;white-space:nowrap}.smartphoto-list li{display:block;position:absolute;top:0;left:0;width:100%;height:100%;transition:all var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out)}.smartphoto-list li:focus{outline:none}.smartphoto-list-onmove{transition:all .3s var(--smartphoto-animation-function,ease-out)}.smartphoto-caption{overflow:hidden;box-sizing:border-box;position:absolute;top:0;left:0;width:100%;height:50px;padding:0 50px;color:#fff;font-size:12px;text-align:center;line-height:50px;white-space:nowrap;text-overflow:ellipsis;margin:0;font-weight:400}.smartphoto-caption:focus{outline:none}.smartphoto-loader-wrap{display:block;position:relative;z-index:103;width:0;height:0;transform:translate(50vw,50vh);transform:translate(50vw,50dvh);transform:translate(50vw,calc(var(--smartphoto-vh, 100dvh)/2))}.smartphoto-loader{position:absolute;z-index:101;top:0;left:0;width:30px;height:30px;margin-top:-25px;margin-left:-25px;border:8px solid #17cddd;border-right-color:transparent;border-radius:50%;animation:smartphoto-loader .5s linear infinite}.smartphoto-img-clone{position:fixed;z-index:100;top:0;left:0;transition:all var(--smartphoto-animation-speed,.45s) var(--smartphoto-animation-function,ease-out)}.smartphoto-sr-only{overflow:hidden;position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;clip:rect(0,0,0,0)}
|
package/js/jquery-smartphoto.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* SmartPhoto v2.1.
|
|
2
|
+
* SmartPhoto v2.1.7
|
|
3
3
|
* (c) appleple
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
loadOffset: 2,
|
|
115
115
|
resizeStyle: "fit",
|
|
116
116
|
lazyAttribute: "data-src",
|
|
117
|
-
animationSpeed:
|
|
117
|
+
animationSpeed: 450
|
|
118
118
|
};
|
|
119
119
|
function deepFreeze(obj) {
|
|
120
120
|
Object.keys(obj).forEach((key) => {
|
|
@@ -128,7 +128,11 @@
|
|
|
128
128
|
function createState(settings) {
|
|
129
129
|
return {
|
|
130
130
|
options: deepFreeze(
|
|
131
|
-
extend(
|
|
131
|
+
extend(
|
|
132
|
+
{},
|
|
133
|
+
defaults,
|
|
134
|
+
settings
|
|
135
|
+
)
|
|
132
136
|
),
|
|
133
137
|
viewer: {
|
|
134
138
|
isOpen: false,
|
|
@@ -793,6 +797,7 @@
|
|
|
793
797
|
const dialog = document.createElement("dialog");
|
|
794
798
|
dialog.className = classNames.smartPhoto;
|
|
795
799
|
dialog.setAttribute("aria-labelledby", `smartphoto-${id}-title`);
|
|
800
|
+
dialog.style.display = "none";
|
|
796
801
|
dialog.style.setProperty(
|
|
797
802
|
"--smartphoto-animation-speed",
|
|
798
803
|
`${options.animationSpeed}ms`
|
|
@@ -1139,6 +1144,44 @@
|
|
|
1139
1144
|
this.timeouts = [];
|
|
1140
1145
|
this.loadAllFired = /* @__PURE__ */ new Set();
|
|
1141
1146
|
this.syncedGroupId = null;
|
|
1147
|
+
// 文字列セレクタで構築された場合のみ設定される。Ajax等で後から追加された
|
|
1148
|
+
// 要素をクリック時に動的検出するための再スキャン起点(§discoverGroupElements)
|
|
1149
|
+
this.rootSelector = null;
|
|
1150
|
+
// クリックされた要素(またはその祖先)から登録済み Item を逆引きするための
|
|
1151
|
+
// キャッシュ。documentへのイベントデリゲーションで祖先チェーンを辿る際に使う
|
|
1152
|
+
this.itemsByElement = /* @__PURE__ */ new Map();
|
|
1153
|
+
// サムネイルクリックはこの1本の document デリゲーションリスナーだけで処理する
|
|
1154
|
+
// (個別バインドは廃止)。同じクリックイベントを複数の SmartPhoto インスタンスが
|
|
1155
|
+
// 二重処理しないよう、処理済みマーカーをイベント自体に立てて後続インスタンスに
|
|
1156
|
+
// 早期returnさせる(セレクタが重複するインスタンスが同時に存在するケース)
|
|
1157
|
+
this.handleDocumentClick = (e) => {
|
|
1158
|
+
if (!(e.target instanceof Element)) {
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
const marker = e;
|
|
1162
|
+
if (marker.__smartphotoClaimed) {
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
let matched = this.findRegisteredAncestor(e.target);
|
|
1166
|
+
if (!matched && this.rootSelector) {
|
|
1167
|
+
matched = e.target.closest(this.rootSelector);
|
|
1168
|
+
}
|
|
1169
|
+
if (!matched) {
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
e.preventDefault();
|
|
1173
|
+
marker.__smartphotoClaimed = true;
|
|
1174
|
+
if (!this.itemsByElement.has(matched) && this.rootSelector) {
|
|
1175
|
+
const groupId = groupIdFromElement(matched);
|
|
1176
|
+
if (this.resyncGroupFromDom(groupId)) {
|
|
1177
|
+
this.syncCurrentGroupView();
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
const item = this.itemsByElement.get(matched);
|
|
1181
|
+
if (item) {
|
|
1182
|
+
this.openPhoto(item, matched);
|
|
1183
|
+
}
|
|
1184
|
+
};
|
|
1142
1185
|
// ---- 内部: window イベント ----
|
|
1143
1186
|
this.updateViewportHeight = () => {
|
|
1144
1187
|
this.view.refs.dialog.style.setProperty(
|
|
@@ -1150,6 +1193,7 @@
|
|
|
1150
1193
|
if (!currentItems(this.state)) {
|
|
1151
1194
|
return;
|
|
1152
1195
|
}
|
|
1196
|
+
this.updateViewportHeight();
|
|
1153
1197
|
this.resetTranslateCurrent();
|
|
1154
1198
|
this.setPosByCurrentIndex();
|
|
1155
1199
|
this.setSizeByScreen();
|
|
@@ -1172,6 +1216,7 @@
|
|
|
1172
1216
|
if (!currentItems(this.state)) {
|
|
1173
1217
|
return;
|
|
1174
1218
|
}
|
|
1219
|
+
this.updateViewportHeight();
|
|
1175
1220
|
this.resetTranslateCurrent();
|
|
1176
1221
|
this.setPosByCurrentIndex();
|
|
1177
1222
|
this.setHashByCurrentIndex();
|
|
@@ -1182,6 +1227,7 @@
|
|
|
1182
1227
|
const poll = (time) => {
|
|
1183
1228
|
this.scheduleTimeout(() => {
|
|
1184
1229
|
if (prevWidth !== getWindowWidth()) {
|
|
1230
|
+
this.updateViewportHeight();
|
|
1185
1231
|
this.resetTranslateCurrent();
|
|
1186
1232
|
this.setPosByCurrentIndex();
|
|
1187
1233
|
this.setHashByCurrentIndex();
|
|
@@ -1194,6 +1240,7 @@
|
|
|
1194
1240
|
};
|
|
1195
1241
|
poll(0);
|
|
1196
1242
|
};
|
|
1243
|
+
this.rootSelector = typeof source === "string" ? source : null;
|
|
1197
1244
|
this.state = createState(settings != null ? settings : {});
|
|
1198
1245
|
this.view = createView(
|
|
1199
1246
|
{ id: this.id, options: this.state.options },
|
|
@@ -1215,15 +1262,14 @@
|
|
|
1215
1262
|
},
|
|
1216
1263
|
{ signal: this.abortController.signal }
|
|
1217
1264
|
);
|
|
1265
|
+
document.addEventListener("click", this.handleDocumentClick, {
|
|
1266
|
+
signal: this.abortController.signal
|
|
1267
|
+
});
|
|
1218
1268
|
this.ingestSource(source);
|
|
1219
1269
|
this.syncCurrentGroupView();
|
|
1220
1270
|
const restored = this.restoreFromHash();
|
|
1221
1271
|
if (restored) {
|
|
1222
|
-
|
|
1223
|
-
triggerEvent(restored.element, "click");
|
|
1224
|
-
} else {
|
|
1225
|
-
this.openPhoto(restored, null);
|
|
1226
|
-
}
|
|
1272
|
+
this.openPhoto(restored, restored.element);
|
|
1227
1273
|
}
|
|
1228
1274
|
this.updateViewportHeight();
|
|
1229
1275
|
if (window.visualViewport) {
|
|
@@ -1268,6 +1314,7 @@
|
|
|
1268
1314
|
clearTimeout(id);
|
|
1269
1315
|
});
|
|
1270
1316
|
this.timeouts = [];
|
|
1317
|
+
this.itemsByElement.clear();
|
|
1271
1318
|
this.gestures.detach();
|
|
1272
1319
|
this.view.destroy();
|
|
1273
1320
|
}
|
|
@@ -1382,7 +1429,7 @@
|
|
|
1382
1429
|
this.gotoSlide(this.state.viewer.prev);
|
|
1383
1430
|
}
|
|
1384
1431
|
addItem(slideOrElement) {
|
|
1385
|
-
const item = slideOrElement instanceof
|
|
1432
|
+
const item = slideOrElement instanceof HTMLElement ? this.addElementItem(slideOrElement) : this.addSlideItem(slideOrElement);
|
|
1386
1433
|
this.syncCurrentGroupView();
|
|
1387
1434
|
return item;
|
|
1388
1435
|
}
|
|
@@ -1414,7 +1461,7 @@
|
|
|
1414
1461
|
);
|
|
1415
1462
|
addItemToGroup(this.state, item);
|
|
1416
1463
|
this.loadAllFired.delete(groupId);
|
|
1417
|
-
this.
|
|
1464
|
+
this.itemsByElement.set(element, item);
|
|
1418
1465
|
return item;
|
|
1419
1466
|
}
|
|
1420
1467
|
addSlideItem(slide) {
|
|
@@ -1426,15 +1473,73 @@
|
|
|
1426
1473
|
this.loadAllFired.delete(groupId);
|
|
1427
1474
|
return item;
|
|
1428
1475
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1476
|
+
// クリックされた要素(またはその祖先。<a><img></a> の img がクリックされる
|
|
1477
|
+
// ケースを含む)から、登録済み Item を持つ要素まで祖先チェーンを遡って探す
|
|
1478
|
+
findRegisteredAncestor(target) {
|
|
1479
|
+
let node = target;
|
|
1480
|
+
while (node) {
|
|
1481
|
+
if (this.itemsByElement.has(node)) {
|
|
1482
|
+
return node;
|
|
1483
|
+
}
|
|
1484
|
+
node = node.parentElement;
|
|
1485
|
+
}
|
|
1486
|
+
return null;
|
|
1487
|
+
}
|
|
1488
|
+
// rootSelector(文字列セレクタで構築した場合のみ設定される)を再スキャンし、
|
|
1489
|
+
// 指定グループを現在のDOM状態に合わせて丸ごと再構築する(追加・削除・並び順の
|
|
1490
|
+
// 変化を一度に反映)。既知要素は既存の Item オブジェクトをそのまま再利用する
|
|
1491
|
+
// ため loaded/width/height は保持され、DOM から消えた要素だけ itemsByElement
|
|
1492
|
+
// からも除去する。index/translateX は resetTranslate() で再計算する。
|
|
1493
|
+
// 呼び出し元(openPhoto)がこの結果を使い、変化があった場合のみ view を
|
|
1494
|
+
// 再同期する(§ダイアログを開く瞬間に整合を取る。開いている間の next()/prev()
|
|
1495
|
+
// では呼ばれないため、この間の追加/削除は次に開き直すまで反映されない)
|
|
1496
|
+
resyncGroupFromDom(groupId) {
|
|
1497
|
+
var _a;
|
|
1498
|
+
if (!this.rootSelector) {
|
|
1499
|
+
return false;
|
|
1500
|
+
}
|
|
1501
|
+
const domElements = Array.from(
|
|
1502
|
+
document.querySelectorAll(this.rootSelector)
|
|
1503
|
+
).filter((el) => groupIdFromElement(el) === groupId);
|
|
1504
|
+
const domElementSet = new Set(domElements);
|
|
1505
|
+
const previous = (_a = this.state.groups.get(groupId)) != null ? _a : [];
|
|
1506
|
+
const previousByElement = /* @__PURE__ */ new Map();
|
|
1507
|
+
previous.forEach((it) => {
|
|
1508
|
+
if (it.element) {
|
|
1509
|
+
previousByElement.set(it.element, it);
|
|
1510
|
+
}
|
|
1511
|
+
});
|
|
1512
|
+
let changed = domElements.length !== previous.length;
|
|
1513
|
+
const rebuilt = domElements.map((el, index) => {
|
|
1514
|
+
const existing = previousByElement.get(el);
|
|
1515
|
+
if (existing) {
|
|
1516
|
+
if (existing.index !== index) {
|
|
1517
|
+
changed = true;
|
|
1518
|
+
existing.index = index;
|
|
1519
|
+
}
|
|
1520
|
+
return existing;
|
|
1521
|
+
}
|
|
1522
|
+
changed = true;
|
|
1523
|
+
const item = itemFromElement(
|
|
1524
|
+
el,
|
|
1525
|
+
this.state.options,
|
|
1526
|
+
index,
|
|
1527
|
+
getWindowWidth()
|
|
1528
|
+
);
|
|
1529
|
+
this.itemsByElement.set(el, item);
|
|
1530
|
+
return item;
|
|
1531
|
+
});
|
|
1532
|
+
previous.forEach((it) => {
|
|
1533
|
+
if (it.element && !domElementSet.has(it.element)) {
|
|
1534
|
+
this.itemsByElement.delete(it.element);
|
|
1535
|
+
}
|
|
1536
|
+
});
|
|
1537
|
+
resetTranslate(rebuilt, getWindowWidth());
|
|
1538
|
+
this.state.groups.set(groupId, rebuilt);
|
|
1539
|
+
if (changed) {
|
|
1540
|
+
this.loadAllFired.delete(groupId);
|
|
1541
|
+
}
|
|
1542
|
+
return changed;
|
|
1438
1543
|
}
|
|
1439
1544
|
syncCurrentGroupView() {
|
|
1440
1545
|
const items = currentItems(this.state);
|
|
@@ -1503,10 +1608,12 @@
|
|
|
1503
1608
|
syncDialog() {
|
|
1504
1609
|
const { dialog, caption } = this.view.refs;
|
|
1505
1610
|
if (this.state.viewer.isOpen && !dialog.open) {
|
|
1611
|
+
dialog.style.removeProperty("display");
|
|
1506
1612
|
dialog.showModal();
|
|
1507
1613
|
caption.focus();
|
|
1508
1614
|
} else if (!this.state.viewer.isOpen && dialog.open) {
|
|
1509
1615
|
dialog.close();
|
|
1616
|
+
dialog.style.display = "none";
|
|
1510
1617
|
}
|
|
1511
1618
|
}
|
|
1512
1619
|
commit() {
|
|
@@ -1692,10 +1799,11 @@
|
|
|
1692
1799
|
});
|
|
1693
1800
|
}
|
|
1694
1801
|
openPhoto(item, trigger) {
|
|
1802
|
+
const groupChanged = this.rootSelector ? this.resyncGroupFromDom(item.groupId) : false;
|
|
1695
1803
|
this.lastTriggerElement = trigger;
|
|
1696
1804
|
this.state.viewer.currentGroup = item.groupId;
|
|
1697
1805
|
this.state.viewer.currentIndex = item.index;
|
|
1698
|
-
if (this.syncedGroupId !== item.groupId) {
|
|
1806
|
+
if (this.syncedGroupId !== item.groupId || groupChanged) {
|
|
1699
1807
|
this.syncCurrentGroupView();
|
|
1700
1808
|
}
|
|
1701
1809
|
this.setHashByCurrentIndex();
|
|
@@ -1787,6 +1895,7 @@
|
|
|
1787
1895
|
this.state.viewer.photoPosX = 0;
|
|
1788
1896
|
this.state.viewer.photoPosY = 0;
|
|
1789
1897
|
this.state.viewer.onMove = true;
|
|
1898
|
+
this.updateViewportHeight();
|
|
1790
1899
|
this.setPosByCurrentIndex();
|
|
1791
1900
|
this.setHashByCurrentIndex();
|
|
1792
1901
|
this.setSizeByScreen();
|