Skip to content

Commit be07300

Browse files
committed
feat(viewport): add view port service
1 parent edc0550 commit be07300

File tree

4 files changed

+85
-7
lines changed

4 files changed

+85
-7
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import {ViewPortService} from './view-port.service';
2+
import {beforeEach} from '@angular/core/testing/src/testing_internal';
3+
4+
describe('Viewport helper', () => {
5+
6+
let sut: ViewPortService;
7+
const documentMock = {
8+
defaultView: {
9+
innerHeight: 0,
10+
innerWidth: 0
11+
},
12+
};
13+
14+
beforeEach(() => sut = new ViewPortService(documentMock));
15+
16+
it('should detect when we drag over the top viewport', () => {
17+
const element = {
18+
getBoundingClientRect: () => ({top: -100, left: 0, bottom: 0, right: 0})
19+
} as any;
20+
const viewPortOverflow = sut.isOutOfViewport(element);
21+
expect(viewPortOverflow.top).toBeTruthy();
22+
});
23+
24+
it('should detect when we drag over the bottom viewport', () => {
25+
spyOn(window, 'innerHeight').and.returnValue(0);
26+
const element = {
27+
getBoundingClientRect: () => ({top: 0, left: 0, bottom: 100, right: 0})
28+
} as any;
29+
const viewPortOverflow = sut.isOutOfViewport(element);
30+
expect(viewPortOverflow.bottom).toBeTruthy();
31+
});
32+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {Inject, Injectable} from '@angular/core';
2+
import {DOCUMENT} from '@angular/common';
3+
4+
export interface ViewPortOverflow {
5+
top: boolean;
6+
bottom: boolean;
7+
}
8+
9+
@Injectable({
10+
providedIn: 'root'
11+
})
12+
export class ViewPortService {
13+
14+
private window: WindowProxy;
15+
16+
constructor(@Inject(DOCUMENT) private document) {
17+
this.window = document.defaultView;
18+
}
19+
20+
public isOutOfViewport(element: HTMLElement): ViewPortOverflow {
21+
22+
const bounding = element.getBoundingClientRect();
23+
return {
24+
top: bounding.top < 0,
25+
bottom: bounding.bottom > (this.window.innerHeight || document.documentElement.clientHeight)
26+
};
27+
}
28+
}

projects/ng-sortgrid/src/lib/ngsg-item.directive.spec.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ describe('NgsgItemDirective', () => {
2727
'setItems'
2828
]);
2929
const ngsgEventService = new NgsgEventsService();
30+
const viewPortService = {
31+
isOutOfViewport: () => ({
32+
top: false,
33+
bottom: false
34+
})
35+
} as any;
3036

3137
beforeEach(() => {
3238
sut = new NgsgItemDirective(
@@ -35,7 +41,8 @@ describe('NgsgItemDirective', () => {
3541
ngsgSelectionService,
3642
ngsgReflectService,
3743
ngsgStore,
38-
ngsgEventService
44+
ngsgEventService,
45+
viewPortService
3946
);
4047
});
4148

projects/ng-sortgrid/src/lib/ngsg-item.directive.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@ import {
55
EventEmitter,
66
HostListener,
77
Input,
8-
NgZone, OnChanges, OnDestroy,
8+
OnChanges,
9+
OnDestroy,
910
OnInit,
10-
Output, SimpleChanges
11+
Output,
12+
SimpleChanges
1113
} from '@angular/core';
1214

1315
import {NgsgReflectService} from './ngsg-reflect.service';
1416
import {NgsgStoreService} from './ngsg-store.service';
1517
import {NgsgSortService} from './ngsg-sort.service';
1618
import {NgsgSelectionService} from './ngsg-selection.service';
17-
import {NgsgClassService} from './ngsg-class.service';
18-
import {NgsgElementsHelper} from './ngsg-elements.helper';
1919
import {NgsgEventsService} from './ngsg-events.service';
2020
import {Subject} from 'rxjs';
2121
import {takeUntil} from 'rxjs/operators';
22-
import {group} from '@angular/animations';
22+
import {ViewPortService} from './helpers/view-port.service';
2323

2424
const selector = '[ngSortgridItem]';
2525

@@ -31,6 +31,7 @@ export class NgsgItemDirective implements OnInit, OnChanges, AfterViewInit, OnDe
3131
@Output() sorted = new EventEmitter<any>();
3232

3333
private selected = false;
34+
private SCROLLSPEED = 100;
3435
private destroy$ = new Subject();
3536

3637
constructor(
@@ -39,7 +40,8 @@ export class NgsgItemDirective implements OnInit, OnChanges, AfterViewInit, OnDe
3940
private selectionService: NgsgSelectionService,
4041
private reflectService: NgsgReflectService,
4142
private ngsgStore: NgsgStoreService,
42-
private ngsgEventService: NgsgEventsService
43+
private ngsgEventService: NgsgEventsService,
44+
private viewPortService: ViewPortService
4345
) {
4446
}
4547

@@ -88,6 +90,15 @@ export class NgsgItemDirective implements OnInit, OnChanges, AfterViewInit, OnDe
8890

8991
@HostListener('dragover', ['$event'])
9092
dragOver(event): boolean {
93+
94+
if (this.viewPortService.isOutOfViewport(event.target).top) {
95+
window.scrollBy({top: -this.SCROLLSPEED, behavior: 'smooth'});
96+
}
97+
98+
if (this.viewPortService.isOutOfViewport(event.target).bottom) {
99+
window.scrollBy({top: this.SCROLLSPEED, behavior: 'smooth'});
100+
}
101+
91102
if (event.preventDefault) {
92103
// Necessary. Allows us to drop.
93104
event.preventDefault();

0 commit comments

Comments
 (0)