Skip to content

Commit 0cce956

Browse files
authored
Merge branch '8.1.x' into fix-for-5432-master
2 parents f98478f + 38b7aaa commit 0cce956

File tree

7 files changed

+129
-47
lines changed

7 files changed

+129
-47
lines changed

projects/igniteui-angular/src/lib/core/touch.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ export class HammerGesturesManager {
2020
inputClass: Hammer.TouchInput,
2121
recognizers: [
2222
[ Hammer.Pan, { threshold: 0 } ],
23-
[ Hammer.Pinch, { enable: true } ],
24-
[ Hammer.Rotate, { enable: true } ],
2523
[ Hammer.Swipe, {
2624
direction: Hammer.DIRECTION_HORIZONTAL
27-
}]
25+
}],
26+
[Hammer.Tap],
27+
[Hammer.Tap, { event: 'doubletap', taps: 2 }, ['tap']]
2828
]
2929
};
3030

@@ -44,14 +44,14 @@ export class HammerGesturesManager {
4444
public addEventListener(element: HTMLElement,
4545
eventName: string,
4646
eventHandler: (eventObj) => void,
47-
options: object = null): () => void {
47+
options: HammerOptions = null): () => void {
4848

4949
// Creating the manager bind events, must be done outside of angular
5050
return this._zone.runOutsideAngular(() => {
5151
let mc: HammerManager = this.getManagerForElement(element);
5252
if (mc === null) {
5353
// new Hammer is a shortcut for Manager with defaults
54-
mc = new Hammer(element, this.hammerOptions);
54+
mc = new Hammer(element, Object.assign(this.hammerOptions, options));
5555
this.addManagerForElement(element, mc);
5656
}
5757
const handler = (eventObj) => { this._zone.run(() => { eventHandler(eventObj); }); };

projects/igniteui-angular/src/lib/grids/cell.component.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { State } from '../services/index';
2323
import { IgxGridBaseComponent, IGridEditEventArgs, IGridDataBindable } from './grid-base.component';
2424
import { IgxGridSelectionService, ISelectionNode, IgxGridCRUDService } from '../core/grid-selection';
2525
import { DeprecateProperty } from '../core/deprecateDecorators';
26+
import { HammerGesturesManager } from '../core/touch';
2627

2728
/**
2829
* Providing reference to `IgxGridCellComponent`:
@@ -40,7 +41,8 @@ import { DeprecateProperty } from '../core/deprecateDecorators';
4041
@Component({
4142
changeDetection: ChangeDetectionStrategy.OnPush,
4243
selector: 'igx-grid-cell',
43-
templateUrl: './cell.component.html'
44+
templateUrl: './cell.component.html',
45+
providers: [HammerGesturesManager]
4446
})
4547
export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
4648
private _vIndex = -1;
@@ -530,7 +532,8 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
530532
public selection: IgxSelectionAPIService,
531533
public cdr: ChangeDetectorRef,
532534
private element: ElementRef,
533-
protected zone: NgZone) { }
535+
protected zone: NgZone,
536+
private touchManager: HammerGesturesManager) { }
534537

535538

536539
/**
@@ -552,6 +555,9 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
552555
this.nativeElement.addEventListener('compositionend', this.compositionEndHandler);
553556
}
554557
});
558+
this.touchManager.addEventListener(this.nativeElement, 'doubletap', this.onDoubleClick, {
559+
cssProps: { } /* don't disable user-select, etc */
560+
} as HammerOptions);
555561
}
556562

557563
/**
@@ -569,6 +575,7 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
569575
this.nativeElement.removeEventListener('compositionend', this.compositionEndHandler);
570576
}
571577
});
578+
this.touchManager.destroy();
572579
}
573580

574581
/**
@@ -716,7 +723,11 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
716723
* @internal
717724
*/
718725
@HostListener('dblclick', ['$event'])
719-
public onDoubleClick(event: MouseEvent) {
726+
public onDoubleClick = (event: MouseEvent| HammerInput) => {
727+
if (event.type === 'doubletap') {
728+
// prevent double-tap to zoom on iOS
729+
event.preventDefault();
730+
}
720731
if (this.editable && !this.editMode && !this.row.deleted) {
721732
this.crudService.begin(this);
722733
}

projects/igniteui-angular/src/lib/grids/grid/cell.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { UIInteractions, wait } from '../../test-utils/ui-interactions.spec';
88
import { configureTestSuite } from '../../test-utils/configure-suite';
99
import { IgxStringFilteringOperand } from '../../data-operations/filtering-condition';
1010
import { SampleTestData } from '../../test-utils/sample-test-data.spec';
11+
import { HammerGesturesManager } from '../../core/touch';
1112

1213
const DEBOUNCETIME = 30;
1314

@@ -171,6 +172,7 @@ describe('IgxGrid - Cell component', () => {
171172

172173
spyOn(grid.onDoubleClick, 'emit').and.callThrough();
173174
const event = new Event('dblclick');
175+
spyOn(event, 'preventDefault');
174176
cellElem.nativeElement.dispatchEvent(event);
175177
const args: IGridCellEventArgs = {
176178
cell: firstCell,
@@ -179,6 +181,38 @@ describe('IgxGrid - Cell component', () => {
179181

180182
fix.detectChanges();
181183

184+
expect(event.preventDefault).not.toHaveBeenCalled();
185+
expect(grid.onDoubleClick.emit).toHaveBeenCalledWith(args);
186+
expect(firstCell).toBe(fix.componentInstance.clickedCell);
187+
});
188+
189+
it('Should handle doubletap, trigger onDoubleClick event', () => {
190+
const addListenerSpy = spyOn(HammerGesturesManager.prototype, 'addEventListener');
191+
const fix = TestBed.createComponent(DefaultGridComponent);
192+
fix.detectChanges();
193+
194+
const grid = fix.componentInstance.instance;
195+
const cellElem = fix.debugElement.query(By.css(CELL_CSS_CLASS));
196+
const firstCell = grid.getCellByColumn(0, 'index');
197+
198+
// should attach 'doubletap'
199+
expect(addListenerSpy.calls.count()).toBeGreaterThan(1);
200+
expect(addListenerSpy).toHaveBeenCalledWith(firstCell.nativeElement, 'doubletap', firstCell.onDoubleClick, { cssProps: { } });
201+
202+
spyOn(grid.onDoubleClick, 'emit').and.callThrough();
203+
204+
const event = {
205+
type: 'doubletap',
206+
preventDefault: jasmine.createSpy('preventDefault')
207+
};
208+
firstCell.onDoubleClick(event as any);
209+
const args: IGridCellEventArgs = {
210+
cell: firstCell,
211+
event
212+
} as any;
213+
214+
fix.detectChanges();
215+
expect(event.preventDefault).toHaveBeenCalled();
182216
expect(grid.onDoubleClick.emit).toHaveBeenCalledWith(args);
183217
expect(firstCell).toBe(fix.componentInstance.clickedCell);
184218
});

projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-cell.component.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import { ChangeDetectorRef, ElementRef, ChangeDetectionStrategy, Component,
55
import { IgxHierarchicalGridComponent } from './hierarchical-grid.component';
66
import { IgxHierarchicalSelectionAPIService } from './selection';
77
import { IgxGridSelectionService, IgxGridCRUDService } from '../../core/grid-selection';
8+
import { HammerGesturesManager } from '../../core/touch';
89

910
@Component({
1011
changeDetection: ChangeDetectionStrategy.OnPush,
1112
preserveWhitespaces: false,
1213
selector: 'igx-hierarchical-grid-cell',
13-
templateUrl: './../cell.component.html'
14+
templateUrl: './../cell.component.html',
15+
providers: [HammerGesturesManager]
1416
})
1517
export class IgxHierarchicalGridCellComponent extends IgxGridCellComponent implements OnInit {
1618

@@ -25,8 +27,9 @@ export class IgxHierarchicalGridCellComponent extends IgxGridCellComponent imple
2527
public cdr: ChangeDetectorRef,
2628
private helement: ElementRef,
2729
protected zone: NgZone,
30+
touchManager: HammerGesturesManager
2831
) {
29-
super(selectionService, crudService, gridAPI, selection, cdr, helement, zone);
32+
super(selectionService, crudService, gridAPI, selection, cdr, helement, zone, touchManager);
3033
this.hSelection = <IgxHierarchicalSelectionAPIService>selection;
3134
}
3235

projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid-navigation.service.ts

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -292,35 +292,41 @@ export class IgxHierarchicalGridNavigationService extends IgxGridNavigationServi
292292
} else {
293293
this.focusNextChildDOMElem(currentRowEl, this.grid);
294294
}
295+
} else if (this.grid.parent && this.grid.parent.summariesRowList.length > 0) {
296+
this._navigateToNextParentRow(currentRowEl);
295297
} else {
296298
this.navigateDown(currentRowEl, { row: rowIndex, column: 0 });
297299
}
298300
} else if (isLastSummaryRow && isLastColumn && this.grid.parent) {
299-
// navigating in child summary, next is parent summary or next parent row
300-
const parent = this.grid.parent;
301-
const parentHasSummary = parent.summariesRowList.toArray().length > 0;
302-
const parentRowIndex = parseInt(
303-
this.getClosestElemByTag(currentRowEl, 'igx-child-grid-row').parentNode.getAttribute('data-rowindex'), 10);
304-
const isLastRowInParent = parent.verticalScrollContainer.igxForOf.length - 1 === parentRowIndex;
305-
// check if next is sibling
306-
const childRowContainer = this.getChildGridRowContainer(this.grid);
307-
const nextIsSiblingChild = !!childRowContainer.nextElementSibling;
308-
if (isLastRowInParent && parentHasSummary && !nextIsSiblingChild) {
309-
// next is parent summary
310-
const parentSummary = parent.summariesRowList.toArray()[0].nativeElement;
311-
parent.navigation.focusNextRow(parentSummary, 0, this.grid.rootGrid, true);
312-
} else {
313-
// next is sibling or parent
314-
this.focusNext(0);
315-
}
316-
} else if (isLastDataRow && hasSummaries && isLastColumn && this.grid.parent) {
301+
this._navigateToNextParentRow(currentRowEl);
302+
} else if (isLastDataRow && hasSummaries && isLastColumn && this.grid.parent) {
317303
// navigating in child rows, next is child grid's summary row
318-
this.focusNextRow(summaryRows[0].nativeElement, 0, this.grid.parent, true);
304+
this.focusNextRow(summaryRows[0].nativeElement, 0, this.grid.parent, true);
319305
} else {
320306
super.performTab(currentRowEl, selectedNode);
321307
}
322308
}
323309

310+
private _navigateToNextParentRow(currentRowEl: any): void {
311+
// next is parent summary or next parent row
312+
const parent = this.grid.parent;
313+
const parentHasSummary = parent.summariesRowList.length > 0;
314+
const parentRowIndex = parseInt(
315+
this.getClosestElemByTag(currentRowEl, 'igx-child-grid-row').parentNode.getAttribute('data-rowindex'), 10);
316+
const isLastRowInParent = parent.verticalScrollContainer.igxForOf.length - 1 === parentRowIndex;
317+
// check if next is sibling
318+
const childRowContainer = this.getChildGridRowContainer(this.grid);
319+
const nextIsSiblingChild = !!childRowContainer.nextElementSibling;
320+
if (isLastRowInParent && parentHasSummary && !nextIsSiblingChild) {
321+
// next is parent summary
322+
const parentSummary = parent.summariesRowList.first.nativeElement;
323+
parent.navigation.focusNextRow(parentSummary, 0, parent, true);
324+
} else {
325+
// next is sibling or parent
326+
this.focusNext(0);
327+
}
328+
}
329+
324330
private focusNextChildDOMElem(currentRowEl, grid) {
325331
const gridElem = currentRowEl.nextElementSibling.querySelector('igx-hierarchical-grid');
326332
const childGridID = gridElem.getAttribute('id');
@@ -443,21 +449,41 @@ export class IgxHierarchicalGridNavigationService extends IgxGridNavigationServi
443449

444450
private performShiftTabIntoChild(gridElem, currentRowEl, rowIndex) {
445451
const childGridID = gridElem.getAttribute('id');
446-
const childGrid = this.getChildGrid(childGridID, this.grid) || this.getChildGrid(childGridID, this.grid.parent);
447-
const lastIndex = childGrid.unpinnedColumns[childGrid.unpinnedColumns.length - 1].visibleIndex;
448-
const summaryRows = childGrid.summariesRowList.toArray();
449-
if (summaryRows.length > 0 && summaryRows[0].summaryCells.length > 0) {
450-
// move focus to last summary row cell
451-
const summaryRow = summaryRows[0].nativeElement;
452-
this.focusPrevRow(summaryRow, lastIndex, childGrid, true, true);
453-
} else if (childGrid.rowList.toArray().length === 0 &&
454-
childGrid.allowFiltering && childGrid.filterMode === FilterMode.quickFilter) {
455-
// move to filter cell
456-
childGrid.navigation.moveFocusToFilterCell();
457-
} else {
458-
// move to next cell
459-
this.navigateUp(currentRowEl, { row: rowIndex, column: lastIndex });
452+
const childGrid = this.getChildGrid(childGridID, this.grid) || this.getChildGrid(childGridID, this.grid.parent);
453+
const lastIndex = childGrid.unpinnedColumns[childGrid.unpinnedColumns.length - 1].visibleIndex;
454+
const summaryRows = childGrid.summariesRowList.toArray();
455+
if (summaryRows.length > 0 && summaryRows[0].summaryCells.length > 0) {
456+
// move focus to last summary row cell
457+
const summaryRow = summaryRows[0].nativeElement;
458+
this.focusPrevRow(summaryRow, lastIndex, childGrid, true, true);
459+
} else if (childGrid.rowList.toArray().length === 0 &&
460+
childGrid.allowFiltering && childGrid.filterMode === FilterMode.quickFilter) {
461+
// move to filter cell
462+
childGrid.navigation.moveFocusToFilterCell();
463+
} else if (childGrid.rowList.length === 0) {
464+
// move to prev child or parent row
465+
const prevChild = this.getSibling(childGrid);
466+
if (prevChild) {
467+
this.performShiftTabIntoChild(prevChild, currentRowEl, rowIndex);
468+
} else {
469+
const selNode = {
470+
row: rowIndex,
471+
column: this.grid.unpinnedColumns[this.grid.unpinnedColumns.length - 1].visibleIndex
472+
};
473+
this.navigateUp(currentRowEl, selNode);
474+
}
475+
} else {
476+
// move to prev cell
477+
childGrid.navigation.goToLastCell();
478+
}
479+
}
480+
481+
private getSibling(childGrid) {
482+
const prevChildRow = childGrid.childRow.nativeElement.previousElementSibling;
483+
if (prevChildRow) {
484+
return prevChildRow.children[0].children[0];
460485
}
486+
return null;
461487
}
462488

463489
private focusNextChild(elem, visibleColumnIndex, grid) {
@@ -711,7 +737,12 @@ export class IgxHierarchicalGridNavigationService extends IgxGridNavigationServi
711737
grid.parentVirtDir.onChunkLoad
712738
.pipe(first())
713739
.subscribe(callBackFunc);
714-
grid.dataRowList.toArray()[0].virtDirRow.scrollTo(unpinnedIndex);
740+
if (grid.dataRowList.length > 0) {
741+
grid.dataRowList.first.virtDirRow.scrollTo(unpinnedIndex);
742+
} else {
743+
grid.headerContainer.scrollTo(unpinnedIndex);
744+
}
745+
715746
}
716747
private scrollGrid(grid, target, callBackFunc) {
717748
this.getFocusableGrid().nativeElement.focus({preventScroll: true});

projects/igniteui-angular/src/lib/grids/tree-grid/tree-cell.component.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import { getNodeSizeViaRange } from '../../core/utils';
77
import { DOCUMENT } from '@angular/common';
88
import { IgxGridBaseComponent, IGridDataBindable } from '../grid';
99
import { IgxGridSelectionService, IgxGridCRUDService } from '../../core/grid-selection';
10+
import { HammerGesturesManager } from '../../core/touch';
1011

1112
@Component({
1213
changeDetection: ChangeDetectionStrategy.OnPush,
1314
selector: 'igx-tree-grid-cell',
14-
templateUrl: 'tree-cell.component.html'
15+
templateUrl: 'tree-cell.component.html',
16+
providers: [HammerGesturesManager]
1517
})
1618
export class IgxTreeGridCellComponent extends IgxGridCellComponent implements OnInit {
1719
private treeGridAPI: IgxTreeGridAPIService;
@@ -24,8 +26,9 @@ export class IgxTreeGridCellComponent extends IgxGridCellComponent implements On
2426
cdr: ChangeDetectorRef,
2527
element: ElementRef,
2628
protected zone: NgZone,
29+
touchManager: HammerGesturesManager,
2730
@Inject(DOCUMENT) public document) {
28-
super(selectionService, crudService, gridAPI, selection, cdr, element, zone);
31+
super(selectionService, crudService, gridAPI, selection, cdr, element, zone, touchManager);
2932
this.treeGridAPI = <IgxTreeGridAPIService>gridAPI;
3033
}
3134

src/app/virtual-for-directive/virtual-for.sample.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ export class VirtualForSampleComponent implements OnInit, AfterViewInit {
196196
if (this.itemSize === '50px') {
197197
this.itemSize = '100px';
198198
} else {
199-
this.itemSize = "50px";
199+
this.itemSize = '50px';
200200
}
201201

202202
}

0 commit comments

Comments
 (0)