Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/core/body/body.ctrl.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export declare class BodyCtrl {
onMouseMove(e: MouseEvent);
onMouseLeave(e: MouseEvent);
onMouseUp(e: MouseEvent);
resize(): void;
}
9 changes: 9 additions & 0 deletions src/core/body/body.ctrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { PathService } from '../path/path.service';
import { Fastdom } from '../services/fastdom';
import { GRID_PREFIX } from '../definition';
import { jobLine } from '../services/job.line';
import { ScrollService } from 'ng2-qgrid/core/scroll/scroll.service';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dont use ng2-qgrid in core use relative path


const MOUSE_LEFT_BUTTON = 1;
const VERTICAL_SCROLL_CLASS = `${GRID_PREFIX}-scroll-vertical`;
Expand All @@ -12,6 +13,7 @@ export class BodyCtrl {
this.model = model;
this.view = view;
this.bag = bag;
this.scrollService = new ScrollService(model, table, bag, view);
this.table = table;
this.rangeStartCell = null;
this.scrollingJob = jobLine(100);
Expand Down Expand Up @@ -131,6 +133,7 @@ export class BodyCtrl {
if (startCell && endCell) {
this.navigate(endCell);
this.view.selection.selectRange(startCell, endCell, 'body');
this.scrollService.scroll(e, startCell);
}
}
}
Expand All @@ -147,6 +150,8 @@ export class BodyCtrl {
}

onMouseUp(e) {
this.scrollService.stop();

const mode = this.selection.mode;
const edit = this.model.edit;

Expand Down Expand Up @@ -221,6 +226,10 @@ export class BodyCtrl {
}
}

resize() {
this.scrollService.invalidate();
}

get selection() {
return this.model.selection();
}
Expand Down
10 changes: 10 additions & 0 deletions src/core/scroll/scroll.model.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ export declare interface ScrollModel {
*/
cursor?: number;

/**
* Scroll velocity.
*/
velocity?: number;

/**
* Defines the distance from borders where scrolling should be initiated.
*/
offset?: number;

map: {
rowToView: (index: number) => number,
viewToRow: (index: number) => number,
Expand Down
2 changes: 2 additions & 0 deletions src/core/scroll/scroll.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export class ScrollModel {
this.top = 0;
this.left = 0;
this.cursor = 0;
this.velocity = 10;
this.offset = 50;

this.map = {
rowToView: identity,
Expand Down
9 changes: 9 additions & 0 deletions src/core/scroll/scroll.service.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Model } from '../infrastructure/model';
import { Table } from '../dom/table';

export declare class ScrollService {
constructor(model: Model, table: Table);

stop(): void;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add scroll method

invalidate(): void;
}
188 changes: 188 additions & 0 deletions src/core/scroll/scroll.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { AppError } from '../infrastructure/error';
import { jobLine } from '../services/job.line';
import { PathService } from '../path/path.service';

export class ScrollService {
constructor(model, table, bag, view) {
this.model = model;
this.table = table;
this.bag = bag;
this.view = view;
this.interval = null;
this.rect = null;
this.body = null;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use this.markup.body directly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

markup is not available during the ScrollService initialization

this.job = jobLine(0);
this.startCell = null;
this.mousePosition = null;

const pathFinder = new PathService(bag.body);
model.scrollChanged.watch(e => {
if (this.interval) {
const path = this.getPath(this.mousePosition);
const td = pathFinder.cell(path);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could it be that we do not find td?


this.navigate(td);
this.view.selection.selectRange(this.startCell, td, 'body');
}
});
}

canScroll(e) {
const table = this.rect;
Copy link
Collaborator

@klumba12 klumba12 Aug 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just call it rect: const {rect, offset} = this;

const offset = this.offset;

return !(e.clientY < (table.bottom - offset) &&
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split this to var defs:
const is... =

e.clientY > (table.top + offset) &&
e.clientX > (table.left + offset) &&
e.clientX < (table.right - offset))
}

scroll(e, startCell) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to start

this.mousePosition = e;
this.startCell = startCell;

if (!this.body) {
this.invalidate();
}

if (this.interval) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how it could happen on start?

if (!this.canScroll(e)) {
this.clearInterval();
return;
}
}

const direction = this.onEdgeOf(e);
if (direction && !this.interval) {
this.job(() => {
const interval = this.doScroll(direction);
this.interval = interval();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we emulate interval with jobs?

})
}

}

doScroll(direction) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to croll

const { scroll } = this.model;
const scrollState = scroll();
const { velocity } = scrollState;
const scrolledToEnd = () => this.isScrolledToEnd(direction);

return () => setInterval(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try to use job

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setInterval is located in function, which is already wrapped in Job.
image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is to tricky, we need to make own interval like a jobLine, or emulate it with job

if (!scrolledToEnd()) {
switch (direction) {
case 'right':
case 'bottom': {
const course = direction === 'bottom' ? 'top' : 'left';
const origin = scrollState[course];
scroll({ [course]: origin + velocity });
break;
}
case 'left':
case 'top': {
const course = direction === 'top' ? 'top' : 'left';
const origin = scrollState[course];
scroll({ [course]: origin - velocity });
break;
}
default: {
throw new AppError('scroll.service', `doScroll: Wrong direction`);
}
}
}
}, 50);
}

