forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtoggle-images.ts
More file actions
115 lines (96 loc) · 4.15 KB
/
toggle-images.ts
File metadata and controls
115 lines (96 loc) · 4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// import { sendEvent } from './events'
import Cookies from 'js-cookie'
// Determines whether images are hidden or displayed on first visit.
const hideImagesByDefault = false
// Set the image placeholder icon here.
const placeholderImagePath = '/assets/images/octicons/image.svg'
/*
* This module adds a new icon button in the margin to toggle all images on the page.
* It uses cookies to keep track of a user's selected image preference.
*/
export default function () {
const toggleImagesBtn = document.getElementById('js-toggle-images')
if (!toggleImagesBtn) return
// If there are no images on the page, return!
// Don't include images in tables, which are already small and shouldn't be hidden.
const images = Array.from(document.querySelectorAll('img')).filter((img) => !img.closest('table'))
if (!images.length) return
// The button is hidden by default so it doesn't appear on browsers with JS disabled.
// If there are images on a docs page and JS is enabled, display the toggle button.
toggleImagesBtn.removeAttribute('hidden')
// Look for a cookie with image visibility preference; otherwise, use the default.
const hideImagesPreferred = Cookies.get('hideImagesPreferred') === 'true' || hideImagesByDefault
// Hide the images if that is the preference.
if (hideImagesPreferred) {
toggleImages(images, 'hide')
}
// Get the span elements containing the off and on icons.
const offIcon = document.getElementById('js-off-icon')
const onIcon = document.getElementById('js-on-icon')
// Get the aria-labels from the span elements for the tooltips.
const tooltipImagesOff = offIcon?.getAttribute('aria-label') || ''
const tooltipImagesOn = onIcon?.getAttribute('aria-label') || ''
// Set the starting state depending on user preferences.
if (hideImagesPreferred) {
offIcon?.removeAttribute('hidden')
toggleImagesBtn.setAttribute('aria-label', tooltipImagesOff)
} else {
onIcon?.removeAttribute('hidden')
toggleImagesBtn.setAttribute('aria-label', tooltipImagesOn)
}
// If images are hidden by default, showOnNextClick should be false.
// If images are not hidden by default, showOnNextClick should be true.
let showOnNextClick = !hideImagesPreferred
toggleImagesBtn.addEventListener('click', () => {
if (showOnNextClick) {
// Button should say "Images are off" on first click (depending on prefs)
offIcon?.removeAttribute('hidden')
onIcon?.setAttribute('hidden', 'hidden')
toggleImagesBtn.setAttribute('aria-label', tooltipImagesOff)
toggleImages(images, 'hide')
} else {
// Button should say "Images are on" on another click
offIcon?.setAttribute('hidden', 'hidden')
onIcon?.removeAttribute('hidden')
toggleImagesBtn.setAttribute('aria-label', tooltipImagesOn)
toggleImages(images, 'show')
}
// Remove focus from the button after click so the tooltip does not stay displayed.
// Use settimeout to work around Firefox-specific issue.
setTimeout(() => {
toggleImagesBtn.blur()
}, 100)
// Save this preference as a cookie.
Cookies.set('hideImagesPreferred', showOnNextClick.toString(), {
sameSite: 'strict',
secure: true,
})
// Toggle the action on every click.
showOnNextClick = !showOnNextClick
// TODO Track image toggle events
// sendEvent({ type: 'imageToggle' })
})
}
function toggleImages(images: Array<HTMLImageElement>, action: string) {
for (const img of images) {
toggleImage(img, action)
}
}
function toggleImage(img: HTMLImageElement, action: string) {
const parentEl = img.parentNode as HTMLElement
// Style the parent element and image depending on the state.
if (action === 'show') {
img.src = img.getAttribute('originalSrc') || ''
img.style.border = '2px solid var(--color-auto-gray-2)'
parentEl.style.display = 'block'
parentEl.style.marginTop = '20px'
parentEl.style.padding = '10px 0'
} else {
if (!img.getAttribute('originalSrc')) img.setAttribute('originalSrc', img.src)
img.src = placeholderImagePath
img.style.border = 'none'
parentEl.style.display = 'inline'
parentEl.style.marginTop = '0'
parentEl.style.padding = '1px 6px'
}
}