mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	- Remove unused tailwind classes - Added comment about timeout jsdoc - Moved new CSS files to @import
		
			
				
	
	
		
			108 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { debounce_timeout } from './constants.js';
 | |
| 
 | |
| /**
 | |
|  * Drag and drop handler
 | |
|  *
 | |
|  * Can be used on any element, enabling drag&drop styling and callback on drop.
 | |
|  */
 | |
| export class DragAndDropHandler {
 | |
|     /** @private @type {JQuery.Selector} */ selector;
 | |
|     /** @private @type {(files: File[], event:JQuery.DropEvent<HTMLElement, undefined, any, any>) => void} */ onDropCallback;
 | |
|     /** @private @type {NodeJS.Timeout} Remark: Not actually NodeJS timeout, but it's close */ dragLeaveTimeout;
 | |
| 
 | |
|     /** @private @type {boolean} */ noAnimation;
 | |
| 
 | |
|     /**
 | |
|      * Create a DragAndDropHandler
 | |
|      * @param {JQuery.Selector} selector - The CSS selector for the elements to enable drag and drop
 | |
|      * @param {(files: File[], event:JQuery.DropEvent<HTMLElement, undefined, any, any>) => void} onDropCallback - The callback function to handle the drop event
 | |
|      */
 | |
|     constructor(selector, onDropCallback, { noAnimation = false } = {}) {
 | |
|         this.selector = selector;
 | |
|         this.onDropCallback = onDropCallback;
 | |
|         this.dragLeaveTimeout = null;
 | |
| 
 | |
|         this.noAnimation = noAnimation;
 | |
| 
 | |
|         this.init();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Destroy the drag and drop functionality
 | |
|      */
 | |
|     destroy() {
 | |
|         if (this.selector === 'body') {
 | |
|             $(document.body).off('dragover', this.handleDragOver.bind(this));
 | |
|             $(document.body).off('dragleave', this.handleDragLeave.bind(this));
 | |
|             $(document.body).off('drop', this.handleDrop.bind(this));
 | |
|         } else {
 | |
|             $(document.body).off('dragover', this.selector, this.handleDragOver.bind(this));
 | |
|             $(document.body).off('dragleave', this.selector, this.handleDragLeave.bind(this));
 | |
|             $(document.body).off('drop', this.selector, this.handleDrop.bind(this));
 | |
|         }
 | |
| 
 | |
|         $(this.selector).remove('drop_target no_animation');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Initialize the drag and drop functionality
 | |
|      * Automatically called on construction
 | |
|      * @private
 | |
|      */
 | |
|     init() {
 | |
|         if (this.selector === 'body') {
 | |
|             $(document.body).on('dragover', this.handleDragOver.bind(this));
 | |
|             $(document.body).on('dragleave', this.handleDragLeave.bind(this));
 | |
|             $(document.body).on('drop', this.handleDrop.bind(this));
 | |
|         } else {
 | |
|             $(document.body).on('dragover', this.selector, this.handleDragOver.bind(this));
 | |
|             $(document.body).on('dragleave', this.selector, this.handleDragLeave.bind(this));
 | |
|             $(document.body).on('drop', this.selector, this.handleDrop.bind(this));
 | |
|         }
 | |
| 
 | |
|         $(this.selector).addClass('drop_target');
 | |
|         if (this.noAnimation) $(this.selector).addClass('no_animation');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param {JQuery.DragOverEvent<HTMLElement, undefined, any, any>} event - The dragover event
 | |
|      * @private
 | |
|      */
 | |
|     handleDragOver(event) {
 | |
|         event.preventDefault();
 | |
|         event.stopPropagation();
 | |
|         clearTimeout(this.dragLeaveTimeout);
 | |
|         $(this.selector).addClass('drop_target dragover');
 | |
|         if (this.noAnimation) $(this.selector).addClass('no_animation');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param {JQuery.DragLeaveEvent<HTMLElement, undefined, any, any>} event - The dragleave event
 | |
|      * @private
 | |
|      */
 | |
|     handleDragLeave(event) {
 | |
|         event.preventDefault();
 | |
|         event.stopPropagation();
 | |
| 
 | |
|         // Debounce the removal of the class, so it doesn't "flicker" on dragging over
 | |
|         clearTimeout(this.dragLeaveTimeout);
 | |
|         this.dragLeaveTimeout = setTimeout(() => {
 | |
|             $(this.selector).removeClass('dragover');
 | |
|         }, debounce_timeout.quick);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param {JQuery.DropEvent<HTMLElement, undefined, any, any>} event - The drop event
 | |
|      * @private
 | |
|      */
 | |
|     handleDrop(event) {
 | |
|         event.preventDefault();
 | |
|         event.stopPropagation();
 | |
|         clearTimeout(this.dragLeaveTimeout);
 | |
|         $(this.selector).removeClass('dragover');
 | |
| 
 | |
|         const files = Array.from(event.originalEvent.dataTransfer.files);
 | |
|         this.onDropCallback(files, event);
 | |
|     }
 | |
| }
 |