diff --git a/CHANGELOG.md b/CHANGELOG.md index 019538a..197552c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,14 @@ # Changelog +## Version 1.4.0 (2018-10-12) + +- Add an option `minDragStartDistance` on `Draggable` to define the minimum distance in + pixels that is needed for a drag to start (#26). Default is `4` pixels. This allows for clicks with tiny movement. The option `clickSuppression` has been marked as DEPRECATED as it had the same goal but a misleading name. + ## Version 1.3.0 (2018-08-15) - Align dart version to support Dart 2 (#25). - ## Version 1.2.0 (2018-06-21) - Support for creating a Draggable with `List` (in addition to `ElementList` and `Element`). diff --git a/README.md b/README.md index eaee7f1..f4d549f 100644 --- a/README.md +++ b/README.md @@ -5,35 +5,30 @@ Drag and Drop for Dart web apps with mouse and touch support. [![Star this Repo](https://img.shields.io/github/stars/marcojakob/dart-dnd.svg?style=flat-square)](https://github.com/marcojakob/dart-dnd) [![Pub Package](https://img.shields.io/pub/v/dnd.svg?style=flat-square)](https://pub.dartlang.org/packages/dnd) - [GitHub](https://github.com/marcojakob/dart-dnd) | [Pub](https://pub.dartlang.org/packages/dnd) | [Demos and Examples](http://code.makery.ch/library/dart-drag-and-drop/) - ![DnD Screenshot](https://raw.githubusercontent.com/marcojakob/dart-dnd/master/doc/dnd-screenshot.png) - ## 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. - +- 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](http://code.makery.ch/library/dart-drag-and-drop/). - ### Basic Set Up Create a `Draggable` and give it some HTML elements; this will make them @@ -65,88 +60,87 @@ Draggable draggable = new Draggable(querySelectorAll('.draggable'), avatarHandler: new AvatarHandler.original()); ``` - ### Draggable Options -The following options can be passed as *named parameters* to the constructor of +The following options can be passed as _named parameters_ to the constructor of `Draggable`: -* `avatarHandler`: Is responsible for creating, position, and removing a drag +- `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 - * `new AvatarHandler.original()` - handler that uses the original + + - `null` (the default) - will not create a drag avatar + - `new AvatarHandler.original()` - handler that uses the original draggable as avatar. See `OriginalAvatarHandler`. - * `new AvatarHandler.clone()` - handler that uses a clone of the draggable + - `new 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 + - A custom `AvatarHandler` - you can provide your own implementation of `AvatarHandler`. -* `horizontalOnly`: If set to true, only horizontal dragging is tracked. +- `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. +- `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 +- `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 +- `cancel`: If cancel query String is specified, drag starting is prevented on specified elements. -* `draggingClass`: Is the css class set to the dragged element +- `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 +- `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 `Stream`s on `Draggable`: -* `onDragStart`: Fired when the user starts dragging. - *Note: `onDragStart` is fired not on touchStart or mouseDown but as +- `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.* + 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.* +- `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 +The following options can be passed as _named parameters_ to the constructor of `Dropzone`: -* `acceptor`: Is used to determine which `Draggable`s will be accepted by +- `acceptor`: Is used to determine which `Draggable`s will be accepted by this `Dropzone`. If none is specified, all `Draggable`s will be accepted. -* `overClass`: Is the css class set to the dropzone element when an 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 +- `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 `Stream`s on `Dropzone`: -* `onDragEnter`: Fired when a `Draggable` enters this `Dropzone`. - -* `onDragOver`: Fired periodically while a `Draggable` is moved over a `Dropzone`. +- `onDragEnter`: Fired when a `Draggable` enters this `Dropzone`. -* `onDragLeave`: Fired when a `Draggable` leaves this `Dropzone`. +- `onDragOver`: Fired periodically while a `Draggable` is moved over a `Dropzone`. -* `onDrop`: Fired when a `Draggable` is dropped inside this `Dropzone`. +- `onDragLeave`: Fired when a `Draggable` leaves this `Dropzone`. -*Note: `Dropzone` events are only fired when the `Draggable` is accepted by -the `Acceptor`.* +- `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 @@ -165,16 +159,15 @@ a `dnd-retarget` attribute to the host: ``` - ## Attribution -The *Dart Drag and Drop* library is inspired by +The _Dart Drag and Drop_ library is inspired by -* [jQuery UI Draggable](http://jqueryui.com/draggable/) -* [Draggabilly](http://draggabilly.desandro.com/) +- [jQuery UI Draggable](http://jqueryui.com/draggable/) +- [Draggabilly](http://draggabilly.desandro.com/) Thank you for your work! - ## License + The MIT License (MIT) diff --git a/analysis_options.yaml b/analysis_options.yaml index 6dd0787..338ed79 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,8 +1,3 @@ -analyzer: - strong-mode: true - errors: - uri_has_not_been_generated: ignore - # Lint rules and documentation, see http://dart-lang.github.io/linter/lints linter: rules: diff --git a/lib/src/draggable.dart b/lib/src/draggable.dart index 5b625b5..b6d5a17 100644 --- a/lib/src/draggable.dart +++ b/lib/src/draggable.dart @@ -53,8 +53,18 @@ class Draggable { /// See [Draggable] constructor. String draggingClassBody; + /// The minimum distance in pixels that is needed for a drag to start. + /// See [Draggable] constructor. + int minDragStartDistance; + /// The minimum distance for a drag to prevent click events. - int clickSuppression = 0; + /// DEPRECATED: Please use [minDragStartDistance] instead. + @deprecated + get clickSuppression => minDragStartDistance; + + /// DEPRECATED: Please use [minDragStartDistance] instead. + @deprecated + set clickSuppression(int distance) => minDragStartDistance = distance; // ------------------- // Events @@ -148,6 +158,10 @@ class Draggable { /// /// The [draggingClassBody] is the css class set to the html body tag /// during a drag. If set to null, no such css class is added. + /// + /// The [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(elementOrElementList, {this.avatarHandler: null, this.horizontalOnly: false, @@ -155,7 +169,8 @@ class Draggable { this.handle: null, this.cancel: 'input, textarea, button, select, option', this.draggingClass: 'dnd-dragging', - this.draggingClassBody: 'dnd-drag-occurring'}) { + this.draggingClassBody: 'dnd-drag-occurring', + this.minDragStartDistance: 4}) { // Wrap in a List if it is not a list but a single Element. _elements = elementOrElementList is List ? elementOrElementList @@ -262,11 +277,8 @@ class Draggable { event.preventDefault(); } - if (event is MouseEvent && - (clickSuppression <= 0 || - _currentDrag.startPosition.distanceTo(_currentDrag.position) > - clickSuppression)) { - // Prevent MouseEvent from firing a click after mouseUp event if the move was significant. + // Prevent MouseEvent from firing a click after mouseUp event. + if (event is MouseEvent) { _suppressClickEvent(_currentDrag.element); } diff --git a/lib/src/draggable_manager.dart b/lib/src/draggable_manager.dart index b45f75b..0ef3045 100644 --- a/lib/src/draggable_manager.dart +++ b/lib/src/draggable_manager.dart @@ -86,16 +86,15 @@ abstract class _EventManager { // Set the current position. _currentDrag.position = position; - if (!_currentDrag.started && - _currentDrag.startPosition != _currentDrag.position) { - // This is the first drag move. - - // Handle dragStart. - drg._handleDragStart(event); - } - - // Handle drag (will also be called after drag start). - if (_currentDrag.started) { + if (!_currentDrag.started) { + // Test if drag has moved far enough to start drag. + if (_currentDrag.startPosition.distanceTo(_currentDrag.position) >= + drg.minDragStartDistance) { + // Drag starts now. + drg._handleDragStart(event); + } + } else { + // Drag already started. Element realTarget = _getRealTarget(clientPosition); drg._handleDrag(event, realTarget); } diff --git a/pubspec.yaml b/pubspec.yaml index 41095ef..4bf3bb1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: dnd -version: 1.3.0 +version: 1.4.0 author: Marco Jakob description: Drag and Drop for Dart web apps with mouse and touch support. homepage: http://code.makery.ch/library/dart-drag-and-drop/