novo-elements
Version:
Bullhorn's NOVO Element Repository for Angular 2
365 lines • 15.3 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
// NG2
var core_1 = require("@angular/core");
// APP
var OutsideClick_1 = require("../../utils/outside-click/OutsideClick");
var KeyCodes_1 = require("../../utils/key-codes/KeyCodes");
var Helpers_1 = require("../../utils/Helpers");
var NovoDropdownContainer = (function () {
function NovoDropdownContainer(element, renderer) {
this.element = element;
this.renderer = renderer;
this.scrollHandler = this.handleScroll.bind(this);
}
NovoDropdownContainer.prototype.ngDoCheck = function () {
if (this.isVisible && this.position) {
var element = this.element.nativeElement;
var position = Helpers_1.Helpers.calcPositionOffset(this.position, element, this.side);
if (position) {
this.renderer.setElementStyle(element, 'top', position.top);
this.renderer.setElementStyle(element, 'left', position.left);
}
}
};
NovoDropdownContainer.prototype.handleScroll = function () {
// On scroll, don't force the position to update (jump from top/middle/bottom/right)
this.updatePosition(this.relativeElement, this.side);
};
NovoDropdownContainer.prototype.show = function (appendToBody) {
this.appendToBody = appendToBody;
this.renderer.setElementStyle(this.element.nativeElement, 'display', 'block');
this.renderer.setElementStyle(this.element.nativeElement, 'visibility', 'visible');
this.isVisible = true;
if (appendToBody) {
window.addEventListener('scroll', this.scrollHandler);
}
};
NovoDropdownContainer.prototype.hide = function () {
this.isVisible = false;
this.renderer.setElementStyle(this.element.nativeElement, 'visibility', 'hidden');
if (this.appendToBody) {
window.removeEventListener('scroll', this.scrollHandler);
}
};
NovoDropdownContainer.prototype.updatePosition = function (element, side) {
this.relativeElement = element;
this.side = side;
this.position = element.getBoundingClientRect();
this.ngDoCheck();
};
NovoDropdownContainer.prototype.onKeyDown = function (event) {
// Close with ESC/Enter
if (this.isVisible && (event.keyCode === KeyCodes_1.KeyCodes.ESC || event.keyCode === KeyCodes_1.KeyCodes.ENTER)) {
this.parent.toggleActive(null, false);
}
};
return NovoDropdownContainer;
}());
NovoDropdownContainer.decorators = [
{ type: core_1.Component, args: [{
selector: 'novo-dropdown-container',
template: '<ng-content></ng-content>'
},] },
];
/** @nocollapse */
NovoDropdownContainer.ctorParameters = function () { return [
{ type: core_1.ElementRef, },
{ type: core_1.Renderer, },
]; };
NovoDropdownContainer.propDecorators = {
'onKeyDown': [{ type: core_1.HostListener, args: ['keydown', ['$event'],] },],
};
exports.NovoDropdownContainer = NovoDropdownContainer;
var NovoDropdownElement = (function (_super) {
__extends(NovoDropdownElement, _super);
function NovoDropdownElement(element) {
var _this = _super.call(this, element) || this;
// Append the dropdown container to the body
_this.appendToBody = false;
// What action to perform when we recieve scroll from parent selector
// TODO - handle "move"
_this.parentScrollAction = 'close';
// Side the dropdown will open
_this.side = 'left';
_this.activeIndex = -1;
_this.filterTerm = '';
// Click handler
_this.clickHandler = _this.toggleActive.bind(_this);
_this.closeHandler = _this.toggleActive.bind(_this);
_this.toggled = _this.onActiveChange;
// Listen for active change to hide/show menu
_this.onActiveChange.subscribe(function (active) {
if (active) {
_this.show();
}
else {
_this.hide();
}
});
return _this;
}
Object.defineProperty(NovoDropdownElement.prototype, "items", {
set: function (items) {
this._items = items;
// Get the innertext of all the items to allow for searching
this._textItems = items.map(function (item) {
return item.element.nativeElement.innerText;
});
},
enumerable: true,
configurable: true
});
NovoDropdownElement.prototype.ngOnInit = function () {
// Add a click handler to the button to toggle the menu
var button = this.element.nativeElement.querySelector('button');
button.addEventListener('click', this.clickHandler);
if (this.parentScrollSelector) {
this.parentScrollElement = Helpers_1.Helpers.findAncestor(this.element.nativeElement, this.parentScrollSelector);
}
};
NovoDropdownElement.prototype.ngOnDestroy = function () {
// Remove listener
var button = this.element.nativeElement.querySelector('button');
if (button) {
button.removeEventListener('click', this.clickHandler);
}
};
NovoDropdownElement.prototype.show = function () {
this.container.parent = this;
this.container.show(this.appendToBody);
this.otherElement = this.container.element;
if (this.appendToBody) {
this.container.updatePosition(this.element.nativeElement.children[0], this.side);
// If append to body then rip it out of here and put on body
window.document.body.appendChild(this.container.element.nativeElement);
window.addEventListener('resize', this.closeHandler);
}
// Listen for scroll on a parent to force close
if (this.parentScrollElement) {
if (this.parentScrollAction === 'close') {
this.parentScrollElement.addEventListener('scroll', this.closeHandler);
}
}
};
NovoDropdownElement.prototype.hide = function () {
this.container.hide();
// If append to body then rip it out of here and put on body
if (this.appendToBody) {
var elm = this.container.element.nativeElement;
elm.parentNode.removeChild(elm);
window.removeEventListener('resize', this.closeHandler);
}
if (this.parentScrollElement) {
if (this.parentScrollAction === 'close') {
this.parentScrollElement.removeEventListener('scroll', this.closeHandler);
}
}
// Clear active index
if (this.activeIndex !== -1) {
this._items.toArray()[this.activeIndex].active = false;
}
this.activeIndex = -1;
};
NovoDropdownElement.prototype.onKeyDown = function (event) {
var _this = this;
Helpers_1.Helpers.swallowEvent(event);
if (this.active && event.keyCode === KeyCodes_1.KeyCodes.ESC) {
// active & esc hit -- close
this.toggleActive();
}
else if (event.keyCode === KeyCodes_1.KeyCodes.ENTER) {
// enter -- perform the "click"
this._items.toArray()[this.activeIndex].onClick();
}
else if (event.keyCode === KeyCodes_1.KeyCodes.DOWN) {
// down - navigate through the list ignoring disabled ones
if (this.activeIndex !== -1) {
this._items.toArray()[this.activeIndex].active = false;
}
this.activeIndex++;
if (this.activeIndex === this._items.length) {
this.activeIndex = 0;
}
while (this._items.toArray()[this.activeIndex].disabled) {
this.activeIndex++;
if (this.activeIndex === this._items.length) {
this.activeIndex = 0;
}
}
this._items.toArray()[this.activeIndex].active = true;
this.scrollToActive();
}
else if (event.keyCode === KeyCodes_1.KeyCodes.UP) {
// up -- navigate through the list ignoring disabled ones
if (this.activeIndex !== -1) {
this._items.toArray()[this.activeIndex].active = false;
}
this.activeIndex--;
if (this.activeIndex < 0) {
this.activeIndex = this._items.length - 1;
}
while (this._items.toArray()[this.activeIndex].disabled) {
this.activeIndex--;
if (this.activeIndex < 0) {
this.activeIndex = this._items.length - 1;
}
}
this._items.toArray()[this.activeIndex].active = true;
this.scrollToActive();
}
else if ((event.keyCode >= 65 && event.keyCode <= 90) || (event.keyCode >= 96 && event.keyCode <= 105) || (event.keyCode >= 48 && event.keyCode <= 57) || event.keyCode === KeyCodes_1.KeyCodes.SPACE) {
// A-Z, 0-9, space -- filter the list and scroll to active filter
// filter has hard reset after 2s
clearTimeout(this.filterTermTimeout);
this.filterTermTimeout = setTimeout(function () { _this.filterTerm = ''; }, 2000);
var char = String.fromCharCode(event.keyCode);
this.filterTerm = this.filterTerm.concat(char);
var index = this._textItems.findIndex(function (value) {
return new RegExp("^" + _this.filterTerm.toLowerCase()).test(value.trim().toLowerCase());
});
if (index !== -1) {
if (this.activeIndex !== -1) {
this._items.toArray()[this.activeIndex].active = false;
}
this.activeIndex = index;
this._items.toArray()[this.activeIndex].active = true;
this.scrollToActive();
}
}
else if ([KeyCodes_1.KeyCodes.BACKSPACE, KeyCodes_1.KeyCodes.DELETE].includes(event.keyCode)) {
// backspace, delete -- remove partial filters
clearTimeout(this.filterTermTimeout);
this.filterTermTimeout = setTimeout(function () { _this.filterTerm = ''; }, 2000);
this.filterTerm = this.filterTerm.slice(0, -1);
}
};
NovoDropdownElement.prototype.scrollToActive = function () {
var container = this.element.nativeElement.querySelector('novo-dropdown-container');
var item = this._items.toArray()[this.activeIndex];
if (container && item) {
container.scrollTop = item.element.nativeElement.offsetTop;
}
else {
// Append to body
container = document.querySelector('body > novo-dropdown-container');
if (container && item) {
container.scrollTop = item.element.nativeElement.offsetTop;
}
}
};
return NovoDropdownElement;
}(OutsideClick_1.OutsideClick));
NovoDropdownElement.decorators = [
{ type: core_1.Component, args: [{
selector: 'novo-dropdown',
template: "\n <ng-content select=\"button\" #trigger></ng-content>\n <novo-dropdown-container class=\"dropdown-container {{ containerClass }}\">\n <ng-content></ng-content>\n </novo-dropdown-container>\n "
},] },
];
/** @nocollapse */
NovoDropdownElement.ctorParameters = function () { return [
{ type: core_1.ElementRef, },
]; };
NovoDropdownElement.propDecorators = {
'appendToBody': [{ type: core_1.Input },],
'parentScrollSelector': [{ type: core_1.Input },],
'parentScrollAction': [{ type: core_1.Input },],
'containerClass': [{ type: core_1.Input },],
'side': [{ type: core_1.Input },],
'toggled': [{ type: core_1.Output },],
'container': [{ type: core_1.ViewChild, args: [NovoDropdownContainer,] },],
'button': [{ type: core_1.ViewChild, args: ['trigger',] },],
'onKeyDown': [{ type: core_1.HostListener, args: ['keydown', ['$event'],] },],
};
exports.NovoDropdownElement = NovoDropdownElement;
var NovoItemElement = (function () {
function NovoItemElement(dropdown, element) {
this.dropdown = dropdown;
this.element = element;
this.keepOpen = false;
this.action = new core_1.EventEmitter();
this.active = false;
}
NovoItemElement.prototype.onClick = function () {
// Poor man's disable
if (!this.disabled) {
// Close if keepOpen is false
if (!this.keepOpen) {
this.dropdown.toggleActive();
}
// Emit the action
this.action.emit();
}
};
return NovoItemElement;
}());
NovoItemElement.decorators = [
{ type: core_1.Component, args: [{
selector: 'item',
template: '<ng-content></ng-content>',
host: {
'[class.disabled]': 'disabled',
'[class.active]': 'active'
}
},] },
];
/** @nocollapse */
NovoItemElement.ctorParameters = function () { return [
{ type: NovoDropdownElement, },
{ type: core_1.ElementRef, },
]; };
NovoItemElement.propDecorators = {
'disabled': [{ type: core_1.Input },],
'keepOpen': [{ type: core_1.Input },],
'action': [{ type: core_1.Output },],
'onClick': [{ type: core_1.HostListener, args: ['click', [],] },],
};
exports.NovoItemElement = NovoItemElement;
var NovoListElement = (function () {
function NovoListElement(dropdown) {
this.dropdown = dropdown;
}
NovoListElement.prototype.ngAfterContentInit = function () {
this.dropdown.items = this.items;
};
return NovoListElement;
}());
NovoListElement.decorators = [
{ type: core_1.Component, args: [{
selector: 'list',
template: '<ng-content></ng-content>'
},] },
];
/** @nocollapse */
NovoListElement.ctorParameters = function () { return [
{ type: NovoDropdownElement, },
]; };
NovoListElement.propDecorators = {
'items': [{ type: core_1.ContentChildren, args: [NovoItemElement,] },],
};
exports.NovoListElement = NovoListElement;
var NovoItemHeaderElement = (function () {
function NovoItemHeaderElement() {
}
return NovoItemHeaderElement;
}());
NovoItemHeaderElement.decorators = [
{ type: core_1.Component, args: [{
selector: 'dropdown-item-header',
template: '<ng-content></ng-content>',
},] },
];
/** @nocollapse */
NovoItemHeaderElement.ctorParameters = function () { return []; };
exports.NovoItemHeaderElement = NovoItemHeaderElement;
//# sourceMappingURL=Dropdown.js.map