UNPKG

angular-dropdown-component

Version:

Even though a dropdown (select-option) is a pretty common utility but it still doesn't support basics such as search.

238 lines (233 loc) 16.8 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@angular/forms')) : typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/common', '@angular/forms'], factory) : (factory((global['angular-dropdown-component'] = {}),global.ng.core,global.ng.common,global.ng.forms)); }(this, (function (exports,core,common,forms) { 'use strict'; var DropdownComponent = /** @class */ (function () { function DropdownComponent() { this.selectedOptionChange = new core.EventEmitter(); this.ifContainerFocused = false; } DropdownComponent.prototype.ngAfterViewInit = function () { var _this = this; this.mutationObserverDOM = new MutationObserver(function (mutations) { _this.setContainerDimensions(); }); this.mutationObserverDOM.observe(this.dropdownMenu.nativeElement, { childList: true }); this.mutationObserverDOM.observe(this.dropdownMenu.nativeElement.children[1], { childList: true }); if (this.filter) this.mutationObserverDOM.observe(this.dropdownMenu.nativeElement.children[1].children[1], { childList: true }); else this.mutationObserverDOM.observe(this.dropdownMenu.nativeElement.children[1].children[0], { childList: true }); }; DropdownComponent.prototype.ngOnChanges = function (simpleChanges) { var _this = this; if (simpleChanges.hasOwnProperty("data")) { this._data = this.data; } if (this.data && !this.selectedOption) this.setDefaultOption(); else if (this.data && this.selectedOption) { if (this.selectedOption.hasOwnProperty("id")) { this.data.forEach(function (obj) { if (obj.id == _this.selectedOption["id"]) _this._selectedOption = obj; }); } else if (this.selectedOption.hasOwnProperty("name")) { this.data.forEach(function (obj) { if (obj.name == _this.selectedOption["name"]) _this._selectedOption = obj; }); } else if (this.editable) { this._selectedOption = this.selectedOption; return; } if (!this._selectedOption) this.setDefaultOption(); } }; DropdownComponent.prototype.setDefaultOption = function () { if (this.editable) this._selectedOption = ""; else this._selectedOption = this.data[0]; }; DropdownComponent.prototype.setContainerDimensions = function () { var defaultDropdownHeight = this.dropdownMenu.nativeElement.children[0].offsetHeight; var actualList; if (this.filter) { defaultDropdownHeight += this.dropdownMenu.nativeElement.children[1].children[0].offsetHeight; actualList = this.dropdownMenu.nativeElement.children[1].children[1].children; } else actualList = this.dropdownMenu.nativeElement.children[1].children[0].children; defaultDropdownHeight += Array.from(actualList).reduce(function (accumulator, currentValue) { return accumulator + currentValue["offsetHeight"]; }, 0); var dropdownButtonElement = this.dropdownButton.nativeElement; var dropdownButtonRect = dropdownButtonElement.getBoundingClientRect(); var dropdownFilterHeight = this.filter ? this.dropdownFilter.nativeElement.offsetHeight : 0; var distanceFromTop = dropdownButtonRect.top; var distanceFromLeft = dropdownButtonRect.left; var distanceFromBottom = window.innerHeight - distanceFromTop - dropdownButtonElement.offsetHeight; var distanceFromRight = window.innerWidth - distanceFromLeft - dropdownButtonElement.offsetWidth; this.selectedItemFocusedStyles = { "width": dropdownButtonElement.offsetWidth - 2 + "px", "height": dropdownButtonElement.offsetHeight - 2 + "px" }; this.restOfListWithoutFilterFocusedStyles = { "margin-top": dropdownFilterHeight + "px" }; if (distanceFromBottom > defaultDropdownHeight) { this.containerFocusedStyles = { "top": distanceFromTop + "px", "left": distanceFromLeft + "px", "width": dropdownButtonElement.offsetWidth + 'px', "flex-direction": "column" }; this.restOfListFocusedStyles = { "margin-top": dropdownButtonElement.offsetHeight + "px" }; } else if (distanceFromTop > defaultDropdownHeight) { this.containerFocusedStyles = { "bottom": distanceFromBottom + "px", "left": distanceFromLeft + "px", "width": dropdownButtonElement.offsetWidth + 'px', "flex-direction": "column-reverse" }; this.restOfListFocusedStyles = { "margin-bottom": dropdownButtonElement.offsetHeight + "px" }; this.selectedItemFocusedStyles = Object.assign({}, this.selectedItemFocusedStyles, { "border-top": "1px solid #e0e0e0" }); } else { if (distanceFromBottom > distanceFromTop) { this.containerFocusedStyles = { "top": distanceFromTop + "px", "bottom": "20px", "left": distanceFromLeft + "px", "width": dropdownButtonElement.offsetWidth + 'px', "flex-direction": "column" }; this.restOfListFocusedStyles = { "margin-top": dropdownButtonElement.offsetHeight + "px" }; } else { this.containerFocusedStyles = { "top": "20px", "bottom": distanceFromBottom + "px", "left": distanceFromLeft + "px", "width": dropdownButtonElement.offsetWidth + 'px', "flex-direction": "column-reverse" }; this.restOfListFocusedStyles = { "margin-bottom": dropdownButtonElement.offsetHeight + "px" }; this.selectedItemFocusedStyles = Object.assign({}, this.selectedItemFocusedStyles, { "border-top": "1px solid #e0e0e0" }); } } }; DropdownComponent.prototype.onFilterSearch = function ($event) { this.setSearchedItems($event.target.value); }; DropdownComponent.prototype.setSearchedItems = function (value) { this._data = this.data.filter(function (element) { return element.name .toLowerCase() .indexOf(value.toLowerCase()) !== -1; }); }; DropdownComponent.prototype.onInputFocus = function ($event) { this.dropdownInput.nativeElement.focus(); this.ifContainerFocused = false; }; DropdownComponent.prototype.onInputChange = function ($event) { this._selectedOption = $event.target.value; this.selectedOptionChange.emit(this._selectedOption); }; DropdownComponent.prototype.onDropdownItemSelect = function ($event, option) { this._selectedOption = option; this.selectedOptionChange.emit(option); this.hideDropdown(); }; DropdownComponent.prototype.onDropdownMenuClick = function ($event) { this.clearSearchFilter(); this.setContainerDimensions(); if ($event.target instanceof HTMLInputElement) return; else this.showDropdown(); }; DropdownComponent.prototype.onDropdownBlur = function ($event) { if (this.dropdownFilter && $event.relatedTarget == this.dropdownFilter.nativeElement && $event.relatedTarget instanceof HTMLInputElement) return; this.ifContainerFocused = false; this.hideDropdown(); }; DropdownComponent.prototype.clearSearchFilter = function () { if (!this.dropdownFilter) return; this.dropdownFilter.nativeElement.value = ""; this.setSearchedItems(""); }; DropdownComponent.prototype.showDropdown = function () { this.dropdownMenu.nativeElement.focus(); }; DropdownComponent.prototype.hideDropdown = function () { this.dropdownMenu.nativeElement.blur(); }; DropdownComponent.prototype.ngOnDestroy = function () { this.mutationObserverDOM.disconnect(); }; return DropdownComponent; }()); DropdownComponent.decorators = [ { type: core.Component, args: [{ selector: "ng-dropdown", template: "<ng-container>\n <div class=\"ng-dropdown\">\n <span *ngIf=\"dTitle\" [innerText]=\"dTitle\" class=\"ng-dropdown__title\"></span>\n <ul class=\"ng-dropdown__container\" tabindex=\"0\" (focus)=\"ifContainerFocused=true\" (blur)=\"onDropdownBlur($event)\" [ngStyle]=\"ifContainerFocused ? containerFocusedStyles: {}\"\n #dropdownMenu>\n <li [ngStyle]=\"ifContainerFocused ? selectedItemFocusedStyles: {}\">\n <a (click)=\"hideDropdown()\">\n <span *ngIf=\"!editable; else ifEditableList\" (focus)=\"onInputFocus($event)\" [innerText]=\"_selectedOption?.name\"></span>\n <ng-template #ifEditableList>\n <input class=\"ng-dropdown__container--editable\" [ngModel]=\"_selectedOption | GetSelectedNamePipe\" (focus)=\"onInputFocus($event)\"/>\n </ng-template>\n <img src=\"assets/downPopup.png\" />\n </a>\n </li>\n <ul class=\"ng-dropdown__container--list\" [ngStyle]=\"ifContainerFocused ? restOfListFocusedStyles: {}\">\n <li *ngIf=\"filter\" [ngStyle]=\"ifContainerFocused ? selectedItemFocusedStyles: {}\">\n <input #dropdownFilter class=\"ng-dropdown__container--list__filter\" placeholder=\"Search\" (keyup)=\"onFilterSearch($event)\" (blur)=\"onDropdownBlur($event)\" />\n </li>\n <ul class=\"ng-dropdown__container--list__sublist\" [ngStyle]=\"ifContainerFocused ? restOfListWithoutFilterFocusedStyles: {}\">\n <ng-container *ngIf=\"_data?.length else noResults\">\n <li *ngFor=\"let option of _data\" [ngClass]=\"_selectedOption?.name == option.name ? 'active' : ''\">\n <a [innerText]=\"option.name\" (click)=\"onDropdownItemSelect($event, option)\"></a>\n </li>\n </ng-container>\n <ng-template #noResults>\n <li>\n <a>No Results Found</a>\n </li>\n </ng-template>\n </ul>\n </ul>\n </ul>\n <div class=\"ng-dropdown__button\" [ngClass]=\"disabled ? 'disabled' : ''\" (mouseup)=\"onDropdownMenuClick($event)\" #dropdownButton>\n <span *ngIf=\"!editable; else ifEditable\" [innerText]=\"_selectedOption?.name\"></span>\n <ng-template #ifEditable>\n <input #dropdownInput (keyup)=\"onInputChange($event)\" [ngModel]=\"_selectedOption | GetSelectedNamePipe\" />\n </ng-template>\n <img src=\"assets/downPopup.png\" />\n </div>\n </div>\n</ng-container>\n", styles: [".ng-dropdown{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;position:relative;padding-bottom:10px}.ng-dropdown .ng-dropdown__title{padding-bottom:5px}.ng-dropdown .ng-dropdown__button{background:#fff;border:1px solid #c9c9c9;padding:2px 10px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;height:18px}.ng-dropdown .ng-dropdown__button span,.ng-dropdown__container>li a span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ng-dropdown .ng-dropdown__button img{height:10px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ng-dropdown .ng-dropdown__button input,.ng-dropdown .ng-dropdown__container li input.ng-dropdown__container--editable{width:100%;height:100%;border:none;outline:0;overflow:hidden;text-overflow:ellipsis}.ng-dropdown .ng-dropdown__button.disabled{pointer-events:none;opacity:.7}.ng-dropdown .ng-dropdown__container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;background:#fff;list-style-type:none;border:1px solid #c9c9c9;position:fixed;left:-10000px;outline:0;-webkit-box-sizing:border-box;box-sizing:border-box;z-index:100000;padding:0;margin:0;-webkit-box-shadow:0 3px 6px rgba(0,0,0,.16),0 3px 6px rgba(0,0,0,.23);box-shadow:0 3px 6px rgba(0,0,0,.16),0 3px 6px rgba(0,0,0,.23)}.ng-dropdown .ng-dropdown__container:focus{left:0}.ng-dropdown .ng-dropdown__container:focus+.ng-dropdown__button{pointer-events:none}.ng-dropdown .ng-dropdown__container li:hover{background-color:#e0e0e0;color:#000}.ng-dropdown .ng-dropdown__container>li:first-child a{height:100%}.ng-dropdown .ng-dropdown__container>li:first-child,.ng-dropdown__container--list>li:first-child{position:fixed;background-color:#fff}.ng-dropdown .ng-dropdown__container>li:first-child a,.ng-dropdown__container--list>li:first-child a{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.ng-dropdown .ng-dropdown__container>li:first-child a img,.ng-dropdown__container--list>li:first-child a img{height:10px}.ng-dropdown .ng-dropdown__container>li:first-child:hover,.ng-dropdown__container--list>li:first-child:hover{color:initial}.ng-dropdown .ng-dropdown__container li a,.ng-dropdown__container--list>li:first-child li a{padding:0 10px;height:22px;line-height:22px;cursor:pointer;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;display:block;text-align:left}.ng-dropdown .ng-dropdown__container li input.ng-dropdown__container--list__filter{width:100%;padding:0 9px;height:22px;outline:0;-webkit-box-sizing:border-box;box-sizing:border-box;border:none;border-bottom:1px solid #e0e0e0;border-top:1px solid #e0e0e0}.ng-dropdown .ng-dropdown__container ul{list-style-type:none;padding:0;margin:0;overflow:auto}.ng-dropdown__container--list__sublist li:first-child{position:initial}.ng-dropdown__container--list__sublist li.active{background-color:#6fbbff;color:#fff}"] },] }, ]; DropdownComponent.ctorParameters = function () { return []; }; DropdownComponent.propDecorators = { "data": [{ type: core.Input },], "disabled": [{ type: core.Input },], "dTitle": [{ type: core.Input },], "selectedOption": [{ type: core.Input },], "filter": [{ type: core.Input },], "editable": [{ type: core.Input },], "selectedOptionChange": [{ type: core.Output },], "dropdownMenu": [{ type: core.ViewChild, args: ["dropdownMenu",] },], "dropdownButton": [{ type: core.ViewChild, args: ["dropdownButton",] },], "dropdownInput": [{ type: core.ViewChild, args: ["dropdownInput",] },], "dropdownFilter": [{ type: core.ViewChild, args: ["dropdownFilter",] },], }; var GetSelectedNamePipe = /** @class */ (function () { function GetSelectedNamePipe() { } GetSelectedNamePipe.prototype.transform = function (selectedOption) { return typeof selectedOption == 'object' ? selectedOption.name : selectedOption; }; return GetSelectedNamePipe; }()); GetSelectedNamePipe.decorators = [ { type: core.Pipe, args: [{ name: 'GetSelectedNamePipe' },] }, ]; GetSelectedNamePipe.ctorParameters = function () { return []; }; var DropdownModule = /** @class */ (function () { function DropdownModule() { } return DropdownModule; }()); DropdownModule.decorators = [ { type: core.NgModule, args: [{ imports: [common.CommonModule, forms.FormsModule], declarations: [DropdownComponent, GetSelectedNamePipe], exports: [DropdownComponent] },] }, ]; DropdownModule.ctorParameters = function () { return []; }; exports.DropdownModule = DropdownModule; exports.ɵa = DropdownComponent; exports.ɵb = GetSelectedNamePipe; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=angular-dropdown-component.umd.js.map