UNPKG

coveo-search-ui

Version:

Coveo JavaScript Search Framework

149 lines (132 loc) 5.18 kB
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);