Coveo for Sitecore 5 is now available!

Coveo for Sitecore Legacy Search UI Framework - Overview of CoveoSearch.ascx

Coveo for Sitecore 4.1 (November 2018)

CoveoSearch.ascx is a sublayout file that represents a search component, which includes a search box, a list of search results, a pager control, and a few placeholders where you can insert additional components. Its default location is c:\inetpub\wwwroot\SitecoreInstanceName\Website\layouts\Coveo\CoveoSearch.ascx.

Digging into Its Code

The code of CoveoSearch.ascx may appear complex at first, but taking a second look reveals its simplicity:

  • At the top, you can find a small block of JavaScript code that initializes the JavaScript Search Framework V1.0 :
    • Coveo.$('#search') is a special extension that selects the elements matching the specified CSS selector. In this case, the div element is selected with an id attribute equal to search.
    • Calling the coveoForSitecore function on the selected div element automatically instantiates/renders a search interface.
    • Notice that the set of options to the coveoForSitecore function was passed (retrieved by calling GetJavaScriptInitializationOptions). These options correspond to the attributes on the div element (i.e., data-enable-history, data-results-per-page, etc.).
  • Inside the div element with an id attribute equal to search, you can find several other div elements, each one having a different value for its class attribute. A few values include:
    • CoveoSearchBox: renders a full-featured search box control that allows you to enter queries.
    • CoveoPager: renders a pager control that allows you to browse through the several pages of search results.
    • CoveoResultList: renders a list of search results.
  • Inside the div element with a class attribute equal to CoveoResultList, you can find a script element with a class attribute equal to result-template and a type attribute equal to text/x-underscore-template. This is actually an underscore.js template:
    • It allows you to dynamically build your search results by adding additional fields (e.g. raw.<%= ToCoveoFieldName("LayoutId", false) %>).
    • It allows you to run conditional expressions, which allows for greater flexibility (e.g., if statements).
  • You can find special sc:placeholder elements into which you can drop additional components (or more precisely sublayouts). They can be identified by their key attribute:
    • coveo-facets: this is where you can insert facet components.
    • coveo-sorts: this is where you can insert sort components.
    • coveo-tabs: this is where you can insert tab components.
  • You can find statements such as Model.Something that allow you to access the options and settings that you defined for your component in the Page Editor. The properties of Model are currently undocumented.
  • Overall, you can see that these HTML elements are the building blocks of your search interface.
<%@ Control Language="c#" AutoEventWireup="true" Inherits="Coveo.UI.CoveoSearch" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
<%@ Import Namespace="Coveo.UI" %>
<%@ Register TagPrefix="coveoui" Namespace="Coveo.UI.Controls" Assembly="Coveo.UIBase" %>
<!-- When customizing this component, ensure to use "Coveo.$" instead of the regular jQuery "$" to
     avoid any conflicts with Sitecore's Page Editor/Experience Editor.  -->
