Skip to content

Commit

Permalink
feat(tree-selection): added handlers for HOME, END, PAGE_UP, PAGE_DOW…
Browse files Browse the repository at this point in the history
…N and no-unselect
  • Loading branch information
lkramarov committed Aug 15, 2018
1 parent 3dd2aa5 commit 9647104
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 31 deletions.
4 changes: 2 additions & 2 deletions src/cdk/a11y/key-manager/list-key-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ export class ListKeyManager<T extends IListKeyManagerOption> {
if (nextItemIndex >= this._items.length) {
this.setLastItemActive();
} else {
this._setActiveItemByDelta(1);
this._setActiveItemByDelta(delta);
}
}

Expand All @@ -288,7 +288,7 @@ export class ListKeyManager<T extends IListKeyManagerOption> {
if (nextItemIndex <= 0) {
this.setFirstItemActive();
} else {
this._setActiveItemByDelta(-1);
this._setActiveItemByDelta(-delta);
}
}

Expand Down
10 changes: 9 additions & 1 deletion src/lib-dev/tree/template.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
<style>
mc-tree-selection {
overflow-y: scroll;
height: 164px;
}
</style>
<h5>multiple selection</h5>

<!--auto-select="true"-->
<mc-tree-selection
auto-select="false"
multiple
no-unselect="false"
[dataSource]="dataSource"
[treeControl]="treeControl"
(navigationChange)="onNavigationChange($event)"
Expand Down
6 changes: 3 additions & 3 deletions src/lib/list/list-selection.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ export class McListSelection extends _McListSelectionMixinBase implements
} else if (this.withCtrl) {
this.withCtrl = false;

if (!this._canUnselectLast(option)) { return; }
if (!this._canDeselectLast(option)) { return; }

option.toggle();
} else {
Expand Down Expand Up @@ -414,7 +414,7 @@ export class McListSelection extends _McListSelectionMixinBase implements
if (focusedIndex != null && this._isValidIndex(focusedIndex)) {
const focusedOption: McListOption = this.options.toArray()[focusedIndex];

if (focusedOption && this._canUnselectLast(focusedOption)) {
if (focusedOption && this._canDeselectLast(focusedOption)) {
focusedOption.toggle();

// Emit a change event because the focused option changed its state through user interaction.
Expand All @@ -423,7 +423,7 @@ export class McListSelection extends _McListSelectionMixinBase implements
}
}

_canUnselectLast(listOption: McListOption): boolean {
_canDeselectLast(listOption: McListOption): boolean {
return !(this.noUnselect && this.selectedOptions.selected.length === 1 && listOption.selected);
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/tree/_tree-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
}

@mixin mc-tree-typography($config) {
.mc-tree {
.mc-tree-selection {
font-family: mc-font-family($config);
}

Expand Down
3 changes: 1 addition & 2 deletions src/lib/tree/padding.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { AfterContentInit, Directive, Input, OnInit, ViewChild } from '@angular/core';
import { Directive, Input, OnInit } from '@angular/core';
import { CdkTreeNodePadding } from '@ptsecurity/cdk/tree';
import { McIcon } from '@ptsecurity/mosaic/icon';


@Directive({
Expand Down
2 changes: 1 addition & 1 deletion src/lib/tree/public-api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export * from './tree.module';
export * from './node';
export * from './padding';
export * from './tree';
export * from './tree-selection';
export * from './data-source/flat-data-source';
export * from './data-source/nested-data-source';
81 changes: 64 additions & 17 deletions src/lib/tree/tree.ts → src/lib/tree/tree-selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ export class McTreeNodeOption<T> extends CdkTreeNode<T> implements CanDisable {
// this._changeDetector.markForCheck();
}

_getHeight(): number {
return this._elementRef.nativeElement.getClientRects()[0].height;
}

_handleFocus(): void {
if (this.disabled || this._hasFocus) { return; }

Expand Down Expand Up @@ -151,9 +155,10 @@ export class McTreeSelectionChange {
template: `<ng-container cdkTreeNodeOutlet></ng-container>`,
host: {
'[tabIndex]': 'tabIndex',
class: 'mc-tree',
class: 'mc-tree-selection',
role: 'tree-selection',
'(keydown)': '_onKeyDown($event)'
'(keydown)': '_onKeyDown($event)',
'(window:resize)': 'updateScrollSize()'
},
styleUrls: ['./tree.css'],
encapsulation: ViewEncapsulation.None,
Expand All @@ -175,6 +180,11 @@ export class McTreeSelection<T> extends _McTreeSelectionBase<T>
tabIndex: number;
multiple: boolean;
autoSelect: boolean;
noUnselect: boolean;

// todo temporary solution
withShift: boolean;
withCtrl: boolean;

@Input()
get disabled(): boolean {
Expand All @@ -200,24 +210,29 @@ export class McTreeSelection<T> extends _McTreeSelectionBase<T>
@Output() readonly selectionChange = new EventEmitter<McTreeSelectionChange>();

constructor(
private _elementRef: ElementRef,
_differs: IterableDiffers,
_changeDetectorRef: ChangeDetectorRef,
@Attribute('tabindex') tabIndex: string,
@Attribute('multiple') multiple: string,
@Attribute('auto-select') autoSelect: string
@Attribute('auto-select') autoSelect: string,
@Attribute('no-unselect') noUnselect: string
) {
super(_differs, _changeDetectorRef);

this.tabIndex = parseInt(tabIndex) || 0;

this.multiple = multiple === null ? true : toBoolean(multiple);
this.autoSelect = autoSelect === null ? true : toBoolean(autoSelect);
this.noUnselect = noUnselect === null ? true : toBoolean(noUnselect);

this.selectedOptions = new SelectionModel<McTreeNodeOption<T>>(this.multiple);
}

_onKeyDown(event: KeyboardEvent) {
const keyCode = event.keyCode;
this.withShift = event.shiftKey;
this.withCtrl = event.ctrlKey;

switch (keyCode) {
case LEFT_ARROW:
Expand All @@ -232,35 +247,33 @@ export class McTreeSelection<T> extends _McTreeSelectionBase<T>
if (this._keyManager.activeItem) {
this.treeControl.expand(this._keyManager.activeItem.data);
}

event.preventDefault();

break;
case SPACE:
case ENTER:
this.toggleFocusedOption();

event.preventDefault();

break;
case HOME:
console.log('need set focus on first node');
this._keyManager.setFirstItemActive();
event.preventDefault();

break;
case END:
console.log('need set focus on last node');
this._keyManager.setLastItemActive();
event.preventDefault();

break;
case PAGE_UP:
console.log('need do scroll page and set focus on first in viewport');

this._keyManager.setPreviousPageItemActive();
event.preventDefault();

break;
case PAGE_DOWN:
console.log('need do scroll page and set focus on last in viewport');

this._keyManager.setNextPageItemActive();
event.preventDefault();

break;
Expand All @@ -276,12 +289,41 @@ export class McTreeSelection<T> extends _McTreeSelectionBase<T>
.withHorizontalOrientation(null);
}

updateScrollSize(): void {
if (!this.options.first) { return; }

this._keyManager.withScrollSize(Math.floor(this._getHeight() / this.options.first._getHeight()));
}

setFocusedOption(option: McTreeNodeOption<T>): void {
this._keyManager.updateActiveItem(option);

if (this.autoSelect) {
this.options.forEach((item) => item.setSelected(false));
option.setSelected(true);
if (this.withShift && this.multiple) {
const previousIndex = this._keyManager.previousActiveItemIndex;
const activeIndex = this._keyManager.activeItemIndex;

if (previousIndex < activeIndex) {
this.options.forEach((item, index) => {
if (index >= previousIndex && index <= activeIndex) { item.setSelected(true); }
});
} else {
this.options.forEach((item, index) => {
if (index >= activeIndex && index <= previousIndex) { item.setSelected(true); }
});
}

this.withShift = false;
} else if (this.withCtrl) {
this.withCtrl = false;

if (!this._canDeselectLast(option)) { return; }

option.toggle();
} else {
if (this.autoSelect) {
this.options.forEach((item) => item.setSelected(false));
option.setSelected(true);
}
}

this._emitNavigationEvent(option);
Expand All @@ -294,7 +336,7 @@ export class McTreeSelection<T> extends _McTreeSelectionBase<T>
if (focusedIndex != null && this._isValidIndex(focusedIndex)) {
const focusedOption: McTreeNodeOption<T> = this.options.toArray()[focusedIndex];

if (focusedOption && this._canUnselectLast(focusedOption)) {
if (focusedOption && this._canDeselectLast(focusedOption)) {
focusedOption.toggle();

// Emit a change event because the focused option changed its state through user interaction.
Expand Down Expand Up @@ -329,6 +371,12 @@ export class McTreeSelection<T> extends _McTreeSelectionBase<T>
this.options.reset(arrayOfInstances);
this.options.notifyOnChanges();
}

this.updateScrollSize();
}

_getHeight(): number {
return this._elementRef.nativeElement.getClientRects()[0].height;
}

_emitNavigationEvent(option: McTreeNodeOption<T>): void {
Expand All @@ -348,9 +396,8 @@ export class McTreeSelection<T> extends _McTreeSelectionBase<T>
return index >= 0 && index < this.options.length;
}

private _canUnselectLast(_option: McTreeNodeOption<T>): boolean {
return true;
// return !(this.noUnselect && this.selectedOptions.selected.length === 1 && listOption.selected);
private _canDeselectLast(option: McTreeNodeOption<T>): boolean {
return !(this.noUnselect && this.selectedOptions.selected.length === 1 && option.selected);
}
}

2 changes: 1 addition & 1 deletion src/lib/tree/tree.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { CdkTreeModule } from '@ptsecurity/cdk/tree';

import { McTreeNodeDef } from './node';
import { McTreeNodePadding } from './padding';
import { McTreeSelection, McTreeNodeOption } from './tree';
import { McTreeSelection, McTreeNodeOption } from './tree-selection';


const MC_TREE_DIRECTIVES = [
Expand Down
4 changes: 1 addition & 3 deletions src/lib/tree/tree.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ $mc-tree-node-height: 28px;
$mc-tree-node-padding: 16px;


.mc-tree {
.mc-tree-selection {
display: block;

border: 1px solid red;
Expand All @@ -34,9 +34,7 @@ $mc-tree-node-padding: 16px;
&:focus {
outline: none;
}
}

.mc-tree-node {
&:not([disabled]) {
cursor: pointer;
}
Expand Down

0 comments on commit 9647104

Please sign in to comment.