Drag and Drop for Dart web apps with mouse and touch support.

Last update: Apr 22, 2022

Dart Drag and Drop

Drag and Drop for Dart web apps with mouse and touch support.

Star this Repo Pub Package

GitHub | Pub | Demos and Examples

DnD Screenshot

Features

  • Use any HTML Element as Draggable or Dropzone.
  • Mouse and Touch dragging.
  • Draggable events: dragStart, drag, and dragEnd
  • Dropzone events: dragEnter, dragOver, dragLeave, and drop
  • Drag avatars as visual indication of a drag operation:
    • Original element as drag avatar.
    • Clone as drag avatar.
    • Custom drag avatar.
  • Support for Shadow DOM (Web Components, Custom Elements, Polymer, etc.).
  • Much more... see examples.

Usage

Before you read the instructions below, you should take a look at the examples.

Basic Set Up

Create a Draggable and give it some HTML elements; this will make them draggable. You can either pass a single Element to the constructor or an ElementList that is returned by querySelectorAll.

If you also want to drop somewhere, you'll need a Dropzone.

// Install draggable (no avatar).
Draggable draggable = Draggable(querySelectorAll('.draggable'));

// Install dropzone.
Dropzone dropzone = Dropzone(querySelector('.dropzone'));

You'll most likely want some drag avatar to show the user that a drag is going on. There are two predefined AvatarHandlers that you can use as follows. But you could also provide your own implementation of AvatarHandler.

// Draggable with clone as avatar.
Draggable draggable = Draggable(querySelectorAll('.draggable'),
    avatarHandler: AvatarHandler.clone());


// Draggable with original element as avatar.
Draggable draggable = Draggable(querySelectorAll('.draggable'),
    avatarHandler: AvatarHandler.original());

Draggable Options

The following options can be passed as named parameters to the constructor of Draggable:

  • avatarHandler: Is responsible for creating, position, and removing a drag avatar. A drag avatar provides visual feedback during a drag operation. Here are possible options (see above for an example):

    • null (the default) - will not create a drag avatar
    • AvatarHandler.original() - handler that uses the original draggable as avatar. See OriginalAvatarHandler.
    • AvatarHandler.clone() - handler that uses a clone of the draggable element as avatar. See CloneAvatarHandler.
    • A custom AvatarHandler - you can provide your own implementation of AvatarHandler.
  • horizontalOnly: If set to true, only horizontal dragging is tracked. This enables vertical touch dragging to be used for scrolling.

  • verticalOnly: If set to true, only vertical dragging is tracked. This enables horizontal touch dragging to be used for scrolling.

  • handle: If handle query String is specified, it restricts the dragging from starting unless it occurs on the specified element(s). Only elements that descend from the draggables elements are permitted.

  • cancel: If cancel query String is specified, drag starting is prevented on specified elements.

  • draggingClass: Is the css class set to the dragged element during a drag. If set to null, no such css class is added.

  • draggingClassBody: Is the css class set to the html body tag during a drag. If set to null, no such css class is added.

  • minDragStartDistance: Is the minimum distance in pixels that is needed for a drag to start. Default is 4. This allows for clicks with tiny movement.

Draggable Events

Available event Streams on Draggable:

  • onDragStart: Fired when the user starts dragging.
    Note: onDragStart is fired not on touchStart or mouseDown but as soon as there is a drag movement. When a drag is started an onDrag event will also be fired.

  • onDrag: Fired periodically throughout the drag operation.

  • onDragEnd: Fired when the user ends the dragging.
    Note: Is also fired when the user clicks the 'esc'-key or the window loses focus.

Dropzone Options

The following options can be passed as named parameters to the constructor of Dropzone:

  • acceptor: Is used to determine which Draggables will be accepted by this Dropzone. If none is specified, all Draggables will be accepted.

  • overClass: Is the css class set to the dropzone element when an accepted draggable is dragged over it. If set to null, no such css class is added.

  • invalidClass: Is the css class set to the dropzone element when a not-accepted draggable is dragged over it. If set to null, no such css class is added.

