Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 1 | // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
Paul Lewis | 9950e18 | 2019-12-16 16:06:07 | [diff] [blame] | 4 | |
Paul Lewis | 9950e18 | 2019-12-16 16:06:07 | [diff] [blame] | 5 | import {createShadowRootWithCoreStyles} from './utils/create-shadow-root-with-core-styles.js'; |
| 6 | |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 7 | /** |
| 8 | * @unrestricted |
| 9 | */ |
Paul Lewis | 9950e18 | 2019-12-16 16:06:07 | [diff] [blame] | 10 | export class DropTarget { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 11 | /** |
| 12 | * @param {!Element} element |
| 13 | * @param {!Array<{kind: string, type: !RegExp}>} transferTypes |
| 14 | * @param {string} messageText |
Tim van der Lippe | 403a88d | 2020-05-13 11:51:32 | [diff] [blame] | 15 | * @param {function(!DataTransfer):*} handleDrop |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 16 | */ |
| 17 | constructor(element, transferTypes, messageText, handleDrop) { |
| 18 | element.addEventListener('dragenter', this._onDragEnter.bind(this), true); |
| 19 | element.addEventListener('dragover', this._onDragOver.bind(this), true); |
| 20 | this._element = element; |
| 21 | this._transferTypes = transferTypes; |
| 22 | this._messageText = messageText; |
| 23 | this._handleDrop = handleDrop; |
| 24 | this._enabled = true; |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 25 | /** @type {?Element} */ |
| 26 | this._dragMaskElement = null; |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 27 | } |
| 28 | |
| 29 | /** |
| 30 | * @param {boolean} enabled |
| 31 | */ |
| 32 | setEnabled(enabled) { |
| 33 | this._enabled = enabled; |
| 34 | } |
| 35 | |
| 36 | /** |
| 37 | * @param {!Event} event |
| 38 | */ |
| 39 | _onDragEnter(event) { |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 40 | if (this._enabled && this._hasMatchingType(event)) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 41 | event.consume(true); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 42 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 43 | } |
| 44 | |
| 45 | /** |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 46 | * @param {!Event} ev |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 47 | * @return {boolean} |
| 48 | */ |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 49 | _hasMatchingType(ev) { |
| 50 | const event = /** @type {!DragEvent} */ (ev); |
| 51 | if (!event.dataTransfer) { |
| 52 | return false; |
| 53 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 54 | for (const transferType of this._transferTypes) { |
| 55 | const found = Array.from(event.dataTransfer.items).find(item => { |
| 56 | return transferType.kind === item.kind && !!transferType.type.exec(item.type); |
| 57 | }); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 58 | if (found) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 59 | return true; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 60 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 61 | } |
| 62 | return false; |
| 63 | } |
| 64 | |
| 65 | /** |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 66 | * @param {!Event} ev |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 67 | */ |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 68 | _onDragOver(ev) { |
| 69 | const event = /** @type {!DragEvent} */ (ev); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 70 | if (!this._enabled || !this._hasMatchingType(event)) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 71 | return; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 72 | } |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 73 | if (event.dataTransfer) { |
| 74 | event.dataTransfer.dropEffect = 'copy'; |
| 75 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 76 | event.consume(true); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 77 | if (this._dragMaskElement) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 78 | return; |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 79 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 80 | this._dragMaskElement = this._element.createChild('div', ''); |
Paul Lewis | 9950e18 | 2019-12-16 16:06:07 | [diff] [blame] | 81 | const shadowRoot = createShadowRootWithCoreStyles(this._dragMaskElement, 'ui/dropTarget.css'); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 82 | shadowRoot.createChild('div', 'drop-target-message').textContent = this._messageText; |
| 83 | this._dragMaskElement.addEventListener('drop', this._onDrop.bind(this), true); |
| 84 | this._dragMaskElement.addEventListener('dragleave', this._onDragLeave.bind(this), true); |
| 85 | } |
| 86 | |
| 87 | /** |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 88 | * @param {!Event} ev |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 89 | */ |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 90 | _onDrop(ev) { |
| 91 | const event = /** @type {!DragEvent} */ (ev); |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 92 | event.consume(true); |
| 93 | this._removeMask(); |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 94 | if (this._enabled && event.dataTransfer) { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 95 | this._handleDrop(event.dataTransfer); |
Tim van der Lippe | 1d6e57a | 2019-09-30 11:55:34 | [diff] [blame] | 96 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 97 | } |
| 98 | |
| 99 | /** |
| 100 | * @param {!Event} event |
| 101 | */ |
| 102 | _onDragLeave(event) { |
| 103 | event.consume(true); |
| 104 | this._removeMask(); |
| 105 | } |
| 106 | |
| 107 | _removeMask() { |
Simon Zünd | f676009 | 2020-08-13 06:19:28 | [diff] [blame^] | 108 | if (this._dragMaskElement) { |
| 109 | this._dragMaskElement.remove(); |
| 110 | this._dragMaskElement = null; |
| 111 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 112 | } |
Tim van der Lippe | 0830b3d | 2019-10-03 13:20:07 | [diff] [blame] | 113 | } |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 114 | |
Tim van der Lippe | 0830b3d | 2019-10-03 13:20:07 | [diff] [blame] | 115 | export const Type = { |
Blink Reformat | 4c46d09 | 2018-04-07 15:32:37 | [diff] [blame] | 116 | URI: {kind: 'string', type: /text\/uri-list/}, |
| 117 | Folder: {kind: 'file', type: /$^/}, |
| 118 | File: {kind: 'file', type: /.*/}, |
| 119 | WebFile: {kind: 'file', type: /[\w]+/}, |
| 120 | ImageFile: {kind: 'file', type: /image\/.*/}, |
| 121 | }; |