coveo-search-ui
Version:
Coveo JavaScript Search Framework
149 lines (132 loc) • 5.18 kB
text/typescript
import { Component } from '../Base/Component';
import { ComponentOptions } from '../Base/ComponentOptions';
import { IComponentBindings } from '../Base/ComponentBindings';
import { Initialization } from '../Base/Initialization';
import { IQueryResult } from '../../rest/QueryResult';
import { Assert } from '../../misc/Assert';
import { $$ } from '../../utils/Dom';
import { KeyboardUtils, KEYBOARD } from '../../utils/KeyboardUtils';
import * as _ from 'underscore';
import { exportGlobally } from '../../GlobalExports';
import 'styling/_CardActionBar';
import { SVGIcons } from '../../utils/SVGIcons';
import { SVGDom } from '../../utils/SVGDom';
export interface ICardActionBarOptions {
hidden?: boolean;
openOnMouseOver?: boolean;
}
/**
* The `CardActionBar` component displays an action bar at the bottom of a card result (see
* [Result Layouts](https://docs.coveo.com/en/360/)). It is a simple container for buttons or complementary
* information.
*
* You should place this component at the bottom of a card result template (i.e., as the last child of the surrounding
* `coveo-result-frame` div).
*
* See [Using the CardActionBar Component](https://docs.coveo.com/en/1349/#using-the-cardactionbar-component)
*/
export class CardActionBar extends Component {
static ID = 'CardActionBar';
static doExport = () => {
exportGlobally({
CardActionBar: CardActionBar
});
};
parentResult: HTMLElement;
arrowContainer: HTMLElement;
removedTabIndexElements: HTMLElement[] = [];
/**
* @componentOptions
*/
static options: ICardActionBarOptions = {
/**
* Whether to hide the component by default and append a visual indicator to its parent query result.
*
* If this option is set to `true`, the component will show itself when the user clicks its parent query result.
*
* Default value is `true`.
*/
hidden: ComponentOptions.buildBooleanOption({ defaultValue: true }),
/**
* Whether to open the `CardActionBar` when the cursor hovers over it.
*
* This option is only meaningful when [`hidden`]{@link CardActionBar.options.hidden} is set to `true`.
*
* Default value is `true`.
*/
openOnMouseOver: ComponentOptions.buildBooleanOption({ defaultValue: true, depend: 'hidden' })
};
/**
* Creates a new `CardActionBar` component.
* @param element The HTMLElement on which to instantiate the component.
* @param options The options for the component.
* @param bindings The bindings that the component requires to function normally. If not set, these will be
* automatically resolved (with a slower execution time).
* @param result The parent [query result]{@link IQueryResult}..
*/
constructor(
public element: HTMLElement,
public options?: ICardActionBarOptions,
bindings?: IComponentBindings,
public result?: IQueryResult
) {
super(element, CardActionBar.ID, bindings);
this.options = ComponentOptions.initComponentOptions(element, CardActionBar, options);
this.parentResult = $$(this.element).closest('CoveoResult');
Assert.check(this.parentResult !== undefined, 'ActionBar needs to be a child of a Result');
if (this.options.hidden) {
$$(this.parentResult).addClass('coveo-clickable');
this.appendArrow();
this.bindEvents();
_.forEach($$(this.element).findAll('*'), (elem: HTMLElement) => {
if (elem.hasAttribute('tabindex') && elem.getAttribute('tabindex') == '0') {
this.removedTabIndexElements.push(elem);
elem.removeAttribute('tabindex');
}
});
} else {
this.element.style.transition = 'none';
this.element.style.transform = 'none';
}
}
/**
* Shows the component.
*/
public show() {
$$(this.element).addClass('coveo-opened');
_.forEach(this.removedTabIndexElements, (e: Element) => {
e.setAttribute('tabindex', '0');
});
}
/**
* Hides the component.
*/
public hide() {
$$(this.element).removeClass('coveo-opened');
_.forEach(this.removedTabIndexElements, (e: Element) => {
e.removeAttribute('tabindex');
});
}
private bindEvents() {
$$(this.parentResult).on('click', () => this.show());
$$(this.parentResult).on('mouseleave', () => this.hide());
$$(this.element).on('focusin', () => this.show());
$$(this.element).on('focusout', () => this.hide());
if (this.options.openOnMouseOver) {
$$(this.arrowContainer).on('mouseenter', () => this.show());
}
}
private appendArrow() {
this.arrowContainer = $$('div', { className: 'coveo-card-action-bar-arrow-container', tabindex: 0 }).el;
this.bind.on(
this.arrowContainer,
'keyup',
KeyboardUtils.keypressAction(KEYBOARD.ENTER, () => this.show())
);
const arrowUp = $$('span', { className: 'coveo-icon coveo-card-action-bar-arrow-icon' }, SVGIcons.icons.arrowUp);
SVGDom.addClassToSVGInContainer(arrowUp.el, 'coveo-card-action-bar-arrow-svg');
this.arrowContainer.appendChild(arrowUp.el);
this.parentResult.appendChild(this.arrowContainer);
}
}
Initialization.registerAutoCreateComponent(CardActionBar);