description.js (3107B)
1 function toggleDescriptionEdit() { 2 const displayDiv = document.getElementById('description-display'); 3 const editDiv = document.getElementById('description-edit'); 4 5 displayDiv.style.display = 'none'; 6 editDiv.style.display = 'block'; 7 8 // Focus the textarea and update character count 9 const textarea = document.getElementById('description-textarea'); 10 textarea.focus(); 11 12 // Move cursor to end of text if there's existing content 13 if (textarea.value) { 14 textarea.setSelectionRange(textarea.value.length, textarea.value.length); 15 } 16 } 17 18 function cancelDescriptionEdit() { 19 const displayDiv = document.getElementById('description-display'); 20 const editDiv = document.getElementById('description-edit'); 21 const textarea = document.getElementById('description-textarea'); 22 23 // Reset textarea to original value 24 const original = displayDiv.dataset.originalDescription || ''; 25 textarea.value = original; 26 27 displayDiv.style.display = 'block'; 28 editDiv.style.display = 'none'; 29 30 // Re-run conversion so any [file/123] becomes clickable again 31 convertFileRefs(); 32 } 33 34 // Auto-resize textarea as content changes 35 document.addEventListener('DOMContentLoaded', function() { 36 const textarea = document.getElementById('description-textarea'); 37 if (textarea) { 38 textarea.addEventListener('input', function() { 39 // Reset height to auto to get the correct scrollHeight 40 this.style.height = 'auto'; 41 // Set the height to match the content, with a minimum of 6 rows 42 const minHeight = parseInt(getComputedStyle(this).lineHeight) * 6; 43 this.style.height = Math.max(minHeight, this.scrollHeight) + 'px'; 44 }); 45 } 46 }); 47 48 // Allow [file/123] and [/file/123] links to become clickable 49 function convertFileRefs() { 50 const el = document.getElementById("current-description"); 51 if (!el) return; 52 53 const pattern = /\[\/?file\/(\d+)\]/g; 54 55 // Walk through text nodes only, preserving existing HTML elements 56 function processTextNodes(node) { 57 if (node.nodeType === Node.TEXT_NODE) { 58 let text = node.textContent; 59 60 // Check if this text node contains file references 61 if (pattern.test(text)) { 62 // Reset regex lastIndex 63 pattern.lastIndex = 0; 64 65 // Replace file references 66 text = text.replace(pattern, (_, id) => { 67 return `<a href="/file/${id}" class="file-link">file/${id}</a>`; 68 }); 69 70 // Create a temporary container and replace the text node 71 const temp = document.createElement('span'); 72 temp.innerHTML = text; 73 const parent = node.parentNode; 74 while (temp.firstChild) { 75 parent.insertBefore(temp.firstChild, node); 76 } 77 parent.removeChild(node); 78 } 79 } else if (node.nodeType === Node.ELEMENT_NODE && node.tagName !== 'A') { 80 // Don't process inside existing anchor tags 81 Array.from(node.childNodes).forEach(processTextNodes); 82 } 83 } 84 85 processTextNodes(el); 86 } 87 88 document.addEventListener("DOMContentLoaded", function() { 89 convertFileRefs(); 90 });