diff --git a/src/mf-select.component.html b/src/mf-select.component.html
index 397743b..4c6bdf3 100644
--- a/src/mf-select.component.html
+++ b/src/mf-select.component.html
@@ -68,6 +68,7 @@
*ngFor='let item of viewPortItems;'
[class.mf-marked]='item === this.filteredItems[markedItem]'
[class.mf-category]='isMfCategory(item)'
+ [class.mf-disabled-option]='disableOptionsByKey && item[disableOptionsByKey]'
>
diff --git a/src/mf-select.component.scss b/src/mf-select.component.scss
index 44dde2b..cd103a1 100644
--- a/src/mf-select.component.scss
+++ b/src/mf-select.component.scss
@@ -195,10 +195,16 @@
color: white;
}
- &:hover:not(.mf-marked):not(.mf-category) {
+ &:hover:not(.mf-marked):not(.mf-category):not(.mf-disabled-option) {
background-color: hsla(0, 0%, 0%, 0.15);
}
+ &.mf-disabled-option {
+ cursor: not-allowed;
+ color: #aaa;
+ background-color:hsla(0, 0%, 0%, 0.075);
+ }
+
.mf-highlighted {
font-weight: bold;
text-decoration: underline;
diff --git a/src/mf-select.component.ts b/src/mf-select.component.ts
index 8eb6b06..d57f91b 100644
--- a/src/mf-select.component.ts
+++ b/src/mf-select.component.ts
@@ -71,6 +71,7 @@ export class MfSelectComponent implements OnInit, AfterViewInit, OnChanges, OnDe
@Input() public backgroundColor: string = 'white';
@Input() public floatingLabelColor: string = 'white';
@Input() public optionRowHeight: number = 28;
+ @Input() public disableOptionsByKey: string;
@Output() public update: EventEmitter = new EventEmitter();
@@ -126,6 +127,8 @@ export class MfSelectComponent implements OnInit, AfterViewInit, OnChanges, OnDe
public ngOnInit(): void {
this.filteredItems = this._items || [];
this.filteredItems = this.processCategories();
+
+ this.markedItem = this.findNextNonCategoryItem(0);
}
public ngAfterViewInit(): void {
@@ -156,9 +159,7 @@ export class MfSelectComponent implements OnInit, AfterViewInit, OnChanges, OnDe
// Update filteredItems
this.onSearch(this.searchTerm);
- if (this.isMfCategory(this.filteredItems[this.markedItem])) {
- this.markedItem += 1;
- }
+ this.markedItem = this.findNextNonCategoryItem(this.markedItem || 0);
if (!(this.changeDetectorRef).destroyed) {
this.changeDetectorRef.detectChanges();
@@ -170,9 +171,7 @@ export class MfSelectComponent implements OnInit, AfterViewInit, OnChanges, OnDe
// Update filteredItems
this.onSearch(this.searchTerm);
- if (this.isMfCategory(this.filteredItems[this.markedItem])) {
- this.markedItem += 1;
- }
+ this.markedItem = this.findNextNonCategoryItem(this.markedItem || 0);
}
}
}
@@ -225,20 +224,27 @@ export class MfSelectComponent implements OnInit, AfterViewInit, OnChanges, OnDe
switch ($event.code) {
case 'ArrowDown':
this.open();
- this.markedItem = this.markedItem < this.filteredItems.length - 1 ? this.markedItem + 1 : this.markedItem;
- this.virtualScrollComponent.scrollInto(this.filteredItems[this.markedItem]);
+ this.markedItem = this.findNextNonCategoryItem(this.markedItem !== undefined ? this.markedItem + 1 : 0);
+ if (this.markedItem !== undefined) {
+ this.virtualScrollComponent.scrollInto(this.filteredItems[this.markedItem]);
+ }
$event.preventDefault();
break;
case 'ArrowUp':
// Also skip over any categories when moving upward
- this.markedItem += this.isMfCategory(this.filteredItems[this.markedItem - 1]) ? -2 : -1;
- this.virtualScrollComponent.scrollInto(this.filteredItems[this.markedItem]);
+ this.markedItem = this.findPreviousNonCategoryItem(this.markedItem !== undefined ? this.markedItem - 1 : 0);
+ if (this.markedItem !== undefined) {
+ this.virtualScrollComponent.scrollInto(this.filteredItems[this.markedItem]);
+ }
$event.preventDefault();
break;
case 'Space':
// this._handleSpace($event);
break;
case 'Enter':
+ if (this.markedItem === undefined) {
+ return;
+ }
const item = this.filteredItems[this.markedItem];
if (!item) {
return;
@@ -297,15 +303,11 @@ export class MfSelectComponent implements OnInit, AfterViewInit, OnChanges, OnDe
this.filteredItems = this.processCategories();
- // If the marker would be outside the bounds, reset it.
- if (this.markedItem >= this.filteredItems.length) {
- this.markedItem = 0;
- }
-
+ this.markedItem = this.findNextNonCategoryItem(0);
}
public selectItem(item: MfSelectItem): void {
- if (this.isDisabled || this.isMfCategory(item)) { return; }
+ if (this.isDisabled || this.isMfCategory(item) || this.isDisabledItem(item)) { return; }
this.model = item;
this.markedItem = this.filteredItems.indexOf(this.model);
this.onChange(this.model);
@@ -391,7 +393,6 @@ export class MfSelectComponent implements OnInit, AfterViewInit, OnChanges, OnDe
const offsetTop = selectRect.top - parentRect.top;
const offsetLeft = selectRect.left - parentRect.left;
const topDelta = this.currentDropdownPosition === 'top' ? -(dropdownPanel.getBoundingClientRect().height + 6) : selectRect.height;
- // console.log(parentRect, selectRect, offsetTop, offsetLeft, topDelta);
dropdownPanel.style.top = offsetTop + topDelta + 'px';
dropdownPanel.style.bottom = 'auto';
dropdownPanel.style.left = offsetLeft + 'px';
@@ -428,19 +429,38 @@ export class MfSelectComponent implements OnInit, AfterViewInit, OnChanges, OnDe
return item && ( item).categoryName !== undefined;
}
- private findNextNonCategoryItem(pos: number): number {
- pos = pos >= 0 ? pos : 0;
+ private isDisabledItem(item: MfSelectItem): boolean {
+ return item && typeof(item) === 'object' && this.disableOptionsByKey && item[this.disableOptionsByKey];
+ }
- while (this.isMfCategory(this.filteredItems[pos])) {
- pos += 1;
+ private findPreviousNonCategoryItem(pos: number): number | undefined {
+ // Make sure the position is between 0 and the length of the list
+ pos = Math.max(0, Math.min(this.filteredItems.length - 1, pos));
- // Off the edge of the map, here be.. Nevermind lets just turn around.
- // Should be non-reachable
- if (pos > this.filteredItems.length) {
- return 0;
- }
+ const offset = this.filteredItems.slice(0, pos + 1)
+ .reverse()
+ .findIndex((item: MfSelectItem) => !this.isMfCategory(item) && !this.isDisabledItem(item));
+
+ // We found what we need
+ if (offset !== -1) {
+ return pos - offset;
+ }
+
+ return this.markedItem;
+ }
+
+ private findNextNonCategoryItem(pos: number): number | undefined {
+ // Make sure the position is between 0 and the length of the list
+ pos = Math.max(0, Math.min(this.filteredItems.length - 1, pos));
+
+ const offset = this.filteredItems.slice(pos)
+ .findIndex((item: MfSelectItem) => !this.isMfCategory(item) && !this.isDisabledItem(item));
+
+ // We found what we need
+ if (offset !== -1) {
+ return pos + offset;
}
- return pos;
+ return this.markedItem;
}
}