Step 1 - Basic Configuration, Options, and Markup

In this step, you will first review each individual section of the index.html file to get a better understanding of how the Coveo JavaScript Search UI is configured.

Next, you will find answers to some of the most frequently asked questions about component options.

Finally, a few exercises will help you get more familiar with the most basic concepts behind the Coveo JavaScript Search Framework.

If you want to actively follow the steps of this tutorial, you should open the ./bin/index.html file in the text editor or IDE of your choice.

Header Resources

The index.html file header contains all required resources for the basic framework to operate, as well as a few extra JavaScript and CSS files that will be used exclusively in this tutorial.

<!-- This is the default CSS offered by Coveo for the UI. -->
<link rel="stylesheet" href="css/CoveoFullSearch.css"/>
<!-- This is some extra CSS used exclusively in this tutorial. -->
<link rel="stylesheet" href="css/coveoextension.css"/>
<!-- This is the JavaScript file that includes the entire framework. -->
<!-- It will populate the "Coveo" namespace in the browser. -->
<!-- Note that it is loading the Lazy version of the framework, not the Eager. -->
<!-- For more information on the differences between both, see https://docs.coveo.com/en/295/javascript-search-framework/lazy-versus-eager-component-loading. -->
<script src="js/CoveoJsSearch.Lazy.js"></script>
<!-- This is an extra JavaScript file used exclusively in this tutorial. -->
<script src="js/coveo.extension.js"></script>
<!-- This is the "default" result template. -->
<!-- It will be used by the UI when no custom template has been specified. -->
<script src="js/templates.js"></script>

Initialization Script

This script initializes a working search interface by first configuring an endpoint (an index) against which to execute queries, and then by targeting a root element under which all search components should be placed.

<script>
  // Wait until all resources have been loaded and page is ready before executing initialization.
  document.addEventListener('DOMContentLoaded', function () {
    // The Coveo JavaScript Search UI comes with a pre-configured public search endpoint
    // (a public index against which to execute queries for demo purposes).
    Coveo.SearchEndpoint.configureSampleEndpointV2();
    // Initialize the UI by targeting a root element.
    Coveo.init(document.body);
  })
</script>

Some additional information about the initialization script follows.

  • The sample endpoint is a public Coveo Cloud endpoint for which we use a hardcoded API key. It comes fully configured with different source types. You will learn how to create and use your own search endpoint later in this tutorial (see Step 5 - Create Your Own Search Endpoint With Authentication - API Key and Search Tokens).

    A search endpoint is a REST Search API against which the UI will execute queries and receive JSON results (see REST Search API Home).

    In the vast majority of cases, this search endpoint will be a Coveo owned machine available on the cloud at https://cloudplatform.coveo.com/rest/search (Coveo Cloud V1) or https://platform.cloud.coveo.com/rest/search (Coveo Cloud V2).

    The search endpoint can also be an on-premises Search API (installed locally in your own infrastructure), in which case the same logic applies, although different authentication methods are available (see Using the JavaScript Search Framework With the On-Premises Search API).

    This tutorial will focus on using a cloud endpoint, as it is the most frequent use case.

  • The Coveo.init method will target an element and scan for all available components. Each recognized component will then instantiate itself (i.e., its constructor function will be executed).

    Components are the base unit of your search interface. A component is typically responsible for a single concern or user-facing feature. Available components include the Searchbox, the ResultList, the Pager, etc.

    Each component can be added once or multiple times, or removed from your search interface.

    A list of all available components can be found on the reference documentation site on GitHub (see Coveo JavaScript Search Framework - Reference Documentation).

    Some components are straightforward and can easily be mapped to visual widgets in the interface. Some others are more subtle or advanced. You should not worry about understanding all available components for now.

Configuration Through Markup

The configuration of each component is done through the HTML markup.

<!-- Each DOM element with a class starting with "Coveo" (uppercase) will instantiate a component. -->
<body id="search" class='CoveoSearchInterface'>
<!-- Each DOM element with a class starting with "coveo-" (lowercase) is for CSS or alignment purpose only. -->
<div class='coveo-search-section'>
    <!-- Note that any Coveo component can be removed (or added); none is actually required for the page to load. -->
    <div class="CoveoSearchbox"></div>
</div>
<!-- The "data-" attributes of each component allow you to set options for a specific instance of that component. -->
<div class="CoveoFacet" data-title="Author" data-field="@author" data-tab="All"></div>
<div class="CoveoFacet" data-title="Year" data-field="@year" data-tab="All"></div>
</body>

Some additional information about configuration through the HTML markup follows.

  • Each time you see a DOM element with a class starting with Coveo (with a capital “C”), you can assume that this element will instantiate a component. You can be almost certain that after the Coveo.init function has been called, the DOM element will be modified and will generate a different markup.
  • Each time you see a DOM element with a class starting with coveo- (lowercase “c”), you can assume that this element will not instantiate a component. It will only be used by the base CSS file, which is included in the Coveo JavaScript Search UI.
  • If you want to change the position of any component within your page, you will most likely have to move the corresponding DOM elements.
  • The data- attributes you see in some components are options for a specific instance of this component.

