// Media picker modal — insert image references into Markdown textareas. // Usage: mediaPickerOpen(textareaId) opens the picker, inserts at cursor on selection. (function() { 'use strict'; var modal = null; var targetTextareaId = null; function createModal() { if (modal) return modal; modal = document.createElement('div'); modal.id = 'media-picker-modal'; modal.style.cssText = 'display:none; position:fixed; inset:0; z-index:1000; background:rgba(0,0,0,0.5); align-items:center; justify-content:center;'; modal.innerHTML = '
' + '
' + '

Insert from Media Library

' + '' + '
' + '
' + '' + '' + '
' + '
' + '

Loading...

' + '
' + '
Click an image to insert its Markdown reference at the cursor.
' + '
'; document.body.appendChild(modal); document.getElementById('media-picker-close').addEventListener('click', mediaPickerClose); modal.addEventListener('click', function(e) { if (e.target === modal) mediaPickerClose(); }); document.getElementById('media-picker-search').addEventListener('input', filterPickerGrid); document.getElementById('media-picker-folder').addEventListener('change', filterPickerGrid); return modal; } function mediaPickerClose() { if (modal) modal.style.display = 'none'; } function filterPickerGrid() { var query = (document.getElementById('media-picker-search').value || '').toLowerCase(); var folder = document.getElementById('media-picker-folder').value; var cards = document.querySelectorAll('#media-picker-grid .mp-card'); for (var i = 0; i < cards.length; i++) { var name = cards[i].dataset.name || ''; var f = cards[i].dataset.folder || ''; var show = (!query || name.toLowerCase().indexOf(query) !== -1) && (!folder || f === folder); cards[i].style.display = show ? '' : 'none'; } } function insertAtCursor(textareaId, text) { var ta = document.getElementById(textareaId); if (!ta) return; ta.focus(); var start = ta.selectionStart; var end = ta.selectionEnd; ta.value = ta.value.substring(0, start) + text + ta.value.substring(end); ta.selectionStart = ta.selectionEnd = start + text.length; // Trigger input event for auto-save / word count ta.dispatchEvent(new Event('input', { bubbles: true })); } function renderGrid(files) { var grid = document.getElementById('media-picker-grid'); if (!files || files.length === 0) { grid.innerHTML = '

No media files yet. Upload images in your Media Library tab first.

'; return; } var html = ''; for (var i = 0; i < files.length; i++) { var f = files[i]; var ref = f.markdown_ref || f.file_name; var isImage = (f.content_type || '').indexOf('image') === 0; html += '
'; if (isImage) { html += '
' + '' + (f.file_name || '') + '
'; } else { html += '
📄
'; } html += '
' + (f.file_name || '') + '
'; html += '
'; } grid.innerHTML = html; } window._mediaPickerSelect = function(ref) { if (targetTextareaId) { insertAtCursor(targetTextareaId, '![](' + ref + ')'); } mediaPickerClose(); }; window.mediaPickerOpen = function(textareaId) { targetTextareaId = textareaId; createModal(); modal.style.display = 'flex'; document.getElementById('media-picker-search').value = ''; document.getElementById('media-picker-grid').innerHTML = '

Loading...

'; fetch('/api/media', { credentials: 'same-origin', headers: csrfHeaders() }) .then(function(res) { return res.json(); }) .then(function(data) { // Populate folder dropdown var sel = document.getElementById('media-picker-folder'); sel.innerHTML = ''; (data.folders || []).forEach(function(f) { var opt = document.createElement('option'); opt.value = f; opt.textContent = f || '(root)'; sel.appendChild(opt); }); renderGrid(data.files || []); }) .catch(function() { document.getElementById('media-picker-grid').innerHTML = '

Failed to load media library.

'; }); }; })();