Dropzone Events

Available event Streams on Dropzone:

  • onDragEnter: Fired when a Draggable enters this Dropzone.

  • onDragOver: Fired periodically while a Draggable is moved over a Dropzone.

  • onDragLeave: Fired when a Draggable leaves this Dropzone.

  • onDrop: Fired when a Draggable is dropped inside this Dropzone.

Note: Dropzone events are only fired when the Draggable is accepted by the Acceptor.

Shadow DOM

Web Components create a nice ecapsulation through Shadow DOM. But this creates a problem with dropzones inside the Shadow DOM as they never receive events because all events are captured by the host element. To make this work we need to retarget events to the Shadow DOM children through recursive elementFromPoint() calls.

For performance reasons it wouldn't make sense to retarget all drag and drop events. If you wish to retarget events to the Shadow DOM children, you must add a dnd-retarget attribute to the host:

// Retarget drag and drop events to Shadow DOM children.
<my-element dnd-retarget></my-element>

Attribution

The Dart Drag and Drop library is inspired by

Thank you for your work!

Running / Building / Testing

  • Run from the terminal: webdev serve
  • Build from the terminal: webdev build

License

The MIT License (MIT)

GitHub

https://github.com/marcojakob/dart-dnd
Comments
  • 1. Not working in Windows 8.1 IE11 Metro

    By the way it's not working on Windows 8.1 IE11 Metro. Some <meta ...> should be added to html for disabling default back/forward on drag?

    Reported by Slava Pankov

    Reviewed by marcojakob at 2014-07-18 07:51
  • 2. Fix mouse drag suppression

    We noticed that drag suppression hasn't really been working. This fixes that, by effectively not starting a drag event until the suppression distance has been met. Once the distance has been exceeded, the drag started event is dispatched.

    @marcojakob

    Reviewed by spencercornish-wk at 2018-10-11 20:06
  • 3. If the page contents scrolls out of the visible area x + y for mouse position becomes wrong

    screenshot-1669

    Here you can see where the mouse cursor is and where the draggable object ist. http://wsk.angular.mikemitterer.at/styleguide/index.html#/draganddrop

    The problem becomes even worser on mobile where the page is narrower...

    Reviewed by MikeMitterer at 2015-03-02 22:34
  • 4. Dropzones don't work with Shadow DOM due to event retargeting

    The onMouseMove events setup in draggable.dart (https://github.com/marcojakob/dart-dnd/blob/master/lib/src/draggable.dart#L320) will never handle targets within Shadow DOM. Reason for this is, that events from within the Shadow DOM are retargeted to its host. For event handlers setup outside the host, the event target will always be the host and not potential drop targets within.

    // Install mouseMove listener.
        _dragSubs.add(document.onMouseMove.listen((MouseEvent event) {
    

    Also have a look here: http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-301/#toc-events

    A solution might be to also register mouseover handlers, when the dropzone is installed to elements and react properly.

    Reviewed by friegger at 2014-07-18 19:10
  • 5. fix for shadow dom

    Hi Marco, I fix your DnD to work with polymer. It's only in added Document in which events happens. Feel free about pull / rewrite / drop this ;)

    Br, František Belšán

    Reviewed by Belsi at 2015-03-01 22:16
  • 6. NoSuchMethodError: method not found: 'pubspec'

    Since 0.2.0 I get

    Precompiling dependencies...
    Loading source assets...
    The null object does not have a getter 'pubspec'.
    
    NoSuchMethodError: method not found: 'pubspec'
    Receiver: null
    Arguments: []
    dart:core                                                                                                                       Object.noSuchMethod
    /Volumes/data/b/build/slave/dart-editor-mac-dev/build/dart/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart 251   _PackageDependencyComputer._PackageDependencyComputer
    /Volumes/data/b/build/slave/dart-editor-mac-dev/build/dart/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart 199   DependencyComputer._loadPackageComputer
    /Volumes/data/b/build/slave/dart-editor-mac-dev/build/dart/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart 107   DependencyComputer._transformersNeededByTransformer
    /Volumes/data/b/build/slave/dart-editor-mac-dev/build/dart/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart 258   _PackageDependencyComputer._PackageDependencyComputer
    /Volumes/data/b/build/slave/dart-editor-mac-dev/build/dart/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart 199   _loadPackageComputer
    dart:core                                                                                                                       List.forEach
    /Volumes/data/b/build/slave/dart-editor-mac-dev/build/dart/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart 53    DependencyComputer.DependencyComputer
    /Volumes/data/b/build/slave/dart-editor-mac-dev/build/dart/sdk/lib/_internal/pub/lib/src/barback/load_all_transformers.dart 33  loadAllTransformers.<async>
    dart:isolate
    

    If I remove the dependency to your package the error is gone.

    Reviewed by MikeMitterer at 2015-03-09 11:50
  • 7. dnd-over class does not get removed when abort the dragging with esc-key

    I've the issue, that the dnd-over class stays on the last dragged over element when i abort the dragging with esc-key.

    Is there a way to disable the abort with esc?

    Reviewed by frickt at 2019-03-12 10:39
  • 8. Please add drag&drop reordering

    Wow, this must be one of the best drag&drop library ever! Only one request: can you support a drag&drop reordering of vertical (or horizontal) lists of elements? For example if I want to move an element from the position 4 of the list to the position 10, it should be able to do it in the following ways:

    • INSERT AFTER: shift all the elements > 10 down (or right) and put the 4 at the 11th position
    • INSERT BEFORE : shift all the elements > 9 down (or right) and put the 4 at the 10h position
    • SWITCH : put the element 4 in place of element 10, and element 10 in place of element 4, without moving any other elements
    • GROUP INSERT : shift a multiple selection of N elements from their original positions to the 11+N position, using the INSERT AFTER mode for the group of elements
    • GROUP SWITCH : put a multiple selection of N elements from their original position 4+N to 11+N, and the group of elements that was 11+N in place of the elements that were at the 4+N position.

    Also those features should be useful: REALTIME REORDERING WHILE WE DRAG: dragging an element or a group of elements above the list should animate the list showing the auto reordering of the list in case the element is dropped at the current point. MULTI-COLUMNS / ROWS SUPPORT : drag&drop reordering should work in multi columns or multi rows elements lists, with the possibility to drag&drop between different columns or rows. UNDO: an animation should undo the latest drag&drop reordering

    Reviewed by Emasoft at 2014-07-18 09:22
  • 9. Cannot initialize Dropzone with List

    Could we change the check in the constructor for Dropzone from:

        if (_elementOrElementList is ElementList) {
    

    to

       if (_elementOrElementList is List<Element>) {
    

    I would like to use the library together with angular dart's ViewChildren where i get a List.

    Or is there a reason for ElementList?

    Reviewed by frickt at 2019-02-13 22:03
  • 10. touch gesture interpreted by OS during drag

    Firstly, thanks for a great library. I am trying to do DnD on touch devices. However, the drag gesture also has an effect on the whole page. Using your example: https://github.com/marcojakob/dart-dnd/tree/master/example/basic On an iPhone or iPad while dragging the paper (which becomes a face) the whole page moves.

    Do you know how to stop this?

    Finally, you library is the only one I could get to work with the Chrome Developer Tools Touch mode!! Cheers, Phil.

    Reviewed by pslavers at 2018-07-19 00:56
  • 11. Handle the edge case where destroy is called while dragging an avatar.

    This addresses https://github.com/marcojakob/dart-dnd/issues/17

    I tested it in our use case, and it worked. I didn't add unit tests, because it doesn't look like the repo has any setup for it, and I don't want to force my unit test tool opinions upon you.

    Reviewed by tomconnell-wf at 2016-11-22 17:21
  • 12. Scrollable areas and parent elements with margins

    In an AngularDart app with a scrollable div, the positioning of the drag avatar is off when dragging inside the scrolled div. The following subclass of OriginalAvatarHandler fixed it for me - but I don't know if it'll break in other circumstances:

    class CustomAvatarHandler extends OriginalAvatarHandler {
      Point _delta;
    
      @override
      void dragStart(Element draggable, Point startPosition) {
        Point clientPos = draggable.getBoundingClientRect().topLeft;
        Point offsetPos = draggable.offset.topLeft;
        _delta = Point(offsetPos.x - clientPos.x, offsetPos.y - clientPos.y);
        super.dragStart(draggable, startPosition);
        avatar.style.position = 'fixed';
        setLeftTop(offsetPos);
      }
    
      @override
      void setLeftTop(Point position) {
        super.setLeftTop(Point(position.x - _delta.x, position.y - _delta.y));
      }
    }
    
    Reviewed by erikhugintech at 2020-02-13 01:46
  • 13. How to make new item also draggable?

    Initially I have a table of 4 rows, and I initialized Draggable once.

        Draggable(tableElement, avatarHandler: AvatarHandler.clone());
    
        Dropzone dropzone = Dropzone(stationListElement);
    
        dropzone.onDrop.listen((DropzoneEvent event) {
          _reorder(event.draggableElement, event.dropzoneElement);
        });
    

    Later the component added a new row after some user interaction.

    Problem is that new row isn't draggable. I tried initialize again but the drop event is listened twice.

    Do you have any suggestion how to handle it on my use case?

    Reviewed by warenix at 2019-05-03 09:33
  • 14. Not scrollable on mobile with handle

    Hi!

    When filling a whole page with a list of list tiles with drag handles, when touching the non-handle part, the page is not able to scroll, whereas when touching outside of the tile it is possible.

        AvatarHandler avatar = AvatarHandler.clone();
    
        dropzone = Dropzone(querySelectorAll('.sortable-zone'));
    
        draggable = Draggable(querySelectorAll('.sortable'),
            avatarHandler: avatar, handle: '.handle');
    
    Reviewed by martinory at 2019-01-20 22:38
  • 15. Feature Request

    Let me say your lib is great and easy to use. However, it is lacking one feature (and so is the native dart) that would ease development for many. That one feature would be the offset between the mouse pointer (position) and the upper left corner of the element being dragged. This would help in setting the position for the element being dragged.

    Reviewed by Monotoba at 2018-02-14 18:51

Related

Native Drag and Drop for Flutter on iOS and MacOS

native_draggable A new flutter plugin project. Getting Started This project is a starting point for a Flutter plug-in package, a specialized package t

Jan 27, 2022
Drag and drop module for CITMATEL's 'strawberry' project

citmatel_strawberry_dnd Drag and drop module for CITMATEL's 'strawberry' project Getting Started This project is a starting point for a Flutter applic

Jan 21, 2022
Flutter package for drag-and-drop reordering of two-level lists
Flutter package for drag-and-drop reordering of two-level lists

drag_and_drop_lists Two-level drag and drop reorderable lists. Features Reorder elements between multiple lists Reorder lists Drag and drop new elemen

May 18, 2022
APP desenvolvido em flutter que se comunica com uma API desenvolvida em python para controlar o mouse e teclado da maquina onde a API roda.

INSTRUÇÕES PARA EXECUÇÃO DA API Para executar a api em python, é necessario instalar as bibliotecas pynput, uvicorn e starlette e pyqrcode. Basta exec

Mar 2, 2022
A flutter deskstop package that allows you to drag the native file into app support.
A flutter deskstop package that allows you to drag the native file into app support.

FileDragAndDrop A flutter deskstop package that allows you to drag the native file into app support. Platform Support Now only support on macOS, if an

May 10, 2022
ESP-Touch Dart API for Flutter. Platform-specific implementation for Android (Java) and iOS (Objective-C).
ESP-Touch Dart API for Flutter. Platform-specific implementation for Android (Java) and iOS (Objective-C).

esptouch_flutter Flutter plugin for ESP-Touch to configure network for ESP-8266 and ESP-32 devices. Runs on iOS and Android. esptouch_flutter is Flutt

Apr 15, 2022
An online Dart editor with support for console, web, and Flutter apps
An online Dart editor with support for console, web, and Flutter apps

DartPad DartPad is a free, open-source online editor to help developers learn about Dart and Flutter. You can access it at dartpad.dev. What is it? Wh

May 20, 2022
A zero-dependency web framework for writing web apps in plain Dart.

Rad Rad is a frontend framework for creating fast and interactive web apps using Dart. It's inspired from Flutter and shares same programming paradigm

May 18, 2022
Flutter plugin that secures your secrets in keychain using biometric authentication (Fingerprint, Touch ID, Face ID...).
Flutter plugin that secures your secrets in keychain using biometric authentication (Fingerprint, Touch ID, Face ID...).

Flutter Locker ?? Flutter plugin that secures your secrets in keychain using biometric authentication (Fingerprint, Touch ID, Face ID...). It uses: Lo

Jan 27, 2022
Alarm app where user setting with touch gesture by moving the hand clock
Alarm app where user setting with touch gesture by moving the hand clock

Alarm App Using Flutter Flutter alarm app where user setting with touch gesture by moving the hand clock How to run Clone this repository Run flutter

May 2, 2022
Parallax - A parallax package for touch-based devices, providing a visually appealing user experience
Parallax - A parallax package for touch-based devices, providing a visually appealing user experience

Parallax A parallax package for touch-based devices, providing a visually appeal

Feb 24, 2022
Drop shadow effect for any widget in Flutter
Drop shadow effect for any widget in Flutter

DropShadow Drop shadow effect for any widget in flutter Parameters Widget child; // required double blurRadius; // default: 10.0 double borderRadius;

Dec 18, 2021
A flutter list view which can drag & move item to change order.
A flutter list view which can drag & move item to change order.

draggable_flutter_list A flutter list view which can drag & move item to change order. some codes come from flutter_list_drag_and_drop fix flutter_lis

Dec 24, 2021
A page transition which supports drag-down-to-pop gesture.

drag_down_to_pop A page transition which supports drag-down-to-pop gesture. The main source code is copied from the cupertino/route.dart in Flutter SD

Jan 9, 2022
Flutter plugin, support android/ios.Support crop, flip, rotate, color martix, mix image, add text. merge multi images.
Flutter plugin, support android/ios.Support crop, flip, rotate, color martix, mix image, add text. merge multi images.

image_editor The version of readme pub and github may be inconsistent, please refer to github. Use native(objc,kotlin) code to handle image data, it i

May 15, 2022
Simple Dart package for creating mailto links in your Flutter apps or web pages
Simple Dart package for creating mailto links in your Flutter apps or web pages

mailto Simple Dart package for creating mailto links in your Flutter and Dart apps The mailto package helps you build mailto links and provides you wi

Apr 24, 2022
A font loader to download, cache and load web fonts in flutter with support for Firebase Cloud Storage.
A font loader to download, cache and load web fonts in flutter with support for Firebase Cloud Storage.

Dynamic Cached Fonts A simple, easy to use yet customizable font loader to use web fonts. Demo: https://sidrao2006.github.io/dynamic_cached_fonts ?? I

Apr 27, 2022
Github-apps-flutter - Github Apps Build Using bloc 8.0 and Github API
Github-apps-flutter - Github Apps Build Using bloc 8.0 and Github API

Github_apps Inspiration This app is made to build using bloc 8.0 and github API.

Apr 14, 2022