If you understand these concepts, you should also be able to roughly understand what happens when the Coveo.init method is executed:

These steps describe how Lazy loading works. To learn how Eager loading works, see Lazy Versus Eager Component Loading.

  1. Starting from the root element specified in the Coveo.init call, the framework will scan the DOM for any DOM element that matches a well-known CSS class (e.g., CoveoFacet → instantiate a Facet component, CoveoSearchbox → instantiate a Searchbox component, etc.) and download its appropriate code.
  2. After having downloaded the code of a component, its constructor function is called. This is done asynchronously for each component detected on your page.
  3. Once a component has been initialized, the framework parses its data- attributes, and sets those option values to the component.
  4. Each component will bind event handlers in their constructor function to interact with the event system of the framework (see Step 3 - Understanding the Event System).

More Information on Options

This section contains answers to some of the most frequently asked questions about component options.

  • Q: Where can I find a list of all possible options for each component?

    • A: Reference documentation for all components is available on GitHub (see Coveo JavaScript Search Framework - Reference Documentation). You should not try to understand all possible options for now. However, you should know that the reference documentation will prove to be an invaluable source of information when you are looking for possible features to implement.

      Facet is one of the most complex components and it contains many different options which are all properly explained in the reference documentation.

  • Q: How can an option name from the reference documentation be applied to a markup configuration?

    • A: The syntax is always the same. First, you have to add data- before the option name. Then, for each capital letter in the option name, add a dash ( - ) before the letter and lowercase the capital.

      The enableFacetSearch option of the Facet component becomes data-enable-facet-search in the markup.

  • Q: How can I know the possible values for a specific option?

    • A: In the reference documentation, you can find which type is accepted by any given option. The following table shows the possible values for each type. It also displays examples of option component markup configuration.

      Type Option Component Example Possible Values Markup Configuration Example
      boolean enableFacetSearch option of the Facet component true or false data-enable-facet-search="true"
      string title option of the Facet component Any string of characters data-title="foo"
      number numberOfValues option of the Facet component

      Any integer of float number

      No distinction is made between integer and float. You must use your own judgement to determine a reasonable value for any given option.

      data-number-of-values="1"
      Array<T> allowedValues option of the Facet component A comma separated list of values of type T (e.g., an Array<string> contains values of type string) data-allowed-values="foo,bar,baz"
      HTMLElement resultContainer option of the Facet component A CSS selector which allows targeting of a HTML element in the DOM data-result-container-selector="#A_HTML_ID"

Exercises

  • All exercises in this section should be done by modifying the tutorial search page under ./bin/index.html. The exercises should not be done by modifying the original search page under ./pages/index.html.
  • In order to actually see the results in your demo page, you must be running a webpack-dev-server (see Step 0 - Environment Setup).
  1. In the ./bin/index.html file, find the HelloWorld component and remove it. Save your work and reload your demo page at http://localhost:3000. The Hello World message should now be gone from the top of the page.

    Solution

     [ ... ]
     <body id="search" class='CoveoSearchInterface' data-enable-history="true" data-design="new">
       <!-- The following line should be removed. -->
       <div class="CoveoHelloWorld"></div>
       <div class="coveo-tab-section">
         <a class="CoveoTab" data-id="All" data-caption="All Content"></a>
       </div>
     [ ... ]
    
  2. Find the coveo-facet-column and add a new Facet with "Source" as a title and "@source" as a field. Save your work and reload your demo page at http://localhost:3000. A new facet titled Source should appear.

    Solution

     [ ... ]
     <div class="coveo-facet-column">
       <!-- The following line should be added. -->
       <div class="CoveoFacet" data-title="Source" data-field="@source" data-tab="All"></div>
       <div class="CoveoFacet" data-title="Type" data-field="@objecttype" data-tab="All"></div>
       <div class="CoveoFacet" data-title="FileType" data-field="@filetype" data-tab="All"></div>
       <div class="CoveoFacet" data-title="Author" data-field="@author" data-tab="All"></div>
       <div class="CoveoFacet" data-title="Year" data-field="@year" data-tab="All"></div>
       <div class="CoveoFacet" data-title="Month" data-field="@month" data-tab="All"></div>
     </div>
     [ ... ]
    
  3. Modify the Tab component so that its caption becomes "Everything". Save your work and reload your demo page at http://localhost:3000. The tab should now contain a different caption.

    Solution

     [ ... ]
     <div class="coveo-tab-section">
       <!-- The following line should be modified -->
       <a class="CoveoTab" data-id="All" data-caption="Everything"></a>
     </div>
     [ ... ]
    

What’s Next?

You should now proceed to Step 2 - Interacting With the Search Interface and Component Instances.