<coveoui:ErrorSummary runat="server" />
<coveoui:WhenConfigured runat="server">
    <script type="text/javascript" src="/Coveo/js/cultures/<%= Model.CultureName %>.js"></script>
    <script type="text/javascript">
        Coveo.$(function() {
            CoveoForSitecore.componentsOptions = <%= Model.GetJavaScriptInitializationOptions() %>;
        });
    </script>
    <!-- This hidden input is required to bypass a problem with the Enter key causing a form submission
         if the form has exactly one text field, or only when there is a submit button present. -->
    <input type="text" class="fix-submit" />
    <div id="search"
         class="CoveoSearchInterface"
         data-design='new'
         data-enable-history="<%= Model.EnableHistory %>"
         data-results-per-page="<%= Model.ResultsPerPage %>"
         data-excerpt-length="<%= Model.ExcerptLength %>"
         data-hide-until-first-query="<%= Model.HideUntilFirstQuery %>"
         data-auto-trigger-query="<%= Model.AutoTriggerQuery %>"
         data-maximum-age="<%= Model.MaximumAge %>">
        <% if (Model.AnalyticsEnabled) { %>
            <div class="CoveoAnalytics"
                 data-anonymous="<%= Model.IsUserAnonymous %>"
                 data-endpoint="<%= Model.GetAnalyticsEndpoint() %>"
                 data-search-hub="<%= Model.GetAnalyticsCurrentPageName() %>"
                 data-send-to-cloud="<%= Model.CoveoAnalyticsEnabled %>">
            </div>
        <% } %>
        <div class="coveo-main-section">
            <% if (Model.DisplayTabs) { %>
                <div class="coveo-tab-section coveo-placeholder-fix">
                    <sc:placeholder key="coveo-tabs" runat="server"></sc:placeholder>
                </div>
            <% } %>
            <% if (Model.DisplayFacets) { %>
                <div class="coveo-facet-column">
                    <% if (Model.DisplayLogo) { %>
                        <div class="coveo-logo"></div>
                    <% } %>
                    <sc:placeholder key="coveo-facets" runat="server"></sc:placeholder>
                    &nbsp;
                </div>
            <% } %>
            <div class="coveo-results-column">
                <% if (Model.DisplaySearchbox) { %>
                    <div class="CoveoSearchbox"
                        <% if (Model.EnableOmnibox) { %>
                            data-enable-omnibox="true"
                            data-omnibox-timeout="<%= Model.OmniboxTimeout %>"
                            data-enable-field-addon="<%= Model.OmniboxEnableFieldAddon %>"
                            data-enable-simple-field-addon="<%= Model.OmniboxEnableSimpleFieldAddon %>"
                            data-enable-top-query-addon="<%= Model.OmniboxEnableTopQueryAddon %>"
                            data-enable-reveal-query-suggest-addon="<%= Model.OmniboxEnableMLQuerySuggestAddon %>"
                            data-enable-query-extension-addon="<%= Model.OmniboxEnableQueryExtensionAddon %>"
                        <% } %>
                        <% if (Model.IsSearchAsYouTypeEnabled) { %>
                            data-enable-search-as-you-type="true"
                            data-search-as-you-type-delay="<%= Model.SearchboxSuggestionsDelay %>"
                        <% } %>
                    ></div>
                <% } %>
                <% if (Model.DisplayBreadcrumb) { %>
                    <div class="CoveoBreadcrumb"></div>
                <% } %>
                <div class="coveo-results-header">
                    <div class="coveo-summary-section">
                        <% if (Model.DisplayQuerySummary) { %>
                            <span class="CoveoQuerySummary"
                                  data-enable-search-tips="<%= Model.QuerySummaryEnableSearchTips %>"
                                  data-only-display-search-tips="<%= Model.QuerySummaryOnlyDisplaySearchTips %>"></span>
                        <% } %>
                        <% if (Model.DisplayQueryDuration) { %>
                            <span class="CoveoQueryDuration"></span>
                        <% } %>
                    </div>
                    <% if (Model.DisplaySorting) { %>
                        <div class="coveo-sort-section">
                            <sc:placeholder key="coveo-sorts" runat="server"></sc:placeholder>
                        </div>
                    <% } %>
                </div>
                <div class="CoveoHiddenQuery"></div>
                <% if (Model.DisplayDidYouMean) { %>
                    <div class="CoveoDidYouMean"
                         data-enable-auto-correction="<%= Model.EnableDidYouMeanAutoCorrection %>"></div>
                <% } %>
                <% if (Model.DisplayErrorReport) { %>
                    <div class="CoveoErrorReport"></div>
                <% } %>
                <% if (Model.DisplayResultList) { %>
                    <% if (Model.DisplayTopPager) { %>
                        <div class="CoveoPager" data-number-of-pages="<%= Model.PagerNumberOfPages %>"
                                                data-max-number-of-pages="<%= Model.PagerMaxNumberOfPages %>"
                                                data-enable-navigation-button="<%= Model.EnablePagerNavigationButton %>"></div>
                    <% } %>
                    <div class="CoveoResultList" data-wait-animation="fade"
                                                 data-enable-infinite-scroll="<%= Model.EnableInfiniteScroll %>"
                                                 data-infinite-scroll-page-size="<%= Model.InfiniteScrollPageSize %>">
                        <script class="result-template" type="text/underscore">
                            <div class="coveo-result-frame">
                                <div class="coveo-result-row">
                                    <div class="coveo-result-cell" style="width:85px;text-align:center;padding-top:7px;">
                                        <span class="CoveoIcon"></span>
                                        {{ if (hasHtmlVersion) { }}
                                            <div class='CoveoQuickview'
                                                 data-fixed='true'
                                                 data-width='70%'
                                                 data-heigth='70%'
                                                 data-template-id='CoveoQuickviewTemplate'></div>
                                        {{ } }}
                                    </div>

                                    <div class="coveo-result-cell" style="padding-left:15px;">
                                        <div class="coveo-result-row">
                                            <div class="coveo-result-cell" style="font-size:18px;">
                                            <div class='coveo-title'>
                                                {{ if (raw.<%= ToCoveoFieldName("HasLayout", false) %> === "1" || raw.syssource !== "<%= Model.IndexSourceName %>") { }}
                                                    <a class='CoveoResultLink'>{{=title?highlight(title, titleHighlights):clickUri}}</a>
                                                {{ } else { }}
                                                    <span class='CoveoResultTitle'>{{=title?highlight(title, titleHighlights):''}}</span>
                                                {{ } }}
                                                                </div>
                                                            </div>

                                                            <div class="coveo-result-cell" style="width:120px; text-align:right; font-size:12px">
                                                                {{/* Change the tooltip on the date. */}}
                                                                {{if(raw.<%= ToCoveoFieldName("created", false) %> === raw.<%= ToCoveoFieldName("updated", false) %>) { }}
                                                                    <div title='<%= Model.Labels[LocalizedStringKeys.CREATION_TIME] %>'>{{-dateTime(raw.sysdate)}}</div>
                                                                {{ } else { }}
                                                                    <div title='<%= Model.Labels[LocalizedStringKeys.LAST_TIME_MODIFIED] %>'>{{-dateTime(raw.sysdate)}}</div>
                                                {{ } }}
                                            </div>
                                        </div>

                                        <div class="coveo-result-row">
                                            <div class="coveo-result-cell">
                                                <span class="CoveoExcerpt"></span>
                                            </div>
                                        </div>
                                    </div>
                                </div>

                                <div class="coveo-result-row">
                                    <div class="coveo-result-cell" style="font-size:13px">
                                        <table class="CoveoFieldTable">
                                            <tbody>
                                                <tr data-field='<%= ToCoveoFieldName("_templatename") %>' data-caption='<%= Model.Labels[LocalizedStringKeys.TEMPLATE] %>' />
                                                {{ if (raw.<%= ToCoveoFieldName("created", false) %> === raw.<%= ToCoveoFieldName("updated", false) %>) { }}
                                                    <tr data-field='<%= ToCoveoFieldName("parsedcreatedby") %>' data-caption='<%= Model.Labels[LocalizedStringKeys.CREATED_BY] %>' />
                                                {{ } else { }}
                                                    <tr data-field='<%= ToCoveoFieldName("parsedcreatedby") %>' data-caption='<%= Model.Labels[LocalizedStringKeys.CREATED_BY] %>' />
                                                    <tr data-field='<%= ToCoveoFieldName("created") %>' data-caption='<%= Model.Labels[LocalizedStringKeys.CREATED] %>' data-helper='dateTime' />
                                                    <tr data-field='<%= ToCoveoFieldName("parsedupdatedby") %>' data-caption='<%= Model.Labels[LocalizedStringKeys.UPDATED_BY] %>' />
                                                {{ } }}
                                                <tr data-field='<%= ToCoveoFieldName("parsedlanguage") %>' data-caption='<%= Model.Labels[LocalizedStringKeys.LANGUAGE] %>' />
                                                <tr>
                                                    <th class='CoveoCaption'><%= Model.Labels[LocalizedStringKeys.UNIFORM_RESOURCE_IDENTIFIER] %></th>
                                                    <td class='CoveoClickableUri'>
                                                        <a href="{{= clickUri}}">{{= clickUri}}</a>
                                                    </td>
                                                </tr>
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                            </div>
                        </script>
                    </div>
                    <% if (Model.DisplayBottomPager) { %>
                        <div class="CoveoPager" data-number-of-pages="<%= Model.PagerNumberOfPages %>"
                                                data-max-number-of-pages="<%= Model.PagerMaxNumberOfPages %>"
                                                data-enable-navigation-button="<%= Model.EnablePagerNavigationButton %>"></div>
                    <% } %>
                <% } %>
            </div>
        </div>
    </div>
    <script class='result-template' id='CoveoQuickviewTemplate' type='text/underscore'>
        <div class='coveo-quick-view-header'>
            <table class='CoveoFieldTable'>
                <tr data-field='@sysdate' data-caption='Date' data-helper='dateTime' />
                <tr data-field='@sysauthor' data-caption='Author' />
                <tr data-field='@clickuri' data-html-value='true' data-caption='URL' data-helper='anchor' data-helper-options='{text: "{{= clickUri }}", target: "_blank"}'>
            </table>
            <div class='CoveoQuickviewDocument'></div>
        </div>
    </script>
    <script type="text/javascript">
        Coveo.$(function() {
            Coveo.$('#search').coveoForSitecore('init', CoveoForSitecore.componentsOptions);
        });
    </script>
</coveoui:WhenConfigured>
<% if (Model.HasErrors) { %>
    <div class="CoveoServerError">
        <h3><%= Model.Labels[LocalizedStringKeys.FRIENDLY_SEARCH_UNAVAILABLE_TITLE] %></h3>
        <h4><%= Model.Labels[LocalizedStringKeys.FRIENDLY_SEARCH_UNAVAILABLE_DETAIL] %></h4>
    </div>
    <% if (SitecoreContext.IsEditingInPageEditor()) { %>
        <script type="text/javascript">
            Coveo.$(function() {
                Coveo.PageEditorDeferRefresh.triggerUpdate();
            });
        </script>
    <% } %>
<% } %>

What’s Next?

Proceed to reading Overview of CoveoFacet.ascx.