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
JavaScript
(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