UNPKG

coveo-search-ui

Version:

Coveo JavaScript Search Framework

154 lines (139 loc) 5.58 kB
import { Template, IFieldsToMatch, TemplateRole } from './Template'; import { Utils } from '../../utils/Utils'; import { TemplateConditionEvaluator } from './TemplateConditionEvaluator'; import { IComponentOptionsFieldsOption } from '../Base/IComponentOptions'; import { ComponentOptions } from '../Base/ComponentOptions'; import { $$, Dom } from '../../utils/Dom'; import { Initialization } from '../Base/Initialization'; import { ValidLayout } from '../ResultLayoutSelector/ValidLayout'; import { map, chain, each } from 'underscore'; export interface ITemplateFromStringProperties { condition?: string; layout?: ValidLayout; mobile?: boolean; tablet?: boolean; desktop?: boolean; fieldsToMatch?: IFieldsToMatch[]; role?: TemplateRole; } export class TemplateFromAScriptTag { constructor(public template: Template, public scriptTag: HTMLElement) { let condition = scriptTag.getAttribute('data-condition'); if (condition != null) { // Allows to add quotes in data-condition on the templates condition = condition.toString().replace(/&quot;/g, '"'); template.setConditionWithFallback(condition); } else { const parsedFieldsAttributes = this.parseFieldsAttributes(); if (parsedFieldsAttributes && Utils.isNonEmptyArray(parsedFieldsAttributes)) { this.template.fieldsToMatch = parsedFieldsAttributes; } } this.template.layout = this.parseLayout(); this.template.mobile = this.parseScreenSize('data-mobile'); this.template.tablet = this.parseScreenSize('data-tablet'); this.template.desktop = this.parseScreenSize('data-desktop'); this.template.fields = TemplateConditionEvaluator.getFieldFromString(`${scriptTag.innerHTML} ${condition ? condition : ''}`); this.template.role = <TemplateRole>scriptTag.getAttribute('data-role'); this.template.addFields(TemplateConditionEvaluator.getFieldFromString(scriptTag.innerHTML + ' ' + condition) || []); // Additional fields that might be specified directly on the script element const additionalFields = ComponentOptions.loadFieldsOption(scriptTag, 'fields', <IComponentOptionsFieldsOption>{ includeInResults: true }); if (additionalFields != null) { // remove the @ this.template.addFields(map(additionalFields, field => field.substr(1))); } // Additional fields that might be used to conditionally load the template when it's going to be rendered. this.template.addFields( map(this.template.fieldsToMatch, (toMatch: IFieldsToMatch) => { return toMatch.field; }) ); // Scan components in this template // return the fields needed for the content of this template const neededFieldsForComponents = chain(this.template.getComponentsInside(scriptTag.innerHTML)) .map((component: string) => { return Initialization.getRegisteredFieldsComponentForQuery(component); }) .flatten() .value(); this.template.addFields(neededFieldsForComponents); } toHtmlElement(container?: Dom): HTMLElement { if (!container) { container = $$('code'); } const condition = $$(this.scriptTag).getAttribute('data-condition'); if (condition) { container.setAttribute('data-condition', condition); } container.setHtml(this.scriptTag.innerHTML); return container.el; } parseFieldsAttributes(): IFieldsToMatch[] { const dataSet = this.scriptTag.dataset; return chain(dataSet) .map((value, key: string) => { const match = key.match(/field([a-zA-Z0-9_\.]*)/i); if (match) { let values; if (value != null && value != 'null' && value != '') { values = map(value.split(','), val => val.trim()); } return { field: match[1].toLowerCase(), values }; } else { return undefined; } }) .compact() .value(); } parseScreenSize(attribute: string) { return Utils.parseBooleanIfNotUndefined(this.scriptTag.getAttribute(attribute)); } parseLayout(): ValidLayout { const layout = this.scriptTag.getAttribute('data-layout'); return <ValidLayout>layout; } static fromString( template: string, properties: ITemplateFromStringProperties = {}, container = document.createElement('code') ): HTMLElement { container.innerHTML = template; if (properties.condition != null) { container.setAttribute('data-condition', properties.condition); } if (properties.layout != null) { container.setAttribute('data-layout', properties.layout); } else { container.setAttribute('data-layout', 'list'); } if (properties.mobile != null) { container.setAttribute('data-mobile', properties.mobile.toString()); } if (properties.tablet != null) { container.setAttribute('data-tablet', properties.tablet.toString()); } if (properties.desktop != null) { container.setAttribute('data-desktop', properties.desktop.toString()); } if (properties.fieldsToMatch != null) { each(properties.fieldsToMatch, (fieldToMatch: IFieldsToMatch) => { if (fieldToMatch.values) { container.setAttribute(`data-field-${fieldToMatch.field.toLowerCase()}`, fieldToMatch.values.join(',')); } else { container.setAttribute(`data-field-${fieldToMatch.field.toLowerCase()}`, null); } }); } if (properties.role != null) { container.setAttribute('data-role', properties.role); } return container; } }