UNPKG

@eclipse-scout/core

Version:
278 lines (244 loc) 9.25 kB
/* * Copyright (c) 2010, 2023 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ import {arrays, DragAndDropHandler, scout, Widget} from '../index'; export enum DropType { NONE = 0, FILE_TRANSFER = 1 } export const dragAndDrop = { DEFAULT_DROP_MAXIMUM_SIZE: 50 * 1024 * 1024, // 50 MiB /** * Mapping function from scout drag types to browser drag types. * * @param scoutTypesArray array of DropType */ scoutTypeToDragTypeMapping(scoutTypesArray: DropType | DropType[]): Array<string> { scoutTypesArray = arrays.ensure(scoutTypesArray); let ret = []; if (scoutTypesArray.indexOf(DropType.FILE_TRANSFER) >= 0) { ret.push('Files'); } return ret; }, /** * Check if specific scout type is supported by dataTransfer, if event is not handled by this field (desktop might handle it) * * @param event including event.originalEvent.dataTransfer * @param fieldAllowedTypes allowed types on field (integer, bitwise comparison used) * @param scoutTypeArray e.g. FILE_TRANSFER */ verifyDataTransferTypesScoutTypes(event: JQuery.DragEventBase, scoutTypeArray: DropType | DropType[], fieldAllowedTypes: number) { scoutTypeArray = arrays.ensure(scoutTypeArray); let dragTypeArray = []; // check if any scout type is allowed for field allowed types (or no field allowed types defined) if (fieldAllowedTypes !== undefined) { scoutTypeArray.forEach(scoutType => { if ((fieldAllowedTypes & scoutType) === scoutType) { // NOSONAR arrays.pushAll(dragTypeArray, dragAndDrop.scoutTypeToDragTypeMapping(scoutTypeArray)); } }); } else { dragTypeArray = dragAndDrop.scoutTypeToDragTypeMapping(scoutTypeArray); } if (Array.isArray(dragTypeArray) && dragTypeArray.length > 0) { dragAndDrop.verifyDataTransferTypes(event, dragTypeArray); } }, /** * Check if specific type is supported by dataTransfer, if event is not handled by this field (upstream field might handle it, at the latest desktop) * * @param dataTransfer dataTransfer object (not dataTransfer.types) * @param needleArray e.g. 'Files' */ verifyDataTransferTypes(event: JQuery.DragEventBase, needleArray: string | string[]): boolean { let dataTransfer = event.originalEvent.dataTransfer; if (dragAndDrop.dataTransferTypesContains(dataTransfer, needleArray)) { event.stopPropagation(); event.preventDefault(); return true; } return false; }, /** * dataTransfer.types might be an array (Chrome, IE) or a DOMStringList. * * Unfortunately there is no intersecting contains method for both types. * * @param dataTransfer dataTransfer object (not dataTransfer.types) * @param scoutTypesArray e.g. FILE_TRANSFER */ dataTransferTypesContainsScoutTypes(dataTransfer: DataTransfer, scoutTypesArray: DropType | DropType[]): boolean { scoutTypesArray = arrays.ensure(scoutTypesArray); let dragTypesArray = dragAndDrop.scoutTypeToDragTypeMapping(scoutTypesArray); return dragAndDrop.dataTransferTypesContains(dataTransfer, dragTypesArray); }, /** * dataTransfer.types might be an array (Chrome, IE) or a DOMStringList. * * Unfortunately there is no intersecting contains method for both types. * * @param dataTransfer dataTransfer object (not dataTransfer.types) * @param needleArray e.g. 'Files' */ dataTransferTypesContains(dataTransfer: DataTransfer, needleArray: string | string[]): boolean { needleArray = arrays.ensure(needleArray); if (dataTransfer && dataTransfer.types) { if (Array.isArray(dataTransfer.types) && arrays.containsAny(dataTransfer.types, needleArray)) { // Array: indexOf function return true; } if (dataTransfer.types['contains']) { // DOMStringList: contains function return needleArray.some(element => { return dataTransfer.types['contains'](element); }); } } return false; }, handler(options: DragAndDropOptions): DragAndDropHandler { if (!options || !options.target) { return null; } return scout.create(DragAndDropHandler, options); }, /** * installs or uninstalls a {@link DragAndDropHandler} on the target. */ installOrUninstallDragAndDropHandler(options: DragAndDropOptions) { if (!options.target) { return; } options = $.extend({}, dragAndDrop._createDragAndDropHandlerOptions(options.target), options); if (options.doInstall()) { dragAndDrop._installDragAndDropHandler(options); } else { dragAndDrop.uninstallDragAndDropHandler(options.target); } }, /** @internal */ _installDragAndDropHandler(options: DragAndDropOptions) { if (options.target.dragAndDropHandler) { return; } options.target.dragAndDropHandler = dragAndDrop.handler(options); if (!options.target.dragAndDropHandler) { return; } let $container = options.container(); if (!$container) { return; } options.target.dragAndDropHandler.install($container, options.selector); }, /** @internal */ _createDragAndDropHandlerOptions(target: DragAndDropTarget): DragAndDropOptions { return { target: target, supportedScoutTypes: DropType.FILE_TRANSFER, validateFiles: (files, defaultValidator) => defaultValidator(files), // eslint-disable-next-line @typescript-eslint/no-empty-function onDrop: event => { }, dropType: () => DropType.FILE_TRANSFER, dropMaximumSize: () => target.dropMaximumSize, doInstall: () => target.enabledComputed, container: () => target.$container, // eslint-disable-next-line @typescript-eslint/no-empty-function additionalDropProperties: event => { } }; }, /** * uninstalls a {@link DragAndDropHandler} from the target. If no handler is installed, this function does nothing. */ uninstallDragAndDropHandler(target: DragAndDropTarget) { if (!target || !target.dragAndDropHandler) { return; } target.dragAndDropHandler.uninstall(); target.dragAndDropHandler = null; } }; export type DragAndDropTarget = Widget & { /** * default drop maximum size used in {@link DragAndDropOptions.dropMaximumSize}. If the target object contains a different field or function to retrieve this value override the supplier. */ dropMaximumSize?: number; /** * default install/uninstall criteria used in {@link DragAndDropOptions.doInstall}. If the target object contains a different field or function to retrieve this value override the supplier. */ enabledComputed?: boolean; /** * default container used in {@link DragAndDropOptions.container}. If the target object contains a different field or function to retrieve this value override the supplier. */ $container?: JQuery; /** * installed drag & drop handler. Will be managed through {@link DragAndDropHandler} */ dragAndDropHandler: DragAndDropHandler; }; export interface DropValidationErrorMessage { title: string; message: string; } export interface FileDropEvent { originalEvent: JQuery.DropEvent; files: File[]; } export interface DragAndDropOptions { /** * the target widget where the handler shall be installed. */ target: DragAndDropTarget; /** * Will be called when a valid element has been dropped. */ onDrop?: (event: FileDropEvent) => void; /** * Determines if the drag & drop handler should be installed or uninstalled. Default implementation is checking {@link Widget.enabledComputed} */ doInstall?: () => boolean; /** * Returns the dom container providing the necessary drag & drop events. Default is {@link Widget.$container} */ container?: () => JQuery; /** * The scout type which will be allowed to drop into the target. Default is {@link DropType.FILE_TRANSFER} */ supportedScoutTypes?: DropType | DropType[]; /** * Allowed mime types. * @see https://developer.mozilla.org/en-US/docs/Glossary/MIME_type */ allowedTypes?: () => string[]; /** * CSS selector which will be added to the event source. */ selector?: JQuery.Selector; /** * Returns the allowed drop type during a drop event. Default is {@link DropType.FILE_TRANSFER} */ dropType?: () => DropType; /** * Returns the maximum allowed size of a dropped object. Default is {@link Widget.dropMaximumSize} */ dropMaximumSize?: () => number; /** * An optional function to add a custom file validation logic. Throw a {@link DropValidationErrorMessage} to indicate a failed validation. * If no custom validator is installed, the default maximum file size validator is invoked. * @throws DropValidationErrorMessage */ validateFiles?: (files: File[], defaultValidator: (f: File[]) => void) => void; /** * Returns additional drop properties to be used in {@link DragAndDropHandler.uploadFiles} as uploadProperties */ additionalDropProperties?: (event: JQuery.DropEvent) => any; }