/** * Fetch and display preview images for various image upload forms. */ import { fetchJson, handleError } from './utils/requests'; import { $, $$, hideEl, showEl, makeEl, clearEl } from './utils/dom'; import { addTag } from './tagsinput'; function scrapeUrl(url) { return fetchJson('POST', '/posts/scrape_url', { url }) .then(handleError) .then(response => response.json()); } function setupImageUpload() { const imgPreviews = $('#js-image-upload-previews'); if (!imgPreviews) return; const form = imgPreviews.closest('form'); const [ fileField, remoteUrl, scraperError ] = $$('.js-scraper', form); const [ sourceEl, tagsEl, descrEl ] = $$('.js-image-input', form); const fetchButton = $('#js-scraper-preview'); function showImages(images) { clearEl(imgPreviews); images.forEach((image, index) => { const imgWrap = makeEl('span', { className: 'scraper-preview--image-wrapper' }); if (image.type === 'image') { const img = makeEl('img', { className: 'scraper-preview--image' }); img.src = image.camo_url; imgWrap.appendChild(img); } else if (image.type === 'paste') { const paste = makeEl('pre', { className: 'scraper-preview--paste' }); const disclaimer = makeEl('p'); paste.innerText = image.preview; disclaimer.innerText = 'Preview is only the first 250 characters - it will all be there in the real post.' imgWrap.appendChild(paste); imgWrap.appendChild(disclaimer); } const label = makeEl('label', { className: 'scraper-preview--label' }); const radio = makeEl('input', { type: 'radio', className: 'scraper-preview--input', name: 'scraper_cache[url]' }); const otherRadio = makeEl('input', { type: 'radio', className: 'scraper-preview--input', name: 'scraper_cache[type]' }); if (image.url) { radio.value = image.url; otherRadio.value = image.type; } if (index === 0) { radio.checked = true; otherRadio.checked = true; } label.appendChild(radio); label.appendChild(otherRadio); label.appendChild(imgWrap); imgPreviews.appendChild(label); }); } function showError(err) { console.error(err); clearEl(imgPreviews); showEl(scraperError); enableFetch(); } function hideError() { hideEl(scraperError); } function disableFetch() { fetchButton.setAttribute('disabled', ''); } function enableFetch() { fetchButton.removeAttribute('disabled'); } const reader = new FileReader(); reader.addEventListener('load', event => { const fileReader = event.target; // I hate this. const isPaste = !fileReader.result.startsWith('data:image/') && !fileReader.result.startsWith('data:video/'); const data = isPaste ? { type: 'paste', preview: fileReader.result.substring(0, 250) } : { type: 'image', camo_url: fileReader.result }; showImages([data]); // Clear any currently cached data, because the file field // has higher priority than the scraper: remoteUrl.value = ''; hideError(); }); // Watch for files added to the form fileField.addEventListener('change', () => { if (fileField.files.length !== 1) return; const file = fileField.files[0]; if (file.type.startsWith('text/')) { reader.readAsText(file); } else { reader.readAsDataURL(file); } }); // Watch for [Fetch] clicks fetchButton.addEventListener('click', () => { if (!remoteUrl.value) return; disableFetch(); scrapeUrl(remoteUrl.value).then(data => { if (data.errors && data.errors.length > 0) { scraperError.innerText = data.errors.join(' '); showError(); return; } hideError(); // Set source if (sourceEl) sourceEl.value = sourceEl.value || data.source_url || ''; // Set description if (descrEl) descrEl.value = descrEl.value || data.description || ''; // Add author if (tagsEl && data.author_name) addTag(tagsEl, `artist:${data.author_name.toLowerCase()}`); // Add scraped tags if (tagsEl && data.tags) { for (let tag of data.tags) { addTag(tagsEl, tag); } } // Clear selected file, if any fileField.value = ''; showImages(data.images); enableFetch(); }).catch(showError); }); } export { setupImageUpload };