Skip to content
This repository was archived by the owner on Sep 22, 2022. It is now read-only.

Commit b8b0b55

Browse files
authored
Merge pull request #31 from github/src
<details-dialog src=""> + <include-fragment>
2 parents 9da29cd + ee3d324 commit b8b0b55

File tree

4 files changed

+85
-3
lines changed

4 files changed

+85
-3
lines changed

README.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@ import 'details-dialog-element'
2424
</details>
2525
```
2626

27+
## Deferred loading
28+
29+
Dialog content can be loaded from a server by embedding an [`<include-fragment>`][fragment] element.
30+
31+
```html
32+
<details>
33+
<summary>Robots</summary>
34+
<details-dialog src="/robots" preload>
35+
<include-fragment>Loading…</include-fragment>
36+
</details-dialog>
37+
</details>
38+
```
39+
40+
The `src` attribute value is copied to the `<include-fragment>` the first time the `<details>` button is toggled open, which starts the server fetch.
41+
42+
If the `preload` attribute is present, hovering over the `<details>` element will trigger the server fetch.
43+
2744
## Events
2845

2946
### `details-dialog:will-close`
@@ -52,9 +69,6 @@ Browsers without native [custom element support][support] require a [polyfill][]
5269
- Safari
5370
- Microsoft Edge
5471

55-
[support]: https://caniuse.com/#feat=custom-elementsv1
56-
[polyfill]: https://github.com/webcomponents/custom-elements
57-
5872
## Development
5973

6074
```
@@ -65,3 +79,7 @@ npm test
6579
## License
6680

6781
Distributed under the MIT license. See LICENSE for details.
82+
83+
[fragment]: https://github.com/github/include-fragment-element/
84+
[support]: https://caniuse.com/#feat=custom-elementsv1
85+
[polyfill]: https://github.com/webcomponents/custom-elements

content.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<a href="./content.html">content.html</a>

index.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<meta charset="utf-8">
55
<!-- <script type="text/javascript" src="dist/index.umd.js"></script> -->
66
<script type="text/javascript" src="https://unpkg.com/details-dialog-element@latest"></script>
7+
<script type="text/javascript" src="https://unpkg.com/include-fragment-element@latest"></script>
78
<title>details-dialog-element demo</title>
89
<link href="./index.css" rel="stylesheet">
910
<link href="https://unpkg.com/primer@latest/build/build.css" rel="stylesheet">
@@ -63,6 +64,13 @@
6364
</details-dialog>
6465
</details>
6566

67+
<details class="details-reset details-with-dialog mt-4">
68+
<summary class="btn">Dialog with &lt;include-fragment&gt;</summary>
69+
<details-dialog class="Box details-dialog anim-fade-in fast narrow" src="./content.html">
70+
<div class="Box-body"><include-fragment>loading</include-fragment></div>
71+
</details-dialog>
72+
</details>
73+
6674
<details class="details-reset details-with-dialog mt-4">
6775
<summary class="btn">Dialog with autofocus</summary>
6876
<details-dialog class="details-dialog anim-fade-in fast narrow">

index.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,23 @@ function toggleDetails(details: Element, open: boolean) {
127127
}
128128
}
129129

130+
function loadIncludeFragment(event: Event) {
131+
const details = event.currentTarget
132+
if (!(details instanceof Element)) return
133+
const dialog = details.querySelector('details-dialog')
134+
if (!(dialog instanceof DetailsDialogElement)) return
135+
const loader = dialog.querySelector('include-fragment:not([src])')
136+
if (!loader) return
137+
138+
const src = dialog.src
139+
if (src === null) return
140+
141+
loader.addEventListener('loadend', () => {
142+
autofocus(dialog)
143+
})
144+
loader.setAttribute('src', src)
145+
}
146+
130147
type State = {|
131148
details: ?Element,
132149
activeElement: ?Element
@@ -157,6 +174,22 @@ class DetailsDialogElement extends HTMLElement {
157174
})
158175
}
159176

177+
get src(): ?string {
178+
return this.getAttribute('src')
179+
}
180+
181+
set src(value: string) {
182+
this.setAttribute('src', value)
183+
}
184+
185+
get preload(): boolean {
186+
return this.hasAttribute('preload')
187+
}
188+
189+
set preload(value: boolean) {
190+
value ? this.setAttribute('preload', '') : this.removeAttribute('preload')
191+
}
192+
160193
connectedCallback() {
161194
this.setAttribute('role', 'dialog')
162195
const state = initialized.get(this)
@@ -194,6 +227,28 @@ class DetailsDialogElement extends HTMLElement {
194227
if (!details) return
195228
toggleDetails(details, open)
196229
}
230+
231+
static get observedAttributes() {
232+
return ['src', 'preload']
233+
}
234+
235+
attributeChangedCallback() {
236+
const details = this.parentElement
237+
if (!details) return
238+
const state = initialized.get(this)
239+
if (!state) return
240+
241+
if (this.src) {
242+
details.addEventListener('toggle', loadIncludeFragment, {once: true})
243+
244+
if (this.preload) {
245+
details.addEventListener('mouseover', loadIncludeFragment, {once: true})
246+
}
247+
} else {
248+
details.removeEventListener('toggle', loadIncludeFragment)
249+
details.removeEventListener('mouseover', loadIncludeFragment)
250+
}
251+
}
197252
}
198253

199254
export default DetailsDialogElement

0 commit comments

Comments
 (0)