diff --git a/cards/multilang-product-prominentvideo/component.js b/cards/multilang-product-prominentvideo/component.js index 779da89eb..631515086 100644 --- a/cards/multilang-product-prominentvideo/component.js +++ b/cards/multilang-product-prominentvideo/component.js @@ -57,6 +57,7 @@ class multilang_product_prominentvideoCardComponent extends BaseCard['multilang- } onMount() { + super.onMount(); const videoSelector = '.js-HitchhikerProductProminentVideo-video'; const videoEl = this._container.querySelector(videoSelector); if (!videoEl) { diff --git a/cards/product-prominentvideo/component.js b/cards/product-prominentvideo/component.js new file mode 100644 index 000000000..29015b903 --- /dev/null +++ b/cards/product-prominentvideo/component.js @@ -0,0 +1,103 @@ +{{> cards/card_component componentName='product-prominentvideo' }} + +class product_prominentvideoCardComponent extends BaseCard['product-prominentvideo'] { + constructor(config = {}, systemConfig = {}) { + super(config, systemConfig); + } + + /** + * This returns an object that will be called `card` + * in the template. Put all mapping logic here. + * + * @param profile profile of the entity in the card + */ + dataForRender(profile) { + this.youtubeUrl = Formatter.getYoutubeUrl(profile.videos || []); + this.vimeoUrl = profile.c_vimeo; + + const linkTarget = AnswersExperience.runtimeConfig.get('linkTarget') || '_top'; + + return { + title: profile.name, // The header text of the card + url: profile.landingPageUrl, // If the card title is a clickable link, set URL here + target: linkTarget, // If the title's URL should open in a new tab, etc. + titleEventOptions: this.addDefaultEventOptions(), + subtitle: profile.featuredMessage?.description, // The sub-header text of the card + videoUrl: this.youtubeUrl || this.vimeoUrl, + details: profile.richTextDescription ? ANSWERS.formatRichText(profile.richTextDescription, 'richTextDescription', linkTarget) : null, // The text in the body of the card + // If the card's details are longer than a certain character count, you can truncate the + // text. A toggle will be supplied that can show or hide the truncated text. + // Note: If you are using rich text for the details, you should not enable this feature. + // showMoreDetails: { + // showMoreLimit: 24, // Character count limit + // showMoreText: 'Show more', // Label when toggle will show truncated text + // showLessText: 'Show less' // Label when toggle will hide truncated text + // }, + // The primary CTA of the card + CTA1: { + label: profile.c_primaryCTA ? profile.c_primaryCTA.label : null, // The CTA's label + iconName: 'chevron', // The icon to use for the CTA + url: Formatter.generateCTAFieldTypeLink(profile.c_primaryCTA), // The URL a user will be directed to when clicking + target: linkTarget, // Where the new URL will be opened + eventType: 'CTA_CLICK', // Type of Analytics event fired when clicking the CTA + eventOptions: this.addDefaultEventOptions(), + // ariaLabel: '', // Accessible text providing a descriptive label for the CTA + }, + // The secondary CTA of the card + CTA2: { + label: profile.c_secondaryCTA ? profile.c_secondaryCTA.label : null, + iconName: 'chevron', + url: Formatter.generateCTAFieldTypeLink(profile.c_secondaryCTA), + target: linkTarget, + eventType: 'CTA_CLICK', + eventOptions: this.addDefaultEventOptions(), + // ariaLabel: '', + } + }; + } + + onMount() { + super.onMount(); + const videoSelector = '.js-HitchhikerProductProminentVideo-video'; + const videoEl = this._container.querySelector(videoSelector); + if (!videoEl) { + return; + } + const addPlayer = videoApi => { + videoApi.addPlayer(videoEl, { + onPlay: () => this.onPlay() + }); + }; + if (this.youtubeUrl) { + HitchhikerJS.requireYoutubeAPI().then(addPlayer); + } else if (this.vimeoUrl) { + HitchhikerJS.requireVimeoAPI().then(addPlayer); + } + } + + onPlay() { + const event = new ANSWERS.AnalyticsEvent('CTA_CLICK') + .addOptions({ + verticalKey: this.verticalKey, + entityId: this.result?._raw?.id, + searcher: this._config.isUniversal ? 'UNIVERSAL' : 'VERTICAL', + ctaLabel: 'video_played' + }); + this.analyticsReporter.report(event); + } + + /** + * The template to render + * @returns {string} + * @override + */ + static defaultTemplateName (config) { + return 'cards/product-prominentvideo'; + } +} + +ANSWERS.registerTemplate( + 'cards/product-prominentvideo', + {{{stringifyPartial (read 'cards/product-prominentvideo/template') }}} +); +ANSWERS.registerComponentType(product_prominentvideoCardComponent); diff --git a/cards/product-prominentvideo/template.hbs b/cards/product-prominentvideo/template.hbs new file mode 100644 index 000000000..a25c5f932 --- /dev/null +++ b/cards/product-prominentvideo/template.hbs @@ -0,0 +1,124 @@ +
+
+ {{> title }} + {{> subtitle }} +
+ {{> video }} + {{> content }} +
+ +{{#*inline 'title'}} +{{#if card.title}} +
+ {{#if card.url}} + + {{card.title}} + + {{else}} + {{card.title}} + {{/if}} +
+{{/if}} +{{/inline}} + +{{#*inline 'subtitle'}} +{{#if card.subtitle}} +
+ {{card.subtitle}} +
+{{/if}} +{{/inline}} + +{{#*inline 'video'}} +{{#if card.videoUrl}} +
+ +
+{{/if}} +{{/inline}} + +{{#*inline 'content'}} +{{#if (any card.details (all card.CTA1 card.CTA1.url card.CTA1.label) (all card.CTA2 card.CTA2.url card.CTA2.label))}} +
+ {{> details }} + {{> ctas }} +
+{{/if}} +{{/inline}} + +{{! Displays the details for the card. If showMoreDetails has been configured, + this partial handles the show more toggle, show less toggle, truncated details, + and full details. If showMoreDetails has not been configured, it will display the + the regular card details. +}} +{{#*inline 'details'}} +{{#if card.details}} +
+ {{#if showExcessDetailsToggle}} +
+ {{{truncatedDetails}}} +
+ {{/if}} +
+ {{{card.details}}} +
+ {{#if showExcessDetailsToggle}} + + + {{/if}} +
+{{/if}} +{{/inline}} + +{{#*inline 'ctas'}} +{{#if (any (all card.CTA1 card.CTA1.url card.CTA1.label) (all card.CTA2 card.CTA2.url card.CTA2.label))}} +
+ {{> CTA card.CTA1 ctaName="primaryCTA" }} + {{> CTA card.CTA2 ctaName="secondaryCTA" }} +
+{{/if}} +{{/inline}} + +{{#*inline 'CTA'}} +{{#if (all url label)}} +
+ + {{#if (any iconName iconUrl)}} +
+
+
+
+ {{/if}} +
+ {{label}} +
+
+
+{{/if}} +{{/inline}}