From d34e9e384d8c2f7101cf0c2fa451bab1c2a46a86 Mon Sep 17 00:00:00 2001 From: Cody Foss <160176245+cfoss-coveo@users.noreply.github.com> Date: Fri, 14 Nov 2025 12:27:15 -0700 Subject: [PATCH 1/7] Initial commit, accessibility updates, misc changes --- src/connector.css | 27 ++++ src/connector.js | 339 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 366 insertions(+) diff --git a/src/connector.css b/src/connector.css index 854ed83..47a2268 100644 --- a/src/connector.css +++ b/src/connector.css @@ -111,3 +111,30 @@ content: "\e092"; margin-left: .5em; } +.smart-snippet-container { + border: 1px solid #ddd; + border-radius: 4px; + padding: 10px 20px 20px 20px; +} +.smart-snippet-container .smart-snippet-answer { + padding: 30px 20px 20px 20px; + position: relative; + overflow: hidden; +} +.smart-snippet-container .smart-snippet-toggle-height { + text-align: center; +} +.smart-snippet-container .smart-snippet-answer .smart-snippet-answer-truncated, +.smart-snippet-container.smart-snippet-height-limiter .smart-snippet-answer .smart-snippet-answer-full { + display: none; +} +.smart-snippet-container .smart-snippet-answer .smart-snippet-answer-full, +.smart-snippet-container.smart-snippet-height-limiter .smart-snippet-answer .smart-snippet-answer-truncated { + display: block; +} +.smart-snippet-ai-disclaimer { + font-style: italic; + font-size: .85em; + border-top: 1px solid #eee; + padding-top: .85em; +} \ No newline at end of file diff --git a/src/connector.js b/src/connector.js index cc5a41f..0fc767e 100644 --- a/src/connector.js +++ b/src/connector.js @@ -6,6 +6,8 @@ import { buildPager, buildResultsPerPage, buildSearchStatus, + buildSmartSnippet, + buildSmartSnippetQuestionsList, buildUrlManager, buildDidYouMean, buildContext, @@ -35,6 +37,8 @@ const defaults = { "numberOfSuggestions": 5, "minimumCharsForSuggestions": 3, "enableHistoryPush": true, + "enableSmartSnippets": false, + "smartSnippetToggleLimit": 250, "isContextSearch": false, "isAdvancedSearch": false, "originLevel3": originPath, @@ -58,6 +62,8 @@ let resultListController; let querySummaryController; let didYouMeanController; let pagerController; +let smartSnippetController; +let smartSnippetQuestionListController; let statusController; let urlManager; let unsubscribeManager; @@ -66,6 +72,8 @@ let unsubscribeResultListController; let unsubscribeQuerySummaryController; let unsubscribeDidYouMeanController; let unsubscribePagerController; +let unsubscribeSmartSnippetController; +let unsubscribeSmartSnippetQuestionListController; // UI states let updateSearchBoxFromState = false; @@ -74,6 +82,8 @@ let resultListState; let querySummaryState; let didYouMeanState; let pagerState; +let smartSnippetState; +let smartSnippetQuestionListState; let lastCharKeyUp; let activeSuggestion = 0; let pagerManuallyCleared = false; @@ -92,6 +102,8 @@ let querySummaryElement = document.querySelector( '#query-summary' ); let pagerElement = document.querySelector( '#pager' ); let suggestionsElement = document.querySelector( '#suggestions' ); let didYouMeanElement = document.querySelector( '#did-you-mean' ); +let smartSnippetsElement = document.querySelector( '#smart-snippet' ); +let smartSnippetQuestionListContainerElement = document.querySelector( '#smart-snippet-question-list' ); // UI templates let resultTemplateHTML = document.getElementById( 'sr-single' )?.innerHTML; @@ -105,6 +117,9 @@ let pageTemplateHTML = document.getElementById( 'sr-pager-page' )?.innerHTML; let nextPageTemplateHTML = document.getElementById( 'sr-pager-next' )?.innerHTML; let pagerContainerTemplateHTML = document.getElementById( 'sr-pager-container' )?.innerHTML; let qsA11yHintHTML = document.getElementById( 'sr-qs-hint' )?.innerHTML; +let smartSnippetHTML = document.getElementById( 'sr-smart-snippet-container' )?.innerHTML; +let smartSnippetQuestionListHTML = document.getElementById( 'sr-smart-snippet-question-list-container' )?.innerHTML; +let smartSnippetQuestionListContainerHTML = document.getElementById( 'sr-smart-snippet-question-list-container' )?.innerHTML; // Init parameters and UI function initSearchUI() { @@ -374,6 +389,77 @@ function initTpl() { resultsSection.append( querySummaryElement ); } + // Smart snippet - Featured SS + if ( params.enableSmartSnippets && !smartSnippetHTML ) { + smartSnippetHTML = + `
+ + +
+ +
+
+
%[source.title]
+
  1. %[source.raw.displaynavlabel]
+
+
`; + + // Localize + if ( lang === "fr" ) { + smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', "Les informations ont été récupérées par l'intelligence artificielle" ) + smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_toggle_more]', "Afficher plus" ) + } else { + smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', 'The information was retrieved by Artificial Intelligence' ) + smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_toggle_more]', "Show more" ) + } + + } + + // Smart snippet - Question list container + if ( params.enableSmartSnippets && !smartSnippetQuestionListContainerHTML ) { + smartSnippetQuestionListContainerHTML = + ``; + + // Localize + if ( lang === "fr" ) { + smartSnippetQuestionListContainerHTML = smartSnippetQuestionListContainerHTML.replace( '%[smart_snippet_question_list_title]', 'Les gens demandent aussi' ) + } else { + smartSnippetQuestionListContainerHTML = smartSnippetQuestionListContainerHTML.replace( '%[smart_snippet_question_list_title]', 'People also ask' ) + } + } + + // Smart snippets - Featured SS + if ( params.enableSmartSnippets && !smartSnippetsElement ) { + smartSnippetsElement = document.createElement( "div" ); + smartSnippetsElement.id = "smart-snippets"; + + resultsSection.append( smartSnippetsElement ); + } + // auto-create did you mean element if ( !didYouMeanElement ) { didYouMeanElement = document.createElement( "div" ); @@ -400,6 +486,44 @@ function initTpl() { pagerElement = newPagerElement; } + + // Smart snippet - Question list item + if( params.enableSmartSnippets && !smartSnippetQuestionListHTML ) { + smartSnippetQuestionListHTML = + `
  • +
    + %[question] +
    +
    + %[answer] +
    %[smart_snippet_answer_ai_disclaimer]
    +
    +
    +
    +
    %[source.title]
    +
    1. %[source.raw.displaynavlabel]
    +
    +
    +
    +
  • `; + + // Localize + if ( lang === "fr" ) { + smartSnippetQuestionListHTML = smartSnippetQuestionListHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', "Les informations ont été récupérées par l'intelligence artificielle" ) + } else { + smartSnippetQuestionListHTML = smartSnippetQuestionListHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', 'Information retrieved by artificial intelligence.' ) + } + } + + // Smart snippets - Questions list container + if ( params.enableSmartSnippets && !smartSnippetQuestionListContainerElement ) { + smartSnippetQuestionListContainerElement = document.createElement( "div" ); + smartSnippetQuestionListContainerElement.id = "smart-snippets-question-list"; + + // Add it after the results list element (after the results, before the paging) + resultListElement.after( smartSnippetQuestionListContainerElement ); + } + // initialize the search box searchBoxElement = document.querySelector( params.searchBoxQuery ); @@ -512,6 +636,97 @@ function stripHtml(html) { return tmp.textContent || tmp.innerText || ""; } +// Calculates the length of the text for a block of HTML +function getTextLength( content ){ + var elem; + + // If a string is passed in, convert it to an element + if( !( content instanceof Element ) ){ + elem = document.createElement( 'div' ); + elem.innerHTML = String( content ); + } else { + elem = content + } + + // Get the inside content + var fullText = elem.textContent || '' + + // Strip out extra whitespace, like indenting + fullText = fullText.replace( /[\n\r]+|[\s]{2,}/g, ' ' ).trim() + return fullText.length + +} + +// Truncate an HTML string to a given text length, preserving tag structure. +function truncateHtml( html, maxLength ) { + + // Put into a temp div element, so we can work with it + const container = document.createElement( "div" ); + container.innerHTML = html; + + // If content is less than maxLength, return it as-is + if ( maxLength < 0 || getTextLength( container ) <= maxLength ) { + return html; + } + + let remaining = maxLength; + + // Recursive function that goes through the HTML tree, rebuilding it to the + // point where we reach `maxLength` + function cloneWithLimit( node ) { + if ( remaining <= 0 ) return null; + + // If this node is just text, we're at the deepest point of this part of the tree. + // If we're below the limit, return as-is. If we hit the limit, truncate here and add the ellipsis. + if ( node.nodeType === Node.TEXT_NODE ) { + const text = node.nodeValue || ''; + if ( text.length <= remaining ) { + remaining -= text.length; + return document.createTextNode( text ); + } else { + const truncatedText = text.slice( 0, remaining ) + '…'; + remaining = 0; + return document.createTextNode( truncatedText ); + } + } + + // If it's a tag, we go inside and recursively iterate through the children until we hit the length limit + if ( node.nodeType === Node.ELEMENT_NODE ) { + // Create a copy of the current tag + const clone = node.cloneNode( false ); + + // Iterate through the children of the original node + for ( let child of node.childNodes ) { + if ( remaining <= 0 ) break; // If we hit the limit, stop here. + const childClone = cloneWithLimit( child ); + if ( childClone ) clone.appendChild( childClone ); + } + + // Drop empty elements (except self-closing ones) + if ( !clone.hasChildNodes() && !['BR', 'IMG'].includes( clone.tagName ) ) { + return null; + } + return clone; + } + + // Drop comments and other node types + return null; + } + + // Build a truncated copy of the HTML structure + const truncatedHtml = document.createDocumentFragment(); + for ( let child of container.childNodes ) { + if ( remaining <= 0 ) break; + const chunk = cloneWithLimit( child ); + if ( chunk ) truncatedHtml.appendChild( chunk ); + } + + // Serialize back to HTML + const wrapper = document.createElement( 'div' ); + wrapper.appendChild( truncatedHtml ); + return wrapper.innerHTML; +} + // Focus to H2 heading in results section function focusToView() { let focusElement = resultsSection.querySelector( "h2" ); @@ -658,6 +873,11 @@ function initEngine() { didYouMeanController = buildDidYouMean( headlessEngine, { options: { automaticallyCorrectQuery: params.automaticallyCorrectQuery } } ); pagerController = buildPager( headlessEngine, { options: { numberOfPages: params.numberOfPages } } ); statusController = buildSearchStatus( headlessEngine ); + + if( params.enableSmartSnippets ){ + smartSnippetController = buildSmartSnippet( headlessEngine ); + smartSnippetQuestionListController = buildSmartSnippetQuestionsList( headlessEngine ); + } // Refine search based on URL parameters for filters, mostly used in Advanced Search to trigger only one search per page load if ( urlParams.allq || urlParams.exctq || urlParams.anyq || urlParams.noneq || urlParams.fqupdate || urlParams.dmn || urlParams.fqocct || urlParams.elctn_cat || urlParams.filetype || urlParams.site || urlParams.year || urlParams.declaredtype || urlParams.startdate || urlParams.enddate || urlParams.dprtmnt ) { @@ -892,6 +1112,10 @@ function initEngine() { unsubscribeQuerySummaryController = querySummaryController.subscribe( () => updateQuerySummaryState( querySummaryController.state ) ); unsubscribeDidYouMeanController = didYouMeanController.subscribe( () => updateDidYouMeanState( didYouMeanController.state ) ); unsubscribePagerController = pagerController.subscribe( () => updatePagerState( pagerController.state ) ); + if( params.enableSmartSnippets ) { + unsubscribeSmartSnippetController = smartSnippetController.subscribe( () => updateSmartSnippetState( smartSnippetController.state ) ); + unsubscribeSmartSnippetQuestionListController = smartSnippetQuestionListController.subscribe( () => updateSmartSnippetQuestionListState( smartSnippetQuestionListController.state ) ); + } // Clear event tracking, for legacy browsers const onUnload = () => { @@ -902,6 +1126,8 @@ function initEngine() { unsubscribeQuerySummaryController?.(); unsubscribeDidYouMeanController?.(); unsubscribePagerController?.(); + unsubscribeSmartSnippetController?.(); + unsubscribeSmartSnippetQuestionListController?.(); }; // Listen to URL change (hash) @@ -990,6 +1216,14 @@ function initEngine() { didYouMeanElement.textContent = ""; pagerElement.textContent = ""; pagerManuallyCleared = true; + if( params.enableSmartSnippets ) { + if( smartSnippetsElement && smartSnippetsElement.textContent ) { + smartSnippetsElement.textContent = ""; + } + if( smartSnippetQuestionListContainerElement && smartSnippetQuestionListContainerElement.textContent ) { + smartSnippetQuestionListContainerElement.textContent = ""; + } + } // Show no results message in Query Summary if no query entered querySummaryElement.innerHTML = noResultTemplateHTML; @@ -1414,5 +1648,110 @@ function updatePagerUrlParam( currentPage ) { window.history.replaceState( {}, '', `${winPath}?${newSearch}${winLoc.hash}` ); } +// Function in insert values into smart snippet HTML templates +function insertSmartSnippetValues ( smartSnippetState, standalone = false, truncateLimit = -1) { + const { question, answer, source } = smartSnippetState; + + var snippetHTML = (standalone ? smartSnippetHTML : smartSnippetQuestionListHTML) + snippetHTML = snippetHTML + .replace( '%[question]', DOMPurify.sanitize( question ) ) + .replace( '%[answer]', DOMPurify.sanitize( answer ) ) + .replace( '%[answer_truncated]', truncateHtml( DOMPurify.sanitize( answer ), truncateLimit ) ); + + if(source) { + var displaynavlabel = source?.raw?.displaynavlabel ? source.raw.displaynavlabel.split( '>' ).join( ' 
  • ' ) : source.uri + snippetHTML = snippetHTML.replace( '%[source.raw.displaynavlabel]', displaynavlabel ) + .split( '%[source.title]' ).join ( source.title ) + .split( '%[source.uri]' ).join ( source.uri ); + } + + return snippetHTML; +} + +// Update the "featured" Smart Snippets section +function updateSmartSnippetState ( newState ) { + console.log('newState', newState) + smartSnippetState = newState; + smartSnippetsElement.innerHTML = ''; // Clear contents of SM + + // We don't get the full smart snippet state past the first page, so don't render anything + if( pagerState.currentPage > 1 ) return; + + if( smartSnippetState.answerFound ) { + smartSnippetsElement.innerHTML = insertSmartSnippetValues( smartSnippetState, true, params.smartSnippetToggleLimit ); + + // If the length of the answer is less that params.smartSnippetToggleLimit, remove toggle controls + if( getTextLength( smartSnippetState.answer ) <= params.smartSnippetToggleLimit ) { + + document.querySelector( '.smart-snippet-toggle-height' ).remove() + document.querySelector( '.smart-snippet-answer-truncated' ).remove() + + } else { + + // Add height toggle stuff + const smartSnippetsContainerElement = document.getElementById( 'smart-snippet-container' ); + smartSnippetsContainerElement.classList.add( 'smart-snippet-height-limiter' ); // Collapse by default + const smartSnippetToggleButton = document.getElementById( 'smart-snippet-toggle' ); + const smartSnippetAnswer = document.getElementById( 'smart-snippet-answer' ); + smartSnippetAnswer.querySelectorAll( "a, link, button, input" ).forEach( ( el ) => { + el.setAttribute( 'disabled', 'true' ); + el.setAttribute( 'tabindex', '-1' ); + } ) + + // Handle the + smartSnippetToggleButton.addEventListener( 'click', (event) => { + + // Expand the container + if(smartSnippetsContainerElement.classList.contains( 'smart-snippet-height-limiter' )){ + smartSnippetsContainerElement.classList.remove( 'smart-snippet-height-limiter' ) + smartSnippetAnswer.setAttribute( "aria-hidden", "false" ); + smartSnippetAnswer.querySelectorAll( "a, link, button, input" ).forEach( ( el ) => { + el.removeAttribute( 'disabled' ); + el.removeAttribute( 'tabindex' ); + } ) + smartSnippetToggleButton.setAttribute( "aria-expanded", "true" ); + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-label' ).innerText = lang === "fr" ? "Afficher moins": "Show less"; + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.remove( 'glyphicon-chevron-down' ) + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.add( 'glyphicon-chevron-up' ) + + // Collapse the container + } else { + smartSnippetsContainerElement.classList.add( 'smart-snippet-height-limiter' ); + smartSnippetAnswer.setAttribute( "aria-hidden", "true" ); + smartSnippetToggleButton.setAttribute( "aria-expanded", "false" ); + smartSnippetAnswer.querySelectorAll( "a, link, button, input" ).forEach( ( el ) => { + el.setAttribute( 'disabled', 'true' ); + el.setAttribute( 'tabindex', '-1' ); + } ) + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-label' ).innerText = lang === "fr" ? "Afficher plus": "Show more"; + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.add( 'glyphicon-chevron-down' ) + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.remove( 'glyphicon-chevron-up' ) + smartSnippetToggleButton.focus() + } + } ) + + } + } +} + +// Update the Smart Snippets questions section +function updateSmartSnippetQuestionListState ( newState ) { + smartSnippetQuestionListState = newState; + smartSnippetQuestionListContainerElement.innerHTML = ''; // Clear contents of SS question list container + + // We don't get the full smart snippet state past the first page, so don't render anything + if( pagerState.currentPage > 1 ) return; + + // If there are questions, populate smartSnippetQuestionListItemsHTML + if( smartSnippetQuestionListState?.questions && smartSnippetQuestionListState?.questions.length > 0 ) { + let smartSnippetQuestionListItemsHTML = ''; + for ( const i in smartSnippetQuestionListState.questions ) { + smartSnippetQuestionListItemsHTML += insertSmartSnippetValues( smartSnippetQuestionListState.questions[i], false ) + } + smartSnippetQuestionListContainerElement.innerHTML = smartSnippetQuestionListContainerHTML.split( '%[smart_snippet_question_list]' ).join( smartSnippetQuestionListItemsHTML ); + } + +} + // Run Search UI initSearchUI(); From 10c90873b84ccd66b2aec3317a7df3e209bebf40 Mon Sep 17 00:00:00 2001 From: Cody Foss <160176245+cfoss-coveo@users.noreply.github.com> Date: Fri, 14 Nov 2025 12:36:10 -0700 Subject: [PATCH 2/7] Linter fixes --- src/connector.js | 75 ++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/src/connector.js b/src/connector.js index 0fc767e..8f76106 100644 --- a/src/connector.js +++ b/src/connector.js @@ -417,15 +417,14 @@ function initTpl() { `; - // Localize - if ( lang === "fr" ) { - smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', "Les informations ont été récupérées par l'intelligence artificielle" ) - smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_toggle_more]', "Afficher plus" ) - } else { - smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', 'The information was retrieved by Artificial Intelligence' ) - smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_toggle_more]', "Show more" ) - } - + // Localize + if ( lang === "fr" ) { + smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', "Les informations ont été récupérées par l'intelligence artificielle" ); + smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_toggle_more]', "Afficher plus" ); + } else { + smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', 'The information was retrieved by Artificial Intelligence' ); + smartSnippetHTML = smartSnippetHTML.replace( '%[smart_snippet_toggle_more]', "Show more" ); + } } // Smart snippet - Question list container @@ -446,9 +445,9 @@ function initTpl() { // Localize if ( lang === "fr" ) { - smartSnippetQuestionListContainerHTML = smartSnippetQuestionListContainerHTML.replace( '%[smart_snippet_question_list_title]', 'Les gens demandent aussi' ) + smartSnippetQuestionListContainerHTML = smartSnippetQuestionListContainerHTML.replace( '%[smart_snippet_question_list_title]', 'Les gens demandent aussi' ); } else { - smartSnippetQuestionListContainerHTML = smartSnippetQuestionListContainerHTML.replace( '%[smart_snippet_question_list_title]', 'People also ask' ) + smartSnippetQuestionListContainerHTML = smartSnippetQuestionListContainerHTML.replace( '%[smart_snippet_question_list_title]', 'People also ask' ); } } @@ -507,12 +506,12 @@ function initTpl() {
  • `; - // Localize - if ( lang === "fr" ) { - smartSnippetQuestionListHTML = smartSnippetQuestionListHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', "Les informations ont été récupérées par l'intelligence artificielle" ) - } else { - smartSnippetQuestionListHTML = smartSnippetQuestionListHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', 'Information retrieved by artificial intelligence.' ) - } + // Localize + if ( lang === "fr" ) { + smartSnippetQuestionListHTML = smartSnippetQuestionListHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', "Les informations ont été récupérées par l'intelligence artificielle" ); + } else { + smartSnippetQuestionListHTML = smartSnippetQuestionListHTML.replace( '%[smart_snippet_answer_ai_disclaimer]', 'Information retrieved by artificial intelligence.' ); + } } // Smart snippets - Questions list container @@ -645,15 +644,15 @@ function getTextLength( content ){ elem = document.createElement( 'div' ); elem.innerHTML = String( content ); } else { - elem = content + elem = content; } // Get the inside content - var fullText = elem.textContent || '' + var fullText = elem.textContent || ''; // Strip out extra whitespace, like indenting - fullText = fullText.replace( /[\n\r]+|[\s]{2,}/g, ' ' ).trim() - return fullText.length + fullText = fullText.replace( /[\n\r]+|[\s]{2,}/g, ' ' ).trim(); + return fullText.length; } @@ -1652,14 +1651,14 @@ function updatePagerUrlParam( currentPage ) { function insertSmartSnippetValues ( smartSnippetState, standalone = false, truncateLimit = -1) { const { question, answer, source } = smartSnippetState; - var snippetHTML = (standalone ? smartSnippetHTML : smartSnippetQuestionListHTML) + var snippetHTML = (standalone ? smartSnippetHTML : smartSnippetQuestionListHTML); snippetHTML = snippetHTML .replace( '%[question]', DOMPurify.sanitize( question ) ) .replace( '%[answer]', DOMPurify.sanitize( answer ) ) .replace( '%[answer_truncated]', truncateHtml( DOMPurify.sanitize( answer ), truncateLimit ) ); if(source) { - var displaynavlabel = source?.raw?.displaynavlabel ? source.raw.displaynavlabel.split( '>' ).join( ' 
  • ' ) : source.uri + var displaynavlabel = source?.raw?.displaynavlabel ? source.raw.displaynavlabel.split( '>' ).join( ' 
  • ' ) : source.uri; snippetHTML = snippetHTML.replace( '%[source.raw.displaynavlabel]', displaynavlabel ) .split( '%[source.title]' ).join ( source.title ) .split( '%[source.uri]' ).join ( source.uri ); @@ -1670,7 +1669,7 @@ function insertSmartSnippetValues ( smartSnippetState, standalone = false, trunc // Update the "featured" Smart Snippets section function updateSmartSnippetState ( newState ) { - console.log('newState', newState) + smartSnippetState = newState; smartSnippetsElement.innerHTML = ''; // Clear contents of SM @@ -1683,8 +1682,8 @@ function updateSmartSnippetState ( newState ) { // If the length of the answer is less that params.smartSnippetToggleLimit, remove toggle controls if( getTextLength( smartSnippetState.answer ) <= params.smartSnippetToggleLimit ) { - document.querySelector( '.smart-snippet-toggle-height' ).remove() - document.querySelector( '.smart-snippet-answer-truncated' ).remove() + document.querySelector( '.smart-snippet-toggle-height' ).remove(); + document.querySelector( '.smart-snippet-answer-truncated' ).remove(); } else { @@ -1696,23 +1695,23 @@ function updateSmartSnippetState ( newState ) { smartSnippetAnswer.querySelectorAll( "a, link, button, input" ).forEach( ( el ) => { el.setAttribute( 'disabled', 'true' ); el.setAttribute( 'tabindex', '-1' ); - } ) + } ); // Handle the - smartSnippetToggleButton.addEventListener( 'click', (event) => { + smartSnippetToggleButton.addEventListener( 'click', () => { // Expand the container if(smartSnippetsContainerElement.classList.contains( 'smart-snippet-height-limiter' )){ - smartSnippetsContainerElement.classList.remove( 'smart-snippet-height-limiter' ) + smartSnippetsContainerElement.classList.remove( 'smart-snippet-height-limiter' ); smartSnippetAnswer.setAttribute( "aria-hidden", "false" ); smartSnippetAnswer.querySelectorAll( "a, link, button, input" ).forEach( ( el ) => { el.removeAttribute( 'disabled' ); el.removeAttribute( 'tabindex' ); - } ) + } ); smartSnippetToggleButton.setAttribute( "aria-expanded", "true" ); smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-label' ).innerText = lang === "fr" ? "Afficher moins": "Show less"; - smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.remove( 'glyphicon-chevron-down' ) - smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.add( 'glyphicon-chevron-up' ) + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.remove( 'glyphicon-chevron-down' ); + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.add( 'glyphicon-chevron-up' ); // Collapse the container } else { @@ -1722,13 +1721,13 @@ function updateSmartSnippetState ( newState ) { smartSnippetAnswer.querySelectorAll( "a, link, button, input" ).forEach( ( el ) => { el.setAttribute( 'disabled', 'true' ); el.setAttribute( 'tabindex', '-1' ); - } ) + } ); smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-label' ).innerText = lang === "fr" ? "Afficher plus": "Show more"; - smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.add( 'glyphicon-chevron-down' ) - smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.remove( 'glyphicon-chevron-up' ) - smartSnippetToggleButton.focus() + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.add( 'glyphicon-chevron-down' ); + smartSnippetToggleButton.querySelector( '#smart-snippet-toggle-icon' ).classList.remove( 'glyphicon-chevron-up' ); + smartSnippetToggleButton.focus(); } - } ) + } ); } } @@ -1746,7 +1745,7 @@ function updateSmartSnippetQuestionListState ( newState ) { if( smartSnippetQuestionListState?.questions && smartSnippetQuestionListState?.questions.length > 0 ) { let smartSnippetQuestionListItemsHTML = ''; for ( const i in smartSnippetQuestionListState.questions ) { - smartSnippetQuestionListItemsHTML += insertSmartSnippetValues( smartSnippetQuestionListState.questions[i], false ) + smartSnippetQuestionListItemsHTML += insertSmartSnippetValues( smartSnippetQuestionListState.questions[i], false ); } smartSnippetQuestionListContainerElement.innerHTML = smartSnippetQuestionListContainerHTML.split( '%[smart_snippet_question_list]' ).join( smartSnippetQuestionListItemsHTML ); } From e078b6f006cedfec543310a8dad3ece8a6cae394 Mon Sep 17 00:00:00 2001 From: Cody Foss <160176245+cfoss-coveo@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:00:39 -0700 Subject: [PATCH 3/7] Update connector.js --- src/connector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connector.js b/src/connector.js index 8f76106..9f900f0 100644 --- a/src/connector.js +++ b/src/connector.js @@ -396,7 +396,7 @@ function initTpl() { -