HTML5 Drag and Drop effectAllowed and dropEffect

23.7k views Asked by At

The relationship between these two properties seems to have been the source of some confusion. Based on reading both the MDN site and MSDN I thought i had figured it out, but now I am not sure...

I figured that when an element is dragged, you can specify what is allowed to happen to it (i.e. it can be moved, copied, linked to - one of the effectAllowed constants). This is the effectAllowed property.

Different drop targets do different things, so when you dragover another element it can control which "effect" takes place on the drop, this is the "dropEffect" property. So I set up a simple example to test this theory out:

JSFiddle

$("[draggable='true']").on("dragstart", function(e) {
    var dt =  e.originalEvent.dataTransfer;
    dt.effectAllowed = "copyMove";
    dt.setData("text/plain", "Foo");
});

$("#dropZoneCopy").on("dragover", function(e) {
    var dt =  e.originalEvent.dataTransfer;
    dt.dropEffect = "copy";
    e.preventDefault();
});

$("#dropZoneMove").on("dragover", function(e) {
    var dt =  e.originalEvent.dataTransfer;
    dt.dropEffect = "move";
    e.preventDefault();
});

I have a box the user can drag - the effects allowed are "copyMove". I have one box that sets dropEffect to copy, and once that sets dropEffect to move. What I expect is that when the user drags over the "copy box" the cursor will change to indicate a copy will happen, as I drag over the "move box" the cursor changes to indicate a move...

Only Chrome behaves as I would expect. Is this because the other browsers are wrong or because I don't understand the spec. properly ?

UPDATE Some more information from fiddling with this;

In both Firefox and Chrome, if you have a dragsource which indicates the effectAllowed is "copy" and a dropzone that says dropEffect is "move" then you cannot drop on the drop zone even if you cancel the event. I thought that dropEffect would be useful to read ondrop to see what to do, but it isn't available on Chrome, the dropEffect does not appear on the drop handler, e.g. trying to read the dataTransfer.dropEffect will say that the dropEffect is "none" even though you set it on dragover. Setting the dropEffect as noted above does influence the way the cursor is displayed.

On Firefox, the dropEffect does come through on the dropzone after being set on dragover, but it does not influence the display of the mouse cursor. On Firefox windows pressing the ctrl key does affect the display of the mouse, but does not affect the dropEffect property.

The spec shows that the source can listen for the dragend event to see what happened. It should look at the dropEffect within this event. Chrome, Mozilla and Safari work as you would hope here, the drop effect appears in the dragend event. In IE if the effect allowed is a simple value e.g. "copy" then any successful drop results in this value appearing as the dropEffect on dragend. If the effectAllowed was a compound value like copyMove and you tried to select "move" on dragover by setting the dropEffect, you're out of luck, that will come through as dropEffect = "none" at the source on dragend. You are stuck with one cursor & one dropEffect and that is the effectAllowed set on dragstart if that effect is a simple value. Interestingly the dropEffect it seems does come through when you drag into a native application from IE11 at least (and i assume earlier).

Other notes

On Safari on a mac - effectAllowed cannot be set programatically, therefore any dropEffect that gets set is valid. When you press the cmd key the effectAllowed becomes "move" and when you press the alt key the effectAllowed becomes "copy". Thereafter it works as you would hope, if the dropEffect is not one of these effectAlloweds the drop is not allowed by the browser.

More Info I've been spending some spare time working on an HTML5 drag and drop library i wrote a bunch more about this and other issues in the docs for it, if you're interested please take a look at the project

3

There are 3 answers

0
Owen Jones On

take a look at https://web.dev/drag-and-drop/

function handleDrop(e) {
  e.stopPropagation(); // Stops some browsers from redirecting.
  e.preventDefault();

  var files = e.dataTransfer.files;
  for (var i = 0, f; f = files[i]; i++) {
    // Read the File objects in this FileList.
  }
}
0
Arun Kashyap On

I see you want to implement drag and drop functionality with the provided HTML elements and jQuery. There's a minor issue in your code; you need to handle the drop event to complete the drag-and-drop functionality. Here's the corrected code:

$(function() {
            $("[draggable='true']").on("dragstart", function(e) {
                var dt = e.originalEvent.dataTransfer;
                dt.effectAllowed = "copyMove";
                dt.setData("text/plain", "Foo");
            });

            $("#dropZoneCopy, #dropZoneMove").on("dragover", function(e) {
                e.preventDefault();
                var dt = e.originalEvent.dataTransfer;
                dt.dropEffect = "copy";
            });

            $("#dropZoneCopy").on("drop", function(e) {
                e.preventDefault();
                var data = e.originalEvent.dataTransfer.getData("text/plain");
                $(this).text(data);
            });

            $("#dropZoneMove").on("drop", function(e) {
                e.preventDefault();
                var data = e.originalEvent.dataTransfer.getData("text/plain");
                $(this).text(data);
            });
        });
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Drag and Drop Example</title>
    <style>
        [draggable="true"] {
            cursor: move; /* Change cursor to indicate draggable element */
        }

        #dropZoneCopy, #dropZoneMove {
            width: 200px;
            height: 100px;
            border: 2px dashed #000;
            margin: 10px;
            padding: 10px;
        }
    </style>
</head>
<body>
    <div draggable="true">Drag Me!</div>

    <div id="dropZoneCopy">Drop On Me to copy</div>
    <div id="dropZoneMove">Drop On Me to move</div>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</body>
</html>

In this code:

The CSS sets the cursor to "move" for the draggable element, making it visually clear that it can be dragged.

We added event listeners for the drop event on the drop zones (#dropZoneCopy and #dropZoneMove) to handle the drop action and update their content with the dragged data.

Now, when you drag and drop the "Drag Me!" element onto the copy or move drop zones, it will update the drop zone's content with "Foo" text.

1
suresh kumar On

The log messages you provided seem to be related to a development environment, likely a code editor or an integrated development environment (IDE), such as Visual Studio Code or a similar tool. These messages typically pertain to code formatting using Prettier, a code formatter for JavaScript and other languages.

Let's break down what each part of the log means:

  1. ["INFO" - 11:47:04 AM] Formatting completed in 44ms.: This is an informational message indicating that code formatting was completed successfully, and it took 44 milliseconds to do so. This typically means that your code was automatically formatted to adhere to your coding style rules.

  2. ["INFO" - 12:16:47 PM] Formatting file:///d%3A/Javascript/Work/01-Fundamentals-Part-1/index.html: This message indicates that a file located at the specified path (file:///d%3A/Javascript/Work/01-Fundamentals-Part-1/index.html) was formatted. It seems like this file was successfully formatted.

  3. ["ERROR" - 12:16:47 PM] Invalid prettier configuration file detected.: This is an error message indicating that there is a problem with the Prettier configuration file in your project. Prettier relies on a configuration file (usually named .prettierrc or similar) to determine how code should be formatted.

  4. ["ERROR" - 12:16:47 PM] ENOENT: no such file or directory, open 'C:\node_modules\prettier': This error message suggests that there is a missing or inaccessible directory related to Prettier. It's looking for a prettier directory within the C:\node_modules path and can't find it.

  5. Error: ENOENT: no such file or directory, open 'C:\node_modules\prettier': This is the error message itself, indicating that the prettier directory within C:\node_modules is missing.

  6. ["ERROR" - 12:16:47 PM] Invalid prettier configuration file detected. See log for details.: This message reiterates the presence of an invalid Prettier configuration file and suggests checking the log for more details.

To resolve this issue, you should:

  1. Ensure that you have a valid Prettier configuration file (e.g., .prettierrc) in your project's root directory or a relevant location. Make sure it's correctly formatted and specifies your desired code formatting rules.

  2. Check that your project's dependencies, including Prettier, are properly installed. Run npm install or yarn install in your project directory to ensure all required packages are installed.

  3. If you encounter issues with the Prettier configuration file, review its contents and make any necessary corrections.

  4. Ensure that your development environment or code editor is correctly configured to use Prettier. You may need to check your editor's settings or extensions to make sure it's integrated with Prettier.

  5. If the issue persists, consider checking the specific log mentioned in the error message for additional details to diagnose the problem further.

Remember to adapt these steps to your specific development environment and project setup.