1// Copyright (c) 2021-2025 GrayBits LLC 2 3import axios from 'axios' 4let autoplay_ids = {}; 5 6export function init(){ 7 initalTextareaAutoexpand(); 8 setupAxios(); 9} 10 11export function turboAutoPlayCachingFix(){ 12 document.addEventListener('turbo:before-cache', stopCachedAutoplay); 13 document.addEventListener('turbo:before-render', restoreAutoplay); 14} 15 16function stopCachedAutoplay(){ 17 let videos = document.querySelectorAll('video'); 18 if (videos.length == 0) return; 19 20 autoplay_ids[window.location.href] = []; 21 videos.forEach((element) => { 22 element.pause(); 23 if (element.getAttribute('autoplay') && element.id){ 24 autoplay_ids[window.location.href].push(element.id); 25 element.removeAttribute('autoplay'); 26 } 27 }); 28} 29 30function restoreAutoplay(event){ 31 if (event.target.hasAttribute('data-turbo-preview') === true) return; 32 if (!autoplay_ids[window.location.href]) return; 33 34 autoplay_ids[window.location.href].forEach((id) => { 35 const autoplay = event.detail.newBody.querySelector(`#${id}`); 36 if (autoplay){ 37 autoplay.setAttribute('autoplay', true); 38 } 39 }); 40 autoplay_ids[window.location.href] = []; 41} 42 43export function initalTextareaAutoexpand(parent){ 44 (parent || document).querySelectorAll('.text_area_grow > textarea').forEach((e) => { 45 e.dispatchEvent(new Event('input')); 46 }); 47} 48 49function autoexpandTextarea(textarea, precalculated_height){ 50 textarea.style.height = 'inherit'; 51 if (!precalculated_height){ 52 precalculated_height = textarea.scrollHeight; 53 } 54 let computed = window.getComputedStyle(textarea); 55 let height = precalculated_height + 56 parseInt(computed.getPropertyValue('border-top-width')) + 57 parseInt(computed.getPropertyValue('padding-top')) + 58 parseInt(computed.getPropertyValue('padding-bottom')) + 59 parseInt(computed.getPropertyValue('border-bottom-width')); 60 textarea.style.height = height + 'px'; 61} 62 63export function setupAxios(){ 64 axios.defaults.headers.common['X-CSRF-Token'] = document.head.querySelector("[name='csrf-token']").content; 65 axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 66 axios.defaults.headers.common['Accept'] = 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript'; 67 axios.interceptors.request.use(config => { 68 config.paramsSerializer = params => { return stringify(params); }; 69 return config; 70 }); 71} 72 73export function stringify(params, parent = '') { 74 const stringified = Object.keys(params).map((key) => { 75 let value = params[key]; 76 if (Array.isArray(value)) { 77 return value.map(array_value => `${parent}${key}[]=${encodeURIComponent(array_value)}`).join("&"); 78 } else if (typeof value === "object") { 79 if (parent == ''){ 80 return stringify(value, key); 81 } else { 82 return stringify(value, `${parent}[${key}]`); 83 } 84 } else { 85 if (parent == ''){ 86 return `${key}=${encodeURIComponent(value)}`; 87 } else { 88 return `${parent}[${key}]=${encodeURIComponent(value)}`; 89 } 90 } 91 }); 92 93 return stringified.filter((s) => { return s.trim().length > 0; } ).join("&"); 94};
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.