From: Alexander Ebert Date: Wed, 4 Nov 2020 12:36:22 +0000 (+0100) Subject: Export `Ui/Redactor/DragAndDrop` to TypeScript X-Git-Tag: 5.4.0_Alpha_1~636^2~16 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=1b7f6af70b9fde7ae047c8ec822c57ed060754f3;p=GitHub%2FWoltLab%2FWCF.git Export `Ui/Redactor/DragAndDrop` to TypeScript --- diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.js index 42ef5b8811..f20bb51347 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.js @@ -2,200 +2,172 @@ * Drag and Drop file uploads. * * @author Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH + * @copyright 2001-2019 WoltLab GmbH * @license GNU Lesser General Public License * @module WoltLabSuite/Core/Ui/Redactor/DragAndDrop */ -define(['Dictionary', 'EventHandler', 'Language'], function (Dictionary, EventHandler, Language) { +define(["require", "exports", "tslib", "../../Event/Handler", "../../Language"], function (require, exports, tslib_1, EventHandler, Language) { "use strict"; - if (!COMPILER_TARGET_DEFAULT) { - var Fake = function () { }; - Fake.prototype = { - init: function () { }, - _dragOver: function () { }, - _drop: function () { }, - _dragLeave: function () { }, - _setup: function () { } - }; - return Fake; - } - var _didInit = false; - var _dragArea = new Dictionary(); - var _isDragging = false; - var _isFile = false; - var _timerLeave = null; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.init = void 0; + EventHandler = tslib_1.__importStar(EventHandler); + Language = tslib_1.__importStar(Language); + let _didInit = false; + const _dragArea = new Map(); + let _isDragging = false; + let _isFile = false; + let _timerLeave = null; /** - * @exports WoltLabSuite/Core/Ui/Redactor/DragAndDrop + * Handles items dragged into the browser window. */ - return { - /** - * Initializes drag and drop support for provided editor instance. - * - * @param {$.Redactor} editor editor instance - */ - init: function (editor) { - if (!_didInit) { - this._setup(); - } - _dragArea.set(editor.uuid, { - editor: editor, - element: null - }); - }, - /** - * Handles items dragged into the browser window. - * - * @param {Event} event drag event - */ - _dragOver: function (event) { - event.preventDefault(); - //noinspection JSUnresolvedVariable - if (!event.dataTransfer || !event.dataTransfer.types) { - return; + function _dragOver(event) { + event.preventDefault(); + if (!event.dataTransfer || !event.dataTransfer.types) { + return; + } + let isFirefox = false; + Object.keys(event.dataTransfer).forEach((property) => { + if (property.startsWith("moz")) { + isFirefox = true; } - var isFirefox = false; - //noinspection JSUnresolvedVariable - for (var property in event.dataTransfer) { - //noinspection JSUnresolvedVariable - if (event.dataTransfer.hasOwnProperty(property) && property.match(/^moz/)) { - isFirefox = true; - break; - } + }); + // IE and WebKit set 'Files', Firefox sets 'application/x-moz-file' for files being dragged + // and Safari just provides 'Files' along with a huge list of garbage + _isFile = false; + if (isFirefox) { + // Firefox sets the 'Files' type even if the user is just dragging an on-page element + if (event.dataTransfer.types[0] === "application/x-moz-file") { + _isFile = true; } - // IE and WebKit set 'Files', Firefox sets 'application/x-moz-file' for files being dragged - // and Safari just provides 'Files' along with a huge list of garbage - _isFile = false; - if (isFirefox) { - // Firefox sets the 'Files' type even if the user is just dragging an on-page element - //noinspection JSUnresolvedVariable - if (event.dataTransfer.types[0] === 'application/x-moz-file') { + } + else { + event.dataTransfer.types.forEach((type) => { + if (type === "Files") { _isFile = true; } - } - else { - //noinspection JSUnresolvedVariable - for (var i = 0; i < event.dataTransfer.types.length; i++) { - //noinspection JSUnresolvedVariable - if (event.dataTransfer.types[i] === 'Files') { - _isFile = true; - break; - } - } - } - if (!_isFile) { - // user is just dragging around some garbage, ignore it - return; - } - if (_isDragging) { - // user is still dragging the file around - return; - } - _isDragging = true; - _dragArea.forEach((function (data, uuid) { - var editor = data.editor.$editor[0]; - if (!editor.parentNode) { - _dragArea.delete(uuid); - return; - } - var element = data.element; - if (element === null) { - element = elCreate('div'); - element.className = 'redactorDropArea'; - elData(element, 'element-id', data.editor.$element[0].id); - elData(element, 'drop-here', Language.get('wcf.attachment.dragAndDrop.dropHere')); - elData(element, 'drop-now', Language.get('wcf.attachment.dragAndDrop.dropNow')); - element.addEventListener('dragover', function () { element.classList.add('active'); }); - element.addEventListener('dragleave', function () { element.classList.remove('active'); }); - element.addEventListener('drop', this._drop.bind(this)); - data.element = element; - } - editor.parentNode.insertBefore(element, editor); - element.style.setProperty('top', editor.offsetTop + 'px', ''); - }).bind(this)); - }, - /** - * Handles items dropped onto an editor's drop area - * - * @param {Event} event drop event - * @protected - */ - _drop: function (event) { - if (!_isFile) { - return; - } - //noinspection JSUnresolvedVariable - if (!event.dataTransfer || !event.dataTransfer.files.length) { + }); + } + if (!_isFile) { + // user is just dragging around some garbage, ignore it + return; + } + if (_isDragging) { + // user is still dragging the file around + return; + } + _isDragging = true; + _dragArea.forEach((data, uuid) => { + const editor = data.editor.$editor[0]; + if (!editor.parentElement) { + _dragArea.delete(uuid); return; } - event.preventDefault(); - //noinspection JSCheckFunctionSignatures - var elementId = elData(event.currentTarget, 'element-id'); - //noinspection JSUnresolvedVariable - for (var i = 0, length = event.dataTransfer.files.length; i < length; i++) { - //noinspection JSUnresolvedVariable - EventHandler.fire('com.woltlab.wcf.redactor2', 'dragAndDrop_' + elementId, { - file: event.dataTransfer.files[i] + let element = data.element; + if (element === null) { + element = document.createElement("div"); + element.className = "redactorDropArea"; + element.dataset.elementId = data.editor.$element[0].id; + element.dataset.dropHere = Language.get("wcf.attachment.dragAndDrop.dropHere"); + element.dataset.dropNow = Language.get("wcf.attachment.dragAndDrop.dropNow"); + element.addEventListener("dragover", () => { + element.classList.add("active"); }); + element.addEventListener("dragleave", () => { + element.classList.remove("active"); + }); + element.addEventListener("drop", (ev) => drop(ev)); + data.element = element; } - // this will reset all drop areas - this._dragLeave(); - }, - /** - * Invoked whenever the item is no longer dragged or was dropped. - * - * @protected - */ - _dragLeave: function () { - if (!_isDragging || !_isFile) { - return; - } - if (_timerLeave !== null) { - window.clearTimeout(_timerLeave); - } - _timerLeave = window.setTimeout(function () { - if (!_isDragging) { - _dragArea.forEach(function (data) { - if (data.element && data.element.parentNode) { - data.element.classList.remove('active'); - elRemove(data.element); - } - }); - } - _timerLeave = null; - }, 100); - _isDragging = false; - }, - /** - * Handles the global drop event. - * - * @param {Event} event - * @protected - */ - _globalDrop: function (event) { - if (event.target.closest('.redactor-layer') === null) { - var eventData = { cancelDrop: true, event: event }; - _dragArea.forEach(function (data) { - //noinspection JSUnresolvedVariable - EventHandler.fire('com.woltlab.wcf.redactor2', 'dragAndDrop_globalDrop_' + data.editor.$element[0].id, eventData); + editor.parentElement.insertBefore(element, editor); + element.style.setProperty("top", `${editor.offsetTop}px`, ""); + }); + } + /** + * Handles items dropped onto an editor's drop area + */ + function drop(event) { + if (!_isFile) { + return; + } + if (!event.dataTransfer || !event.dataTransfer.files.length) { + return; + } + event.preventDefault(); + const target = event.currentTarget; + const elementId = target.dataset.elementId; + Array.from(event.dataTransfer.files).forEach((file) => { + EventHandler.fire("com.woltlab.wcf.redactor2", `dragAndDrop_${elementId}`, { + file, + }); + }); + // this will reset all drop areas + dragLeave(); + } + /** + * Invoked whenever the item is no longer dragged or was dropped. + * + * @protected + */ + function dragLeave() { + if (!_isDragging || !_isFile) { + return; + } + if (_timerLeave !== null) { + window.clearTimeout(_timerLeave); + } + _timerLeave = window.setTimeout(() => { + if (!_isDragging) { + _dragArea.forEach((data) => { + if (data.element && data.element.parentElement) { + data.element.classList.remove("active"); + data.element.remove(); + } }); - if (eventData.cancelDrop) { - event.preventDefault(); - } } - this._dragLeave(event); - }, - /** - * Binds listeners to global events. - * - * @protected - */ - _setup: function () { - // discard garbage event - window.addEventListener('dragend', function (event) { event.preventDefault(); }); - window.addEventListener('dragover', this._dragOver.bind(this)); - window.addEventListener('dragleave', this._dragLeave.bind(this)); - window.addEventListener('drop', this._globalDrop.bind(this)); - _didInit = true; + _timerLeave = null; + }, 100); + _isDragging = false; + } + /** + * Handles the global drop event. + */ + function globalDrop(event) { + const target = event.target; + if (target.closest(".redactor-layer") === null) { + const eventData = { cancelDrop: true, event: event }; + _dragArea.forEach((data) => { + EventHandler.fire("com.woltlab.wcf.redactor2", `dragAndDrop_globalDrop_${data.editor.$element[0].id}`, eventData); + }); + if (eventData.cancelDrop) { + event.preventDefault(); + } } - }; + dragLeave(); + } + /** + * Binds listeners to global events. + * + * @protected + */ + function setup() { + // discard garbage event + window.addEventListener("dragend", (ev) => ev.preventDefault()); + window.addEventListener("dragover", (ev) => _dragOver(ev)); + window.addEventListener("dragleave", () => dragLeave()); + window.addEventListener("drop", (ev) => globalDrop(ev)); + _didInit = true; + } + /** + * Initializes drag and drop support for provided editor instance. + */ + function init(editor) { + if (!_didInit) { + setup(); + } + _dragArea.set(editor.uuid, { + editor: editor, + element: null, + }); + } + exports.init = init; }); diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.js b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.js deleted file mode 100644 index f41f3d6d79..0000000000 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.js +++ /dev/null @@ -1,234 +0,0 @@ -/** - * Drag and Drop file uploads. - * - * @author Alexander Ebert - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @module WoltLabSuite/Core/Ui/Redactor/DragAndDrop - */ -define(['Dictionary', 'EventHandler', 'Language'], function (Dictionary, EventHandler, Language) { - "use strict"; - - if (!COMPILER_TARGET_DEFAULT) { - var Fake = function() {}; - Fake.prototype = { - init: function() {}, - _dragOver: function() {}, - _drop: function() {}, - _dragLeave: function() {}, - _setup: function() {} - }; - return Fake; - } - - var _didInit = false; - var _dragArea = new Dictionary(); - var _isDragging = false; - var _isFile = false; - var _timerLeave = null; - - /** - * @exports WoltLabSuite/Core/Ui/Redactor/DragAndDrop - */ - return { - /** - * Initializes drag and drop support for provided editor instance. - * - * @param {$.Redactor} editor editor instance - */ - init: function (editor) { - if (!_didInit) { - this._setup(); - } - - _dragArea.set(editor.uuid, { - editor: editor, - element: null - }); - }, - - /** - * Handles items dragged into the browser window. - * - * @param {Event} event drag event - */ - _dragOver: function (event) { - event.preventDefault(); - - //noinspection JSUnresolvedVariable - if (!event.dataTransfer || !event.dataTransfer.types) { - return; - } - - var isFirefox = false; - //noinspection JSUnresolvedVariable - for (var property in event.dataTransfer) { - //noinspection JSUnresolvedVariable - if (event.dataTransfer.hasOwnProperty(property) && property.match(/^moz/)) { - isFirefox = true; - break; - } - } - - // IE and WebKit set 'Files', Firefox sets 'application/x-moz-file' for files being dragged - // and Safari just provides 'Files' along with a huge list of garbage - _isFile = false; - if (isFirefox) { - // Firefox sets the 'Files' type even if the user is just dragging an on-page element - //noinspection JSUnresolvedVariable - if (event.dataTransfer.types[0] === 'application/x-moz-file') { - _isFile = true; - } - } - else { - //noinspection JSUnresolvedVariable - for (var i = 0; i < event.dataTransfer.types.length; i++) { - //noinspection JSUnresolvedVariable - if (event.dataTransfer.types[i] === 'Files') { - _isFile = true; - break; - } - } - } - - if (!_isFile) { - // user is just dragging around some garbage, ignore it - return; - } - - if (_isDragging) { - // user is still dragging the file around - return; - } - - _isDragging = true; - - _dragArea.forEach((function (data, uuid) { - var editor = data.editor.$editor[0]; - if (!editor.parentNode) { - _dragArea.delete(uuid); - return; - } - - var element = data.element; - if (element === null) { - element = elCreate('div'); - element.className = 'redactorDropArea'; - elData(element, 'element-id', data.editor.$element[0].id); - elData(element, 'drop-here', Language.get('wcf.attachment.dragAndDrop.dropHere')); - elData(element, 'drop-now', Language.get('wcf.attachment.dragAndDrop.dropNow')); - - element.addEventListener('dragover', function () { element.classList.add('active'); }); - element.addEventListener('dragleave', function () { element.classList.remove('active'); }); - element.addEventListener('drop', this._drop.bind(this)); - - data.element = element; - } - - editor.parentNode.insertBefore(element, editor); - element.style.setProperty('top', editor.offsetTop + 'px', ''); - }).bind(this)); - }, - - /** - * Handles items dropped onto an editor's drop area - * - * @param {Event} event drop event - * @protected - */ - _drop: function (event) { - if (!_isFile) { - return; - } - - //noinspection JSUnresolvedVariable - if (!event.dataTransfer || !event.dataTransfer.files.length) { - return; - } - - event.preventDefault(); - - //noinspection JSCheckFunctionSignatures - var elementId = elData(event.currentTarget, 'element-id'); - - //noinspection JSUnresolvedVariable - for (var i = 0, length = event.dataTransfer.files.length; i < length; i++) { - //noinspection JSUnresolvedVariable - EventHandler.fire('com.woltlab.wcf.redactor2', 'dragAndDrop_' + elementId, { - file: event.dataTransfer.files[i] - }); - } - - // this will reset all drop areas - this._dragLeave(); - }, - - /** - * Invoked whenever the item is no longer dragged or was dropped. - * - * @protected - */ - _dragLeave: function () { - if (!_isDragging || !_isFile) { - return; - } - - if (_timerLeave !== null) { - window.clearTimeout(_timerLeave); - } - - _timerLeave = window.setTimeout(function () { - if (!_isDragging) { - _dragArea.forEach(function (data) { - if (data.element && data.element.parentNode) { - data.element.classList.remove('active'); - elRemove(data.element); - } - }); - } - - _timerLeave = null; - }, 100); - - _isDragging = false; - }, - - /** - * Handles the global drop event. - * - * @param {Event} event - * @protected - */ - _globalDrop: function (event) { - if (event.target.closest('.redactor-layer') === null) { - var eventData = { cancelDrop: true, event: event }; - _dragArea.forEach(function(data) { - //noinspection JSUnresolvedVariable - EventHandler.fire('com.woltlab.wcf.redactor2', 'dragAndDrop_globalDrop_' + data.editor.$element[0].id, eventData); - }); - - if (eventData.cancelDrop) { - event.preventDefault(); - } - } - - this._dragLeave(event); - }, - - /** - * Binds listeners to global events. - * - * @protected - */ - _setup: function () { - // discard garbage event - window.addEventListener('dragend', function (event) { event.preventDefault(); }); - - window.addEventListener('dragover', this._dragOver.bind(this)); - window.addEventListener('dragleave', this._dragLeave.bind(this)); - window.addEventListener('drop', this._globalDrop.bind(this)); - - _didInit = true; - } - }; -}); diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.ts new file mode 100644 index 0000000000..a78eaf8e90 --- /dev/null +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/DragAndDrop.ts @@ -0,0 +1,207 @@ +/** + * Drag and Drop file uploads. + * + * @author Alexander Ebert + * @copyright 2001-2019 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLabSuite/Core/Ui/Redactor/DragAndDrop + */ + +import * as EventHandler from "../../Event/Handler"; +import * as Language from "../../Language"; +import { RedactorEditor } from "./Editor"; + +type Uuid = string; + +interface EditorData { + editor: RedactorEditor; + element: HTMLElement | null; +} + +let _didInit = false; +const _dragArea = new Map(); +let _isDragging = false; +let _isFile = false; +let _timerLeave: number | null = null; + +/** + * Handles items dragged into the browser window. + */ +function _dragOver(event: DragEvent): void { + event.preventDefault(); + + if (!event.dataTransfer || !event.dataTransfer.types) { + return; + } + + let isFirefox = false; + Object.keys(event.dataTransfer).forEach((property) => { + if (property.startsWith("moz")) { + isFirefox = true; + } + }); + + // IE and WebKit set 'Files', Firefox sets 'application/x-moz-file' for files being dragged + // and Safari just provides 'Files' along with a huge list of garbage + _isFile = false; + if (isFirefox) { + // Firefox sets the 'Files' type even if the user is just dragging an on-page element + if (event.dataTransfer.types[0] === "application/x-moz-file") { + _isFile = true; + } + } else { + event.dataTransfer.types.forEach((type) => { + if (type === "Files") { + _isFile = true; + } + }); + } + + if (!_isFile) { + // user is just dragging around some garbage, ignore it + return; + } + + if (_isDragging) { + // user is still dragging the file around + return; + } + + _isDragging = true; + + _dragArea.forEach((data, uuid) => { + const editor = data.editor.$editor[0]; + if (!editor.parentElement) { + _dragArea.delete(uuid); + return; + } + + let element: HTMLElement | null = data.element; + if (element === null) { + element = document.createElement("div"); + element.className = "redactorDropArea"; + element.dataset.elementId = data.editor.$element[0].id; + element.dataset.dropHere = Language.get("wcf.attachment.dragAndDrop.dropHere"); + element.dataset.dropNow = Language.get("wcf.attachment.dragAndDrop.dropNow"); + + element.addEventListener("dragover", () => { + element!.classList.add("active"); + }); + element.addEventListener("dragleave", () => { + element!.classList.remove("active"); + }); + element.addEventListener("drop", (ev) => drop(ev)); + + data.element = element; + } + + editor.parentElement.insertBefore(element, editor); + element.style.setProperty("top", `${editor.offsetTop}px`, ""); + }); +} + +/** + * Handles items dropped onto an editor's drop area + */ +function drop(event: DragEvent): void { + if (!_isFile) { + return; + } + + if (!event.dataTransfer || !event.dataTransfer.files.length) { + return; + } + + event.preventDefault(); + + const target = event.currentTarget as HTMLElement; + const elementId = target.dataset.elementId!; + + Array.from(event.dataTransfer.files).forEach((file) => { + EventHandler.fire("com.woltlab.wcf.redactor2", `dragAndDrop_${elementId}`, { + file, + }); + }); + + // this will reset all drop areas + dragLeave(); +} + +/** + * Invoked whenever the item is no longer dragged or was dropped. + * + * @protected + */ +function dragLeave() { + if (!_isDragging || !_isFile) { + return; + } + + if (_timerLeave !== null) { + window.clearTimeout(_timerLeave); + } + + _timerLeave = window.setTimeout(() => { + if (!_isDragging) { + _dragArea.forEach((data) => { + if (data.element && data.element.parentElement) { + data.element.classList.remove("active"); + data.element.remove(); + } + }); + } + + _timerLeave = null; + }, 100); + + _isDragging = false; +} + +/** + * Handles the global drop event. + */ +function globalDrop(event: DragEvent): void { + const target = event.target as HTMLElement; + if (target.closest(".redactor-layer") === null) { + const eventData = { cancelDrop: true, event: event }; + _dragArea.forEach((data) => { + EventHandler.fire("com.woltlab.wcf.redactor2", `dragAndDrop_globalDrop_${data.editor.$element[0].id}`, eventData); + }); + + if (eventData.cancelDrop) { + event.preventDefault(); + } + } + + dragLeave(); +} + +/** + * Binds listeners to global events. + * + * @protected + */ +function setup() { + // discard garbage event + window.addEventListener("dragend", (ev) => ev.preventDefault()); + + window.addEventListener("dragover", (ev) => _dragOver(ev)); + window.addEventListener("dragleave", () => dragLeave()); + window.addEventListener("drop", (ev) => globalDrop(ev)); + + _didInit = true; +} + +/** + * Initializes drag and drop support for provided editor instance. + */ +export function init(editor: RedactorEditor): void { + if (!_didInit) { + setup(); + } + + _dragArea.set(editor.uuid, { + editor: editor, + element: null, + }); +} diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/Editor.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/Editor.ts index 757f4d958e..dbc413cf84 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/Editor.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ui/Redactor/Editor.ts @@ -1,4 +1,5 @@ export interface RedactorEditor { + uuid: string; $editor: JQuery; $element: JQuery;