Skip to content

Commit

Permalink
feat(snapGrid): implement draggable snap grids
Browse files Browse the repository at this point in the history
Closes #4
  • Loading branch information
Matt Lewis committed Nov 27, 2016
1 parent d2fdcde commit 16a3df8
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
4 changes: 2 additions & 2 deletions demo/demo.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {Component} from '@angular/core';
<div mwlDraggable dropData="foo">
Drag me!
</div>
<div mwlDraggable dropData="bar">
Or drag me!
<div mwlDraggable dropData="bar" [snapGrid]="{x: 100, y: 100}">
I snap to a 100x100 grid
</div>
<div
[class.dropOverActive]="dropOverActive"
Expand Down
19 changes: 19 additions & 0 deletions src/draggable.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type Coordinates = {x: number, y: number};

type DragAxis = {x: boolean, y: boolean};

type SnapGrid = {x?: number, y?: number};

@Directive({
selector: '[mwlDraggable]'
})
Expand All @@ -21,6 +23,8 @@ export class Draggable implements OnInit, OnDestroy {

@Input() dragAxis: DragAxis = {x: true, y: true};

@Input() snapGrid: SnapGrid = {};

@Output() dragStart: EventEmitter<Coordinates> = new EventEmitter<Coordinates>();

@Output() dragging: EventEmitter<Coordinates> = new EventEmitter<Coordinates>();
Expand Down Expand Up @@ -58,12 +62,27 @@ export class Draggable implements OnInit, OnDestroy {

})
.map((moveData: Coordinates) => {

if (this.snapGrid.x) {
moveData.x = Math.floor(moveData.x / this.snapGrid.x) * this.snapGrid.x;
}

if (this.snapGrid.y) {
moveData.y = Math.floor(moveData.y / this.snapGrid.y) * this.snapGrid.y;
}

return moveData;
})
.map((moveData: Coordinates) => {

if (!this.dragAxis.x) {
moveData.x = 0;
}

if (!this.dragAxis.y) {
moveData.y = 0;
}

return moveData;
})
.takeUntil(Observable.merge(this.mouseUp, this.mouseDown));
Expand Down
36 changes: 36 additions & 0 deletions test/draggable.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('draggable directive', () => {
<div
mwlDraggable
[dragAxis]="dragAxis"
[snapGrid]="snapGrid"
(dragStart)="dragStart($event)"
(dragging)="dragging($event)"
(dragEnd)="dragEnd($event)">
Expand All @@ -26,6 +27,7 @@ describe('draggable directive', () => {
public dragging: sinon.SinonSpy = sinon.spy();
public dragEnd: sinon.SinonSpy = sinon.spy();
public dragAxis: any = {x: true, y: true};
public snapGrid: any = {};

}

Expand Down Expand Up @@ -118,4 +120,38 @@ describe('draggable directive', () => {
expect(fixture.componentInstance.dragEnd).to.have.been.calledWith({x: 0, y: 0});
});

it('should snap all horizontal drags to a grid', () => {
fixture.componentInstance.snapGrid = {x: 10};
fixture.detectChanges();
const draggableElement: HTMLElement = fixture.componentInstance.draggable.element.nativeElement;
triggerDomEvent('mousedown', draggableElement, {clientX: 5, clientY: 10});
triggerDomEvent('mousemove', draggableElement, {clientX: 7, clientY: 12});
expect(fixture.componentInstance.dragging).to.have.been.calledWith({x: 0, y: 2});
triggerDomEvent('mousemove', draggableElement, {clientX: 14, clientY: 18});
expect(fixture.componentInstance.dragging).to.have.been.calledWith({x: 0, y: 8});
triggerDomEvent('mousemove', draggableElement, {clientX: 15, clientY: 20});
expect(fixture.componentInstance.dragging).to.have.been.calledWith({x: 10, y: 10});
triggerDomEvent('mousemove', draggableElement, {clientX: 16, clientY: 22});
expect(fixture.componentInstance.dragging).to.have.been.calledWith({x: 10, y: 12});
triggerDomEvent('mouseup', draggableElement, {clientX: 16, clientY: 22});
expect(fixture.componentInstance.dragEnd).to.have.been.calledWith({x: 10, y: 12});
});

it('should snap all vertical drags to a grid', () => {
fixture.componentInstance.snapGrid = {y: 10};
fixture.detectChanges();
const draggableElement: HTMLElement = fixture.componentInstance.draggable.element.nativeElement;
triggerDomEvent('mousedown', draggableElement, {clientX: 10, clientY: 5});
triggerDomEvent('mousemove', draggableElement, {clientX: 12, clientY: 7});
expect(fixture.componentInstance.dragging).to.have.been.calledWith({x: 2, y: 0});
triggerDomEvent('mousemove', draggableElement, {clientX: 18, clientY: 14});
expect(fixture.componentInstance.dragging).to.have.been.calledWith({x: 8, y: 0});
triggerDomEvent('mousemove', draggableElement, {clientX: 20, clientY: 15});
expect(fixture.componentInstance.dragging).to.have.been.calledWith({x: 10, y: 10});
triggerDomEvent('mousemove', draggableElement, {clientX: 22, clientY: 16});
expect(fixture.componentInstance.dragging).to.have.been.calledWith({x: 12, y: 10});
triggerDomEvent('mouseup', draggableElement, {clientX: 22, clientY: 16});
expect(fixture.componentInstance.dragEnd).to.have.been.calledWith({x: 12, y: 10});
});

});

0 comments on commit 16a3df8

Please sign in to comment.