import type { IJodit } from 'jodit/types'; import type { ImageSelectorCallbacks } from 'jodit/modules/widget'; import type { MediaItem } from './MediaItem'; import type { IGif } from '@giphy/js-types'; // import type { IGif } from '@giphy/js-types'; // import type { Basic } from 'unsplash-js/dist/methods/photos/types'; // Variable Section type MediaDataUpdateType = 'replace' | 'append'; // Main Section export class MediaList { editor: IJodit; callbacks: ImageSelectorCallbacks; element: HTMLElement; searchWord: string = ''; page: number = 0; perPage: number = 30; hasNext: boolean = true; mediaDataUpdateType: MediaDataUpdateType; items: MediaItem[] = []; close: () => void; moreLoading: boolean = true; constructor( editor: IJodit, callbacks: ImageSelectorCallbacks, searchWord: string, close: () => void ) { this.editor = editor; this.callbacks = callbacks; this.searchWord = searchWord; this.mediaDataUpdateType = 'replace'; this.close = close; this.element = editor.c.fromHTML('
'); this.load(); } // load -> fetchData -> create MediaItems -> generate HTML Element async load(): Promise { const data = await this.fetchData(); if (data?.length || this.mediaDataUpdateType === 'append') { this.generateContent(this.createMediaItems(data)); } else { this.generateEmpty(); } } // 신규 검색 search(searchWord: string): void { this.mediaDataUpdateType = 'replace'; this.searchWord = searchWord; this.load(); } // 데이터 로드 async fetchData(): Promise { throw Error('Need implementation'); return []; } // new MediaItem 리스트 생성 createMediaItems(data: IGif[] | any): MediaItem[] { throw Error('Need implementation'); return []; } generateContent(mediaItems: MediaItem[]): void { // empty element 제거 this.element.querySelector('.jodit-media-empty')?.remove(); // 리스트 element const contentElm = this.element.querySelector('.jodit-media-list'); // 없으면 만들기 if (!contentElm) { this.element.appendChild( this.editor.c.fromHTML( `
` ) ); this.generateContent(mediaItems); return; } (contentElm as HTMLElement).style.paddingBottom = '24px'; // 스크롤 더보기 기능 contentElm.addEventListener('scroll', () => { if ( contentElm.scrollTop > contentElm.scrollHeight - 2 * contentElm.clientHeight && // 스크롤이 특정 위치에 왔는지 !this.moreLoading && // 로딩중인지 this.hasNext // 다음 페이지가 있는지 ) { this.moreLoading = true; this.load(); } }); if (this.mediaDataUpdateType === 'replace') { contentElm.replaceChildren(...mediaItems.map(item => item.element)); this.items = mediaItems; this.mediaDataUpdateType = 'append'; } else { contentElm.append(...mediaItems.map(item => item.element)); this.items = [...this.items, ...mediaItems]; } this.moreLoading = false; } generateEmpty(): void { const hello = this.editor.i18n( 'No results found with', this.searchWord ); this.element.replaceChildren( ...[ this.editor.c.fromHTML( '
' + hello + '
' ) ] ); return; } }