ngx-bootstrap
Version:
Native Angular Bootstrap Components
240 lines • 12.3 kB
JavaScript
import { Component, ElementRef, HostListener, QueryList, ViewChild, ViewChildren, Renderer2 } from '@angular/core';
import { isBs3, Utils } from '../utils';
import { latinize } from './typeahead-utils';
var TypeaheadContainerComponent = /** @class */ (function () {
function TypeaheadContainerComponent(element, renderer) {
this.renderer = renderer;
this.isFocused = false;
this._matches = [];
this.isScrolledIntoView = function (elem) {
var containerViewTop = this.ulElement.nativeElement.scrollTop;
var containerViewBottom = containerViewTop + this.ulElement.nativeElement.offsetHeight;
var elemTop = elem.offsetTop;
var elemBottom = elemTop + elem.offsetHeight;
return ((elemBottom <= containerViewBottom) && (elemTop >= containerViewTop));
};
this.element = element;
}
Object.defineProperty(TypeaheadContainerComponent.prototype, "isBs4", {
get: function () {
return !isBs3();
},
enumerable: true,
configurable: true
});
Object.defineProperty(TypeaheadContainerComponent.prototype, "active", {
get: function () {
return this._active;
},
enumerable: true,
configurable: true
});
Object.defineProperty(TypeaheadContainerComponent.prototype, "matches", {
get: function () {
return this._matches;
},
set: function (value) {
var _this = this;
this._matches = value;
this.needScrollbar = this.typeaheadScrollable && this.typeaheadOptionsInScrollableView < this.matches.length;
if (this.typeaheadScrollable) {
setTimeout(function () {
_this.setScrollableMode();
});
}
if (this._matches.length > 0) {
this._active = this._matches[0];
if (this._active.isHeader()) {
this.nextActiveMatch();
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(TypeaheadContainerComponent.prototype, "optionsListTemplate", {
get: function () {
return this.parent ? this.parent.optionsListTemplate : undefined;
},
enumerable: true,
configurable: true
});
Object.defineProperty(TypeaheadContainerComponent.prototype, "typeaheadScrollable", {
get: function () {
return this.parent ? this.parent.typeaheadScrollable : false;
},
enumerable: true,
configurable: true
});
Object.defineProperty(TypeaheadContainerComponent.prototype, "typeaheadOptionsInScrollableView", {
get: function () {
return this.parent ? this.parent.typeaheadOptionsInScrollableView : 5;
},
enumerable: true,
configurable: true
});
Object.defineProperty(TypeaheadContainerComponent.prototype, "itemTemplate", {
get: function () {
return this.parent ? this.parent.typeaheadItemTemplate : undefined;
},
enumerable: true,
configurable: true
});
TypeaheadContainerComponent.prototype.selectActiveMatch = function () {
this.selectMatch(this._active);
};
TypeaheadContainerComponent.prototype.prevActiveMatch = function () {
var index = this.matches.indexOf(this._active);
this._active = this.matches[index - 1 < 0 ? this.matches.length - 1 : index - 1];
if (this._active.isHeader()) {
this.prevActiveMatch();
}
if (this.typeaheadScrollable) {
this.scrollPrevious(index);
}
};
TypeaheadContainerComponent.prototype.nextActiveMatch = function () {
var index = this.matches.indexOf(this._active);
this._active = this.matches[index + 1 > this.matches.length - 1 ? 0 : index + 1];
if (this._active.isHeader()) {
this.nextActiveMatch();
}
if (this.typeaheadScrollable) {
this.scrollNext(index);
}
};
TypeaheadContainerComponent.prototype.selectActive = function (value) {
this.isFocused = true;
this._active = value;
};
TypeaheadContainerComponent.prototype.highlight = function (match, query) {
var itemStr = match.value;
var itemStrHelper = (this.parent && this.parent.typeaheadLatinize
? latinize(itemStr)
: itemStr).toLowerCase();
var startIdx;
var tokenLen;
// Replaces the capture string with the same string inside of a "strong" tag
if (typeof query === 'object') {
var queryLen = query.length;
for (var i = 0; i < queryLen; i += 1) {
// query[i] is already latinized and lower case
startIdx = itemStrHelper.indexOf(query[i]);
tokenLen = query[i].length;
if (startIdx >= 0 && tokenLen > 0) {
itemStr =
itemStr.substring(0, startIdx) + "<strong>" + itemStr.substring(startIdx, startIdx + tokenLen) + "</strong>" +
("" + itemStr.substring(startIdx + tokenLen));
itemStrHelper =
itemStrHelper.substring(0, startIdx) + " " + ' '.repeat(tokenLen) + " " +
("" + itemStrHelper.substring(startIdx + tokenLen));
}
}
}
else if (query) {
// query is already latinized and lower case
startIdx = itemStrHelper.indexOf(query);
tokenLen = query.length;
if (startIdx >= 0 && tokenLen > 0) {
itemStr =
itemStr.substring(0, startIdx) + "<strong>" + itemStr.substring(startIdx, startIdx + tokenLen) + "</strong>" +
("" + itemStr.substring(startIdx + tokenLen));
}
}
return itemStr;
};
TypeaheadContainerComponent.prototype.focusLost = function () {
this.isFocused = false;
};
TypeaheadContainerComponent.prototype.isActive = function (value) {
return this._active === value;
};
TypeaheadContainerComponent.prototype.selectMatch = function (value, e) {
var _this = this;
if (e === void 0) { e = void 0; }
if (e) {
e.stopPropagation();
e.preventDefault();
}
this.parent.changeModel(value);
setTimeout(function () { return _this.parent.typeaheadOnSelect.emit(value); }, 0);
return false;
};
TypeaheadContainerComponent.prototype.setScrollableMode = function () {
if (!this.ulElement) {
this.ulElement = this.element;
}
if (this.liElements.first) {
var ulStyles = Utils.getStyles(this.ulElement.nativeElement);
var liStyles = Utils.getStyles(this.liElements.first.nativeElement);
var ulPaddingBottom = parseFloat((ulStyles['padding-bottom'] ? ulStyles['padding-bottom'] : '').replace('px', ''));
var ulPaddingTop = parseFloat((ulStyles['padding-top'] ? ulStyles['padding-top'] : '0').replace('px', ''));
var optionHeight = parseFloat((liStyles['height'] ? liStyles['height'] : '0').replace('px', ''));
var height = this.typeaheadOptionsInScrollableView * optionHeight;
this.guiHeight = height + ulPaddingTop + ulPaddingBottom + "px";
}
this.renderer.setStyle(this.element.nativeElement, 'visibility', 'visible');
};
TypeaheadContainerComponent.prototype.scrollPrevious = function (index) {
if (index === 0) {
this.scrollToBottom();
return;
}
if (this.liElements) {
var liElement = this.liElements.toArray()[index - 1];
if (liElement && !this.isScrolledIntoView(liElement.nativeElement)) {
this.ulElement.nativeElement.scrollTop = liElement.nativeElement.offsetTop;
}
}
};
TypeaheadContainerComponent.prototype.scrollNext = function (index) {
if (index + 1 > this.matches.length - 1) {
this.scrollToTop();
return;
}
if (this.liElements) {
var liElement = this.liElements.toArray()[index + 1];
if (liElement && !this.isScrolledIntoView(liElement.nativeElement)) {
this.ulElement.nativeElement.scrollTop =
liElement.nativeElement.offsetTop -
this.ulElement.nativeElement.offsetHeight +
liElement.nativeElement.offsetHeight;
}
}
};
TypeaheadContainerComponent.prototype.scrollToBottom = function () {
this.ulElement.nativeElement.scrollTop = this.ulElement.nativeElement.scrollHeight;
};
TypeaheadContainerComponent.prototype.scrollToTop = function () {
this.ulElement.nativeElement.scrollTop = 0;
};
TypeaheadContainerComponent.decorators = [
{ type: Component, args: [{
selector: 'typeahead-container',
// tslint:disable-next-line
template: "<!-- inject options list template --> <ng-template [ngTemplateOutlet]=\"optionsListTemplate || (isBs4 ? bs4Template : bs3Template)\" [ngTemplateOutletContext]=\"{matches:matches, itemTemplate:itemTemplate, query:query}\"></ng-template> <!-- default options item template --> <ng-template #bsItemTemplate let-match=\"match\" let-query=\"query\"><span [innerHtml]=\"highlight(match, query)\"></span> </ng-template> <!-- Bootstrap 3 options list template --> <ng-template #bs3Template> <ul class=\"dropdown-menu\" #ulElement [style.overflow-y]=\"needScrollbar ? 'scroll': 'auto'\" [style.height]=\"needScrollbar ? guiHeight: 'auto'\"> <ng-template ngFor let-match let-i=\"index\" [ngForOf]=\"matches\"> <li #liElements *ngIf=\"match.isHeader()\" class=\"dropdown-header\">{{ match }}</li> <li #liElements *ngIf=\"!match.isHeader()\" [class.active]=\"isActive(match)\" (mouseenter)=\"selectActive(match)\"> <a href=\"#\" (click)=\"selectMatch(match, $event)\" tabindex=\"-1\"> <ng-template [ngTemplateOutlet]=\"itemTemplate || bsItemTemplate\" [ngTemplateOutletContext]=\"{item:match.item, index:i, match:match, query:query}\"></ng-template> </a> </li> </ng-template> </ul> </ng-template> <!-- Bootstrap 4 options list template --> <ng-template #bs4Template> <ng-template ngFor let-match let-i=\"index\" [ngForOf]=\"matches\"> <h6 *ngIf=\"match.isHeader()\" class=\"dropdown-header\">{{ match }}</h6> <ng-template [ngIf]=\"!match.isHeader()\"> <button #liElements class=\"dropdown-item\" (click)=\"selectMatch(match, $event)\" (mouseenter)=\"selectActive(match)\" [class.active]=\"isActive(match)\"> <ng-template [ngTemplateOutlet]=\"itemTemplate || bsItemTemplate\" [ngTemplateOutletContext]=\"{item:match.item, index:i, match:match, query:query}\"></ng-template> </button> </ng-template> </ng-template> </ng-template> ",
host: {
class: 'dropdown open',
'[class.dropdown-menu]': 'isBs4',
'[style.overflow-y]': "isBs4 && needScrollbar ? 'scroll': 'visible'",
'[style.height]': "isBs4 && needScrollbar ? guiHeight: 'auto'",
'[style.visibility]': "typeaheadScrollable ? 'hidden' : 'visible'",
'[class.dropup]': 'dropup',
style: 'position: absolute;display: block;'
}
},] },
];
/** @nocollapse */
TypeaheadContainerComponent.ctorParameters = function () { return [
{ type: ElementRef, },
{ type: Renderer2, },
]; };
TypeaheadContainerComponent.propDecorators = {
"ulElement": [{ type: ViewChild, args: ['ulElement',] },],
"liElements": [{ type: ViewChildren, args: ['liElements',] },],
"focusLost": [{ type: HostListener, args: ['mouseleave',] }, { type: HostListener, args: ['blur',] },],
};
return TypeaheadContainerComponent;
}());
export { TypeaheadContainerComponent };
//# sourceMappingURL=typeahead-container.component.js.map