coveo-search-ui
Version:
Coveo JavaScript Search Framework
131 lines (108 loc) • 3.75 kB
text/typescript
import { Dom, $$ } from '../../../utils/Dom';
import PopperJs from 'popper.js';
import { ResponsiveComponentsManager } from '../ResponsiveComponentsManager';
import { Assert } from '../../../misc/Assert';
import { l } from '../../../strings/Strings';
import { ComponentOptions } from '../../Base/ComponentOptions';
export interface IResponsiveDropdownContent {
element: Dom;
positionDropdown(): void;
hideDropdown(): void;
cleanUp(): void;
}
export class ResponsiveDropdownContent implements IResponsiveDropdownContent {
public static DEFAULT_CSS_CLASS_NAME = 'coveo-dropdown-content';
private coveoRoot: Dom;
private cssClassName: string;
private widthRatio: number;
private minWidth: number;
private popperReference: PopperJs;
public static isTargetInsideOpenedDropdown(target: Dom) {
Assert.exists(target);
const targetParentDropdown = target.parent(ResponsiveDropdownContent.DEFAULT_CSS_CLASS_NAME);
if (targetParentDropdown) {
return targetParentDropdown.style.display != 'none';
}
return false;
}
constructor(componentName: string, public element: Dom, coveoRoot: Dom, minWidth: number, widthRatio: number) {
Assert.isString(componentName);
Assert.exists(element);
Assert.exists(coveoRoot);
Assert.isLargerOrEqualsThan(0, minWidth);
Assert.isLargerOrEqualsThan(0, widthRatio);
Assert.isSmallerOrEqualsThan(1, widthRatio);
this.cssClassName = `coveo-${componentName}-dropdown-content`;
this.coveoRoot = coveoRoot;
this.widthRatio = widthRatio;
this.minWidth = minWidth;
}
public positionDropdown() {
this.setElementAttributes();
this.createPopper();
}
public hideDropdown() {
if (this.popperReference) {
this.unbindPopperEvents();
this.popperReference.destroy();
}
this.unsetElementAttributes();
}
public cleanUp() {
this.element.el.removeAttribute('style');
}
private setElementAttributes() {
this.element.show();
this.element.addClass(this.cssClassName);
this.element.addClass(ResponsiveDropdownContent.DEFAULT_CSS_CLASS_NAME);
this.element.setAttribute('role', 'group');
this.element.setAttribute('aria-label', l('FiltersDropdown'));
this.setElementWidth();
}
private setElementWidth() {
let width = this.widthRatio * this.coveoRoot.width();
if (width <= this.minWidth) {
width = this.minWidth;
}
this.element.el.style.width = width.toString() + 'px';
}
private unsetElementAttributes() {
this.element.hide();
this.element.removeClass(this.cssClassName);
this.element.removeClass(ResponsiveDropdownContent.DEFAULT_CSS_CLASS_NAME);
this.element.setAttribute('role', null);
this.element.setAttribute('aria-label', null);
}
private get popperReferenceElement() {
return this.coveoRoot.find(`.${ResponsiveComponentsManager.DROPDOWN_HEADER_WRAPPER_CSS_CLASS}`);
}
private createPopper() {
this.popperReference = new PopperJs(this.popperReferenceElement, this.element.el, {
placement: 'bottom-end',
positionFixed: true,
modifiers: {
preventOverflow: {
boundariesElement: this.coveoRoot.el
},
computeStyle: {
gpuAcceleration: false
}
},
eventsEnabled: false
});
this.bindPopperEvents();
}
private get scrollableParent() {
return ComponentOptions.findParentScrolling(this.popperReferenceElement);
}
private bindPopperEvents() {
$$(this.scrollableParent).on(['scroll', 'resize'], () => {
this.popperReference.update();
});
}
private unbindPopperEvents() {
$$(this.scrollableParent).off(['scroll', 'resize'], () => {
this.popperReference.update();
});
}
}