[READ-ONLY] Mirror of https://github.com/probablykasper/thumbnail-grabber. Chrome extension for grabbing thumbnails/covers
browser-extension chrome chrome-extension chrome-extention extension
0

Configure Feed

Select the types of activity you want to include in your feed.

Add focus trap

Kasper (Oct 15, 2022, 4:21 AM +0200) 377452d4 aa5de826

+57 -6
+1
CHANGELOG.md
··· 2 2 3 3 ## Next 4 4 - Add dark mode 5 + - Add focus trap 5 6 - Improved responsiveness for small screens 6 7 - Slight redesign 7 8 - Fix context menu not showing on Spotify
+1
src/content-script.css
··· 120 120 box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); 121 121 display: block; 122 122 margin: auto; 123 + outline: none; 123 124 } 124 125 125 126 #thumbnail-grabber-buttons {
+55 -6
src/content-script.ts
··· 161 161 throw notify(`Error copying thumbnail: ${error}`); 162 162 } 163 163 } 164 + 165 + let lastActiveElement: Element | null = null; 166 + const focusTrapInstance = focusTrap(thumbnailGrabber); 167 + 164 168 async function open() { 165 169 document.addEventListener('keydown', keydownEventListener); 166 170 document.addEventListener('copy', copyEventListener); 167 171 thumbnailGrabber.style.display = ''; 168 172 document.body.classList.add('thumbnail-grabber-prevent-scroll'); 173 + focusTrapInstance.open(img || thumbnailGrabber); 169 174 } 170 175 171 176 function close() { ··· 173 178 document.removeEventListener('copy', copyEventListener); 174 179 thumbnailGrabber.style.display = 'none'; 175 180 document.body.classList.remove('thumbnail-grabber-prevent-scroll'); 181 + focusTrapInstance.close(); 176 182 } 177 183 close(); 184 + 185 + function focusTrap(el: HTMLElement) { 186 + function getFocusElements() { 187 + return el.querySelectorAll( 188 + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])', 189 + ); 190 + } 191 + 192 + function handleKeydown(e: KeyboardEvent) { 193 + if (e.key === 'Tab' && e.shiftKey && !e.ctrlKey && !e.metaKey) { 194 + const focusElements = getFocusElements(); 195 + const lastFocusElement = focusElements[focusElements.length - 1]; 196 + if ( 197 + focusElements[0] && 198 + document.activeElement?.isSameNode(focusElements[0]) && 199 + lastFocusElement instanceof HTMLElement 200 + ) { 201 + lastFocusElement.focus(); 202 + e.preventDefault(); 203 + } 204 + } else if (e.key === 'Tab' && !e.shiftKey && !e.ctrlKey && !e.metaKey) { 205 + const focusElements = getFocusElements(); 206 + const lastFocusElement = focusElements[focusElements.length - 1]; 207 + if ( 208 + document.activeElement?.isSameNode(lastFocusElement) && 209 + focusElements[0] instanceof HTMLElement 210 + ) { 211 + focusElements[0].focus(); 212 + e.preventDefault(); 213 + } 214 + } 215 + } 216 + el.addEventListener('keydown', handleKeydown); 217 + return { 218 + open(focusElement: HTMLElement) { 219 + lastActiveElement = document.activeElement; 220 + focusElement.focus(); 221 + }, 222 + close() { 223 + if (lastActiveElement instanceof HTMLElement) { 224 + lastActiveElement.focus(); 225 + } 226 + lastActiveElement = null; 227 + }, 228 + }; 229 + } 178 230 179 231 let lastFilename: string; 180 232 async function setup(url: string) { ··· 273 325 document.body.removeChild(a); 274 326 } 275 327 276 - function createImage(options) { 277 - options = options || {}; 328 + function createImage(src: string) { 278 329 const img = Image ? new Image() : document.createElement('img'); 279 - if (options.src) { 280 - img.src = options.src; 281 - } 330 + img.src = src; 282 331 return img; 283 332 } 284 333 ··· 290 339 if (!ctx) { 291 340 throw alert('No 2d canvas ctx'); 292 341 } 293 - const imageEl = createImage({ src: imageUrl }); 342 + const imageEl = createImage(imageUrl); 294 343 imageEl.onload = (e) => { 295 344 if (!(e.target instanceof HTMLImageElement)) { 296 345 throw alert('No imageEl target');