Newer
Older
url: string;
description: string;
menuLinkId: string;
isExternal: string;
}
export interface SearchLabels {
label?: string;
declare global {
interface Window {
CludoSayt: any;
}
}
import {Component, Prop, h, Watch, State, Listen, Host, Event, EventEmitter, Element} from '@stencil/core';
Markus Kalijärvi
committed
import {ComponentLabels} from '../site-header';
import {ColorVariant} from '../../../utils/utils';
@Component({
tag: 'hy-site-search',
styleUrl: 'site-search.scss',
shadow: true,
@Prop() color: ColorVariant = ColorVariant.black;
@Prop() isAlternative: boolean = false;
@Prop() searchLabels: string;
@Prop() searchTools: string;
private _searchTools: SearchTools[];
@Prop() showLabel: boolean = false;
@Prop() size: number;
private _searchLabels: SearchLabels[];
private searchTitleLabel: string;
private searchCloseLabel: string;
private searchToolsLabel: string;
private searchDescriptionLabel: string;
@State() isSearchPanelOpen: boolean = false;
@Event() searchPanelToggled: EventEmitter;
private _labels: ComponentLabels[];
@Watch('labels') labelsWatcher(data: ComponentLabels[] | string) {
this._labels = typeof data === 'string' ? JSON.parse(data) : data;
}
// Special search tools.
if (this.searchTools) {
this._searchTools = JSON.parse(this.searchTools);
}
if (this.searchLabels) {
this._searchLabels = JSON.parse(this.searchLabels);
this.searchTitleLabel = this._searchLabels['search_label'];
this.searchCloseLabel = this._searchLabels['search_close_label'];
this.searchToolsLabel = this._searchLabels['search_tools_label'];
this.searchDescriptionLabel = this._searchLabels['search_description'];
componentWillRender() {
this.labelsWatcher(this.labels);
}
// CLose the search panel if user opens the desktop menu panel.
@Listen('menuDesktopToggled', {target: 'document'})
desktopMenuToggled() {
}
// CLose the search panel if user opens the mobile menu panel.
@Listen('menuMobileToggled', {target: 'document'})
mobileMenuToggled() {
}
// CLose the search panel if user opens the language menu.
@Listen('menuLanguageToggled', {target: 'document'})
menuLanguageToggled() {
// Close the search panel if user opens University main menu
@Listen('universityMainMenuToggled', {target: 'document'})
universityMainMenuPanelToggled() {
this.closeSearchPanel();
}
// CLose the search panel on Scroll down.
@Listen('headerScrollDown', {target: 'document'})
headerScrollDown() {
this.closeSearchPanel();
}
closeSearchPanel() {
let cludoSayt = document.querySelectorAll('stencil-cludo-sayt')[0] as HTMLElement;
if (cludoSayt) {
let CludoSayt = window.CludoSayt;
if (typeof CludoSayt !== 'undefined') {
CludoSayt.hide();
}
this.isSearchPanelOpen = !this.isSearchPanelOpen;
if (this.isSearchPanelOpen) {
//const searchPanelSelector = this.el as HTMLElement;
// Close desktop menu panel and lang menu panel if they are open.
this.searchPanelToggled.emit();
let hyHeader = this.el.closest('.hy-site-header') as HTMLElement;
const headerHeight = hyHeader.classList.contains('hy-site-header--sticky-active')
? `${hyHeader.offsetHeight}px`
: `${hyHeader.offsetTop + hyHeader.offsetHeight}px`;
const searchPanel = this.el.shadowRoot.querySelectorAll(`.site-search__panel`)[0] as HTMLElement;
searchPanel.style.top = headerHeight;
// Remove hidden class from cludo suggestions
let cludoSayt = document.querySelectorAll('stencil-cludo-sayt')[0] as HTMLElement;
if (cludoSayt) {
cludoSayt.classList.remove('hidden');
}
// Add shadow backdrop
let rect = searchPanel.getBoundingClientRect();
let shadowTop = hyHeader.classList.contains('hy-site-header--sticky-active')
? hyHeader.offsetHeight + rect.height
: hyHeader.offsetTop + hyHeader.offsetHeight + rect.height;
this.showBackdropShadow('open', shadowTop);
// Without setTimeout it will not focus the input because it hasn't rendered yet.
setTimeout(() => {
const searchInput = this.el.shadowRoot.querySelector('input#search') as HTMLElement;
searchInput.focus();
});
showBackdropShadow(state = 'close', top = 0) {
let hyHeader = this.el.closest('.hy-site-header') as HTMLElement;
let hyBackdropDiv = hyHeader.children[0] as HTMLElement;
if (hyBackdropDiv) {
if (state === 'open') {
let me = window.outerHeight - top;
hyBackdropDiv.style.height = `${me}px`;
hyBackdropDiv.style.top = `${top}px`;
hyBackdropDiv.style.position = 'absolute';
hyBackdropDiv.classList.add('is-active');
} else {
hyBackdropDiv.removeAttribute('style');
hyBackdropDiv.classList.remove('is-active');
}
}
}
'site-search': true,
'site-search__is-open': this.isSearchPanelOpen,
aria-expanded={`${this.isSearchPanelOpen}`}
group: this.isGroup,
'is-open--menu': this.isAlternative,
'is-open': this.isSearchPanelOpen,
}}
{this.showLabel ? (
<span class={{'button--search__label': true, 'button--search__label__group': this.isGroup}}>
{this._labels['label']}
</span>
) : (
''
)}
<hy-icon icon={'hy-icon-search'} size={this.size} fill={this.color} />
</button>
<div
class={{
'site-search__panel': true,
'site-search__panel__is-open': this.isSearchPanelOpen,
}}
aria-hidden={`${!this.isSearchPanelOpen}`}
<div class="site-search__panel__wrapper">
<div class="site-search__panel__title">
<div class="site-search__panel__title__group">
<h1>{this.searchTitleLabel}</h1>
<div class="description">{this.searchDescriptionLabel}</div>
<div id="cludo-search-results" class="container_12">
<div class="search-banner"></div>
<div class="search-filters search-filters-mobile"></div>
<div class="col-md-12">
<div style={{margin: '20px 0 32px'}} id="cludo-search-content-form">
<hy-search-field input-id="search" label=""></hy-search-field>
</div>
</div>
<div class="col-md-3">
<div class="search-filters" aria-controls="search-results"></div>
</div>
<div class="col-md-9">
<div class="search-results-container">
<hy-paragraph-text>
<div class="search-result-count"></div>
</hy-paragraph-text>
<div class="search-did-you-mean" role="Complementary"></div>
<div class="search-results" role="region" id="search-results" aria-live="polite"></div>
</div>
</div>
{this._searchTools && this._searchTools.length > 0 && (
<div class="title">{this.searchToolsLabel}</div>
<div class="list">
{this._searchTools.map((i) => {
let searchToolTarget = i.isExternal ? '_blank' : '_self';
return (
<a class="search-special-tool" href={i.url} target={searchToolTarget}>
<hy-icon icon={'hy-icon-arrow-to-right'} size={14} fill={ColorVariant.black} />
<span class="label">{i.label}</span>
<span class="description">{i.description}</span>
</a>
);
})}
</div>
class={{
'site-search__panel__panel-toggle': true,
}}
aria-label={this.searchCloseLabel}
aria-expanded={`${this.isSearchPanelOpen}`}
>
<span class="site-search__panel__panel-toggle__label">
<span class="site-search__panel__panel-toggle__label__title" tabindex="0">
{this.searchCloseLabel}
</span>
<hy-icon icon={'hy-icon-remove'} size={16} fill={ColorVariant.black} />
</span>
</button>