the browser-facing portion of osu!
at master 1.8 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 2// See the LICENCE file in the repository root for full licence text. 3 4import { route } from 'laroute'; 5import { debounce } from 'lodash'; 6import { fail } from 'utils/fail'; 7import { htmlElementOrNull } from 'utils/html'; 8 9export default class BbcodeAutoPreview { 10 private readonly debouncedLoadPreview; 11 private readonly xhr = new Map<HTMLElement, JQuery.jqXHR<string>>(); 12 13 constructor() { 14 this.debouncedLoadPreview = debounce(this.loadPreview, 500); 15 document.addEventListener('input', this.onInput); 16 } 17 18 private readonly loadPreview = (target: HTMLTextAreaElement) => { 19 const form = target.closest('form') ?? fail('form element is missing'); 20 const body = target.value; 21 const preview = htmlElementOrNull(form.querySelector('.js-post-preview--preview')); 22 const previewBox = form.querySelector('.js-post-preview--box'); 23 24 if (preview == null) { 25 return; 26 } 27 28 this.xhr.get(preview)?.abort(); 29 30 if (body === '') { 31 preview.dataset.raw = ''; 32 preview.innerHTML = ''; 33 previewBox?.classList.add('hidden'); 34 return; 35 } 36 37 if (preview.dataset.raw === body) { 38 previewBox?.classList.remove('hidden'); 39 return; 40 } 41 42 const xhr = $.post(route('bbcode-preview'), { text: body }) as JQuery.jqXHR<string>; 43 xhr.done((data) => { 44 preview.dataset.raw = body; 45 preview.innerHTML = data; 46 previewBox?.classList.remove('hidden'); 47 }).always(() => { 48 this.xhr.delete(preview); 49 }); 50 }; 51 52 private readonly onInput = (e: InputEvent) => { 53 const target = htmlElementOrNull(e.target)?.closest('.js-post-preview--auto'); 54 55 if (target instanceof HTMLTextAreaElement) { 56 this.debouncedLoadPreview(target); 57 } 58 }; 59}