isScrolledToEnd(direction) {
const body = this.body;

switch (direction) {
case 'top': {
return body.scrollTop === 0;
}
case 'bottom': {
return body.clientHeight === body.scrollHeight - body.scrollTop;
}
case 'left': {
return body.scrollLeft === 0;
}
case 'right': {
return body.scrollLeft === body.scrollWidth - body.clientWidth;
}
default: {
throw new AppError('scroll.service', `isScrolledToEnd: Wrong direction`);
}
}
}

onEdgeOf(e) {
const table = this.rect;
const offset = this.offset;

if (e.clientY < (table.top + offset) &&
e.clientX > (table.left + offset) &&
e.clientX < (table.right - offset)) {
return 'top';
}

if (e.clientY > (table.bottom - offset) &&
e.clientX > (table.left + offset) &&
e.clientX < (table.right - offset)) {
return 'bottom';
}

if (e.clientX < (table.left + offset) &&
e.clientY > (table.top + offset) &&
e.clientY < (table.bottom - offset)) {
return 'left';
}

if (e.clientX > (table.right - offset) &&
e.clientY > (table.top + offset) &&
e.clientY < (table.bottom - offset)) {
return 'right';
}

return false;
}

invalidate() {
const { view } = this.table;

this.body = view.markup.body;
this.rect = view.rect(this.body);
}

stop() {
if(this.interval) {
this.clearInterval();
}
}

clearInterval() {
clearInterval(this.interval);
this.interval = null;
}

navigate(cell) {
const { focus } = this.view.nav;
if (focus.canExecute(cell)) {
focus.execute(cell);
}
}

getPath(e) {
const path = [];
let element = document.elementFromPoint(e.clientX, e.clientY);
while (element) {
path.push(element);
element = element.parentElement;
}

return path;
}

get offset() {
return this.model.scroll().offset;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write unit tests

16 changes: 13 additions & 3 deletions src/lib/main/core/body/body-core.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, ElementRef, OnInit, NgZone, Input, ChangeDetectorRef } from '@angular/core';
import { Component, ElementRef, OnInit, NgZone, Input, ChangeDetectorRef, Inject } from '@angular/core';
import { EventListener } from 'ng2-qgrid/core/infrastructure/event.listener';
import { EventManager } from 'ng2-qgrid/core/infrastructure/event.manager';
import { ColumnView } from 'ng2-qgrid/core/scene/view/column.view';
Expand All @@ -12,7 +12,8 @@ import { TableCoreService } from '../table/table-core.service';

@Component({
selector: 'tbody[q-grid-core-body]',
templateUrl: './body-core.component.html'
templateUrl: './body-core.component.html',
providers: [{ provide: 'window', useValue: window }]
})
export class BodyCoreComponent extends NgComponent implements OnInit {
@Input() pin = 'body';
Expand All @@ -21,6 +22,7 @@ export class BodyCoreComponent extends NgComponent implements OnInit {
rowId: (index: number, row: any) => any;

constructor(
@Inject('window') private window: Window,
private element: ElementRef,
public $view: ViewCoreService,
public $table: TableCoreService,
Expand All @@ -39,6 +41,7 @@ export class BodyCoreComponent extends NgComponent implements OnInit {
const table = this.$table;
const ctrl = new BodyCtrl(model, view, this.root.table, this.root.bag);
const listener = new EventListener(element, new EventManager(this));
const windowListener = new EventListener(this.window, new EventManager(this));

this.zone.runOutsideAngular(() => {
listener.on('wheel', e => ctrl.onWheel(e));
Expand All @@ -56,7 +59,14 @@ export class BodyCoreComponent extends NgComponent implements OnInit {
});

listener.on('mousedown', ctrl.onMouseDown.bind(ctrl));
listener.on('mouseup', ctrl.onMouseUp.bind(ctrl));

windowListener.on('resize', () => ctrl.resize());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigate if it could be run outsize ng zone

windowListener.on('mouseup', (e) => {
const isActive = model.focus().isActive;
if (isActive) {
ctrl.onMouseUp(e);
}
});

const { id } = model.data();
this.rowId = id.row;
Expand Down
9 changes: 2 additions & 7 deletions src/lib/main/core/cell/cell-handler.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,8 @@ export class CellHandlerComponent implements OnInit, AfterViewInit {

get isMarkerVisible() {
const model = this.root.model;
const { column } = model.navigation();
const method = model.edit().method;

if (column) {
const type = column.type;
return model.edit().method === 'batch';
}

return false;
return method === 'batch';
}
}