https://www.telia.no/static/js/mobile-safari-video-fix.js?h=0624200-448052dd3712e66f15ac1bb35c8db3a3
1// Mobile Safari Video Poster Fix - Sets poster attribute to video src value 2(function() { 3 'use strict'; 4 5 function isMobileSafari() { 6 const userAgent = navigator.userAgent; 7 const isIOS = /iPad|iPhone|iPod/.test(userAgent); 8 9 const isSafari = userAgent.includes('Safari') && !userAgent.includes('Chrome') && !userAgent.includes('CriOS') && !userAgent.includes('FxiOS'); 10 const isMobile = userAgent.includes('Mobile'); 11 12 const result = (isIOS && isSafari) || (isMobile && isSafari); 13 14 return result; 15 } 16 17 if (!isMobileSafari()) { 18 return; 19 } 20 21 function extractFirstFrame(video) { 22 return new Promise((resolve, reject) => { 23 const canvas = document.createElement('canvas'); 24 const context = canvas.getContext('2d'); 25 26 function captureFrame() { 27 try { 28 canvas.width = video.videoWidth || 640; 29 canvas.height = video.videoHeight || 360; 30 31 context.drawImage(video, 0, 0, canvas.width, canvas.height); 32 33 const dataURL = canvas.toDataURL('image/jpeg', 0.8); 34 resolve(dataURL); 35 } catch (error) { 36 console.error('Error extracting frame:', error); 37 reject(error); 38 } 39 } 40 41 function seekAndCapture() { 42 video.setAttribute('preload', 'metadata'); 43 video.currentTime = 0; 44 45 const onSeeked = () => { 46 video.removeEventListener('seeked', onSeeked); 47 setTimeout(captureFrame, 100); 48 }; 49 50 const onCanPlay = () => { 51 video.removeEventListener('canplay', onCanPlay); 52 video.addEventListener('seeked', onSeeked, { once: true }); 53 video.currentTime = 0; 54 }; 55 56 const onLoadedMetadata = () => { 57 video.removeEventListener('loadedmetadata', onLoadedMetadata); 58 59 if (video.readyState >= 1) { 60 onCanPlay(); 61 } else { 62 video.addEventListener('canplay', onCanPlay, { once: true }); 63 } 64 }; 65 66 if (video.readyState >= 1) { 67 onCanPlay(); 68 } else { 69 video.addEventListener('loadedmetadata', onLoadedMetadata, { once: true }); 70 video.load(); 71 } 72 73 setTimeout(() => { 74 video.removeEventListener('seeked', onSeeked); 75 video.removeEventListener('canplay', onCanPlay); 76 video.removeEventListener('loadedmetadata', onLoadedMetadata); 77 console.error('Timeout waiting for video to be ready for frame extraction'); 78 reject(new Error('Timeout waiting for video frame extraction')); 79 }, 8000); 80 } 81 82 if (video.readyState >= 2 && video.videoWidth > 0) { 83 captureFrame(); 84 } else { 85 seekAndCapture(); 86 } 87 }); 88 } 89 90 function fixVideoPosters() { 91 const videos = document.querySelectorAll('video[data-mobile-safari-video="true"]'); 92 93 videos.forEach(async (video) => { 94 const src = video.getAttribute('src') || video.currentSrc; 95 96 video.removeAttribute('autoplay'); 97 video.removeAttribute('muted'); 98 video.removeAttribute('playsinline'); 99 100 const posterValue = video.getAttribute('poster'); 101 const needsPoster = !posterValue || posterValue.trim() === ''; 102 103 if (needsPoster) { 104 try { 105 // Extract first frame as poster 106 const posterDataURL = await extractFirstFrame(video); 107 video.setAttribute('poster', posterDataURL); 108 } catch (error) { 109 console.warn('Failed to extract frame, fallback to src as poster:', error); 110 // Fallback to using video src as poster 111 if (src) { 112 video.setAttribute('poster', src); 113 } else { 114 // Check for source elements within the video 115 const sourceElement = video.querySelector('source'); 116 if (sourceElement) { 117 const sourceSrc = sourceElement.getAttribute('src'); 118 if (sourceSrc) { 119 video.setAttribute('poster', sourceSrc); 120 } 121 } 122 } 123 } 124 125 video.removeAttribute('data-mobile-safari-video'); 126 } 127 128 if (!video.paused) { 129 video.pause(); 130 } 131 }); 132 } 133 134 if (document.readyState === 'loading') { 135 document.addEventListener('DOMContentLoaded', fixVideoPosters); 136 } else { 137 fixVideoPosters(); 138 } 139})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.