Skip to content

Commit

Permalink
Merge pull request #420 from zjffun/feature/drag-stoped-event
Browse files Browse the repository at this point in the history
feature: add a drag stopped event
  • Loading branch information
tsov authored Jul 20, 2020
2 parents 4e1e1bc + 9f4933d commit e8f6091
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 1 deletion.
4 changes: 4 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ declare module '@shopify/draggable' {
? DragOutContainerEvent
: eventName extends 'drag:stop'
? DragStopEvent
: eventName extends 'drag:stopped'
? DragStoppedEvent
: eventName extends 'drag:pressure'
? DragPressureEvent
: eventName extends 'mirror:create'
Expand Down Expand Up @@ -124,6 +126,8 @@ declare module '@shopify/draggable' {

export class DragStopEvent extends DragEvent { }

export class DragStoppedEvent extends DragEvent { }

/**
* DraggableEvent
*/
Expand Down
10 changes: 10 additions & 0 deletions src/Draggable/DragEvent/DragEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,13 @@ export class DragPressureEvent extends DragEvent {
export class DragStopEvent extends DragEvent {
static type = 'drag:stop';
}

/**
* Drag stopped event
* @class DragStoppedEvent
* @module DragStoppedEvent
* @extends DragEvent
*/
export class DragStoppedEvent extends DragEvent {
static type = 'drag:stopped';
}
13 changes: 13 additions & 0 deletions src/Draggable/DragEvent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,16 @@ Read-only property for pressure applied on a draggable element. Value ranges fro
| **Cancelable** | false |
| **Cancel action** | - |
| **type** | `drag:stop` |

## DragStoppedEvent

`DragStoppedEvent` gets triggered after `DragStopEvent`. This event fires after `drag:stop` listeners have finished running,
the source element removed from the document and draggable classes are removed.

| | |
| ----------------- | ------------------ |
| **Specification** | `DragEvent` |
| **Interface** | `DragStoppedEvent` |
| **Cancelable** | false |
| **Cancel action** | - |
| **type** | `drag:stopped` |
17 changes: 17 additions & 0 deletions src/Draggable/DragEvent/tests/DragEvent.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
DragPressureEvent,
DragStartEvent,
DragStopEvent,
DragStoppedEvent,
} from '../DragEvent';

describe('DragEvent', () => {
Expand Down Expand Up @@ -259,3 +260,19 @@ describe('DragStopEvent', () => {
});
});
});

describe('DragStoppedEvent', () => {
describe('#constructor', () => {
it('should be instance of DragStoppedEvent', () => {
const event = new DragStoppedEvent();

expect(event).toBeInstanceOf(DragStoppedEvent);
});

it('should initialize with `type` of `drag:stopped`', () => {
const event = new DragStoppedEvent();

expect(event.type).toBe('drag:stopped');
});
});
});
10 changes: 10 additions & 0 deletions src/Draggable/Draggable.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
DragOverEvent,
DragStopEvent,
DragPressureEvent,
DragStoppedEvent,
} from './DragEvent';

const onDragStart = Symbol('onDragStart');
Expand Down Expand Up @@ -590,6 +591,15 @@ export default class Draggable {
this.lastPlacedContainer = null;
}, this.options.placedTimeout);

const dragStoppedEvent = new DragStoppedEvent({
source: this.source,
originalSource: this.originalSource,
sensorEvent: event.sensorEvent,
sourceContainer: this.sourceContainer,
});

this.trigger(dragStoppedEvent);

this.source = null;
this.originalSource = null;
this.currentOverContainer = null;
Expand Down
19 changes: 19 additions & 0 deletions src/Draggable/Plugins/Mirror/tests/Mirror.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -494,4 +494,23 @@ describe('Mirror', () => {

releaseMouse(draggable.source);
});

describe('when `drag:stopped`', () => {
it('mirror element was removed from document', async () => {
draggable = new Draggable(container, draggableOptions);

clickMouse(draggableElement);
waitForDragDelay();

await waitForPromisesToResolve();

const mirrorElement = document.querySelector('.draggable-mirror');

draggable.on('drag:stopped', () => {
expect(mirrorElement.parentNode).toBeNull();
});

releaseMouse(draggable.source);
});
});
});
2 changes: 2 additions & 0 deletions src/Draggable/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Allow excluding default plugins and default sensors. Use with caution as it may
| [`drag:out`][dragout] | Gets fired when dragging out of other draggable | false | - |
| [`drag:out:container`][dragoutcontainer] | Gets fired when dragging out of other draggable container | false | - |
| [`drag:stop`][dragstop] | Gets fired when draggable has been released | false | - |
| [`drag:stopped`][dragstopped] | Gets fired when draggable finished | false | - |
| [`drag:pressure`][dragpressure] | Gets fired when using force touch on draggable element | false | - |

[draggableinit]: DraggableEvent#draggableinitializedevent
Expand All @@ -123,6 +124,7 @@ Allow excluding default plugins and default sensors. Use with caution as it may
[dragout]: DragEvent#dragoutevent
[dragoutcontainer]: DragEvent#dragoutcontainerevent
[dragstop]: DragEvent#dragstopevent
[dragstopped]: DragEvent#dragstoppedevent
[dragpressure]: DragEvent#dragpressureevent

### Classes
Expand Down
47 changes: 46 additions & 1 deletion src/Draggable/tests/Draggable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
waitForRequestAnimationFrame,
} from 'helper';
import Draggable, {defaultOptions} from '../Draggable';
import {DragStartEvent, DragMoveEvent, DragStopEvent} from '../DragEvent';
import {DragStartEvent, DragMoveEvent, DragStopEvent, DragStoppedEvent} from '../DragEvent';
import {DraggableInitializedEvent, DraggableDestroyEvent} from '../DraggableEvent';
import {Focusable, Mirror, Scrollable, Announcement} from '../Plugins';
import {MouseSensor, TouchSensor} from '../Sensors';
Expand Down Expand Up @@ -607,6 +607,30 @@ describe('Draggable', () => {
expect(call).toBeInstanceOf(DragStopEvent);
});

it('triggers `drag:stopped` drag event on mouseup', () => {
const newInstance = new Draggable(containers, {
draggable: 'li',
});
const draggableElement = sandbox.querySelector('li');
document.elementFromPoint = () => draggableElement;

triggerEvent(draggableElement, 'mousedown', {button: 0});

// Wait for delay
waitForDragDelay();

const callback = jest.fn();
newInstance.on('drag:stopped', callback);

triggerEvent(draggableElement, 'mouseup', {button: 0});

const call = callback.mock.calls[0][0];

expect(call.type).toBe('drag:stopped');

expect(call).toBeInstanceOf(DragStoppedEvent);
});

it('adds `source:dragging` classname to draggable element on mousedown', () => {
const newInstance = new Draggable(containers, {
draggable: 'li',
Expand Down Expand Up @@ -881,4 +905,25 @@ describe('Draggable', () => {

triggerEvent(document.body, 'mouseup', {button: 0});
});

describe('when `drag:stopped`', () => {
it('source element was removed from document', () => {
const newInstance = new Draggable(containers, {
draggable: 'li',
});
const draggableElement = sandbox.querySelector('li');
document.elementFromPoint = () => draggableElement;

newInstance.on('drag:stopped', (event) => {
expect(event.source.parentNode).toBeNull();
});

clickMouse(draggableElement);

// Wait for delay
waitForDragDelay();

releaseMouse(newInstance.source);
});
});
});

0 comments on commit e8f6091

Please sign in to comment.