UNPKG

carbon-components-angular

Version:
362 lines (359 loc) 13.7 kB
/*! * * Neutrino v0.0.0 | dropdown-list.component.js * * Copyright 2014, 2018 IBM * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Component, Input, Output, EventEmitter, ViewChild, ElementRef } from "@angular/core"; import { AbstractDropdownView } from "./../abstract-dropdown-view.class"; import { watchFocusJump } from "./../dropdowntools"; /** * ```html * <ibm-dropdown-list [items]="listItems"></ibm-dropdown-list> * ``` * ```typescript * listItems = [ * { * content: "item one", * selected: false * }, * { * content: "item two", * selected: false, * }, * { * content: "item three", * selected: false * }, * { * content: "item four", * selected: false * } * ]; * ``` */ var DropdownList = /** @class */ (function () { /** * Creates an instance of `DropdownList`. */ function DropdownList(elementRef) { this.elementRef = elementRef; /** * The list items belonging to the `DropdownList`. */ this.items = []; /** * Template to bind to items in the `DropdownList` (optional). */ this.listTpl = null; /** * Event to emit selection of a list item within the `DropdownList`. */ this.select = new EventEmitter(); /** * Defines whether or not the `DropdownList` supports selecting multiple items as opposed to single * item selection. */ this.type = "single"; /** * Defines the rendering size of the `DropdownList` input component. */ this.size = "md"; /** * Holds the list of items that will be displayed in the `DropdownList`. * It differs from the the complete set of items when filtering is used (but * it is always a subset of the total items in `DropdownList`). */ this.displayItems = []; /** * Maintains the index for the selected item within the `DropdownList`. */ this.index = -1; } /** * Updates list when changes occur within the items belonging to the `DropdownList`. */ DropdownList.prototype.ngOnChanges = function (changes) { if (changes.items) { this.updateList(changes.items.currentValue); } }; /** * Retrieves array of list items and index of the selected item after view has rendered. * Additionally, any Observables for the `DropdownList` are initialized. */ DropdownList.prototype.ngAfterViewInit = function () { this.listElementList = Array.from(this.list.nativeElement.querySelectorAll("li")); this.index = this.items.findIndex(function (item) { return item.selected; }); this.setupFocusObservable(); }; /** * Removes any Observables on destruction of the component. */ DropdownList.prototype.ngOnDestroy = function () { if (this.focusJump) { this.focusJump.unsubscribe(); } }; /** * Updates the displayed list of items and then retrieves the most current properties for the `DropdownList` from the DOM. */ DropdownList.prototype.updateList = function (items) { var _this = this; this.items = items.map(function (item) { return Object.assign({}, item); }); this.displayItems = this.items; setTimeout(function () { _this.listElementList = Array.from(_this.list.nativeElement.querySelectorAll("li")); }, 0); this.index = this.items.findIndex(function (item) { return item.selected; }); this.setupFocusObservable(); setTimeout(function () { if (_this.type === "single") { _this.select.emit({ item: _this.items.find(function (item) { return item.selected; }) }); } else { _this.select.emit(_this.getSelected() || []); } }); }; /** * Filters the items being displayed in the DOM list. */ DropdownList.prototype.filterBy = function (query) { if (query === void 0) { query = ""; } if (query) { this.displayItems = this.items.filter(function (item) { return item.content.toLowerCase().includes(query.toLowerCase()); }); } else { this.displayItems = this.items; } }; /** * Initializes (or re-initializes) the Observable that handles switching focus to an element based on * key input matching the first letter of the item in the list. */ DropdownList.prototype.setupFocusObservable = function () { if (this.focusJump) { this.focusJump.unsubscribe(); } var elList = Array.from(this.list.nativeElement.querySelectorAll("li")); this.focusJump = watchFocusJump(this.list.nativeElement, elList) .subscribe(function (el) { el.focus(); }); }; /** * Returns the `ListItem` that is subsequent to the selected item in the `DropdownList`. */ DropdownList.prototype.getNextItem = function () { if (this.index < this.items.length - 1) { this.index++; } return this.items[this.index]; }; /** * Returns `true` if the selected item is not the last item in the `DropdownList`. */ DropdownList.prototype.hasNextElement = function () { if (this.index < this.items.length - 1) { return true; } return false; }; /** * Returns the `HTMLElement` for the item that is subsequent to the selected item. */ DropdownList.prototype.getNextElement = function () { if (this.index < this.items.length - 1) { this.index++; } var elem = this.listElementList[this.index]; var item = this.items[this.index]; if (item.disabled) { return this.getNextElement(); } return elem; }; /** * Returns the `ListItem` that precedes the selected item within `DropdownList`. */ DropdownList.prototype.getPrevItem = function () { if (this.index > 0) { this.index--; } return this.items[this.index]; }; /** * Returns `true` if the selected item is not the first in the list. */ DropdownList.prototype.hasPrevElement = function () { if (this.index > 0) { return true; } return false; }; /** * Returns the `HTMLElement` for the item that precedes the selected item. */ DropdownList.prototype.getPrevElement = function () { if (this.index > 0) { this.index--; } var elem = this.listElementList[this.index]; var item = this.items[this.index]; if (item.disabled) { return this.getPrevElement(); } return elem; }; /** * Returns the `ListItem` that is selected within `DropdownList`. */ DropdownList.prototype.getCurrentItem = function () { if (this.index < 0) { return this.items[0]; } return this.items[this.index]; }; /** * Returns the `HTMLElement` for the item that is selected within the `DropdownList`. */ DropdownList.prototype.getCurrentElement = function () { if (this.index < 0) { return this.listElementList[0]; } return this.listElementList[this.index]; }; /** * Returns a list containing the selected item(s) in the `DropdownList`. */ DropdownList.prototype.getSelected = function () { var selected = this.items.filter(function (item) { return item.selected; }); if (selected.length === 0) { return null; } return selected; }; /** * Transforms array input list of items to the correct state by updating the selected item(s). */ DropdownList.prototype.propagateSelected = function (value) { for (var _i = 0, value_1 = value; _i < value_1.length; _i++) { var newItem = value_1[_i]; // copy the item var tempNewItem = Object.assign({}, newItem); // deleted selected because it's what we _want_ to change delete tempNewItem.selected; // stringify for compare tempNewItem = JSON.stringify(tempNewItem); for (var _a = 0, _b = this.items; _a < _b.length; _a++) { var oldItem = _b[_a]; var tempOldItem = Object.assign({}, oldItem); delete tempOldItem.selected; tempOldItem = JSON.stringify(tempOldItem); // do the compare if (tempOldItem.includes(tempNewItem)) { // oldItem = Object.assign(oldItem, newItem); oldItem.selected = newItem.selected; } else { oldItem.selected = false; } } } }; /** * Initalizes focus in the list, effectivly a wrapper for `getCurrentElement().focus()` */ DropdownList.prototype.initFocus = function () { this.getCurrentElement().focus(); }; /** * Manages the keyboard accessiblity for navigation and selection within a `DropdownList`. */ DropdownList.prototype.doKeyDown = function (event, item) { if (event.key && (event.key === "Enter" || event.key === " ")) { event.preventDefault(); this.doClick(event, item); } else if (event.key === "ArrowDown" || event.key === "ArrowUp") { event.preventDefault(); // this.checkScrollArrows(); if (event.key === "ArrowDown" && this.hasNextElement()) { this.getNextElement().focus(); } else if (event.key === "ArrowUp") { if (this.hasPrevElement()) { this.getPrevElement().focus(); } else if (this.getSelected()) { this.clearSelected.nativeElement.focus(); } } if (event.shiftKey) { event.target.click(); } } }; /** * Emits the selected item or items after a mouse click event has occurred. */ DropdownList.prototype.doClick = function (event, item) { if (!item.disabled) { item.selected = !item.selected; if (this.type === "single") { // reset the selection for (var _i = 0, _a = this.items; _i < _a.length; _i++) { var otherItem = _a[_i]; if (item !== otherItem) { otherItem.selected = false; } } this.select.emit({ item: item }); } else { // emit an array of selected items this.select.emit(this.getSelected()); } this.index = this.items.indexOf(item); } }; DropdownList.decorators = [ { type: Component, args: [{ selector: "ibm-dropdown-list", template: "\n\t\t<ul\n\t\t\t#list\n\t\t\trole=\"listbox\"\n\t\t\tclass=\"bx--list-box__menu\">\n\t\t\t<li tabindex=\"{{item.disabled? -1 : 0}}\"\n\t\t\t\trole=\"option\"\n\t\t\t\t*ngFor=\"let item of displayItems\"\n\t\t\t\t(click)=\"doClick($event, item)\"\n\t\t\t\t(keydown)=\"doKeyDown($event, item)\"\n\t\t\t\tclass=\"bx--list-box__menu-item\"\n\t\t\t\t[ngClass]=\"{\n\t\t\t\t\tselected: item.selected,\n\t\t\t\t\tdisabled: item.disabled\n\t\t\t\t}\">\n\t\t\t\t<div\n\t\t\t\t\t*ngIf=\"!listTpl && type === 'multi'\"\n\t\t\t\t\tclass=\"bx--form-item bx--checkbox-wrapper\">\n\t\t\t\t\t<input\n\t\t\t\t\t\tclass=\"bx--checkbox\"\n\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t[checked]=\"item.selected\"\n\t\t\t\t\t\t[disabled]=\"item.disabled\"\n\t\t\t\t\t\t(click)=\"doClick($event, item)\"\n\t\t\t\t\t\ttabindex=\"-1\">\n\t\t\t\t\t<label class=\"bx--checkbox-label\">{{item.content}}</label>\n\t\t\t\t</div>\n\t\t\t\t<ng-container *ngIf=\"!listTpl && type === 'single'\">{{item.content}}</ng-container>\n\t\t\t\t<ng-template\n\t\t\t\t\t*ngIf=\"listTpl\"\n\t\t\t\t\t[ngTemplateOutletContext]=\"{item: item}\"\n\t\t\t\t\t[ngTemplateOutlet]=\"listTpl\">\n\t\t\t\t</ng-template>\n\t\t\t</li>\n\t\t</ul>", providers: [ { provide: AbstractDropdownView, useExisting: DropdownList } ] },] }, ]; /** @nocollapse */ DropdownList.ctorParameters = function () { return [ { type: ElementRef } ]; }; DropdownList.propDecorators = { items: [{ type: Input }], listTpl: [{ type: Input }], select: [{ type: Output }], list: [{ type: ViewChild, args: ["list",] }], clearSelected: [{ type: ViewChild, args: ["clearSelected",] }], type: [{ type: Input }] }; return DropdownList; }()); export { DropdownList }; //# sourceMappingURL=dropdown-list.component.js.map