Events

This is for:

Developer

You can take advantage of the Coveo JavaScript Search Framework event system to interact with the framework using external, event-driven code. There are two broad categories of events you can attach handlers to: global events and component events.

Base assumptions

<link rel="stylesheet" href="./css/CoveoFullSearchNewDesign.css"/>
<script src="js/CoveoJsSearch.js"></script>
<script src="js/templates/templatesNew.js"></script>

The examples also assume that the id attribute of the root element of your search interface is search.

Attaching event handlers

The JavaScript Search Framework triggers regular DOM events. You can attach handlers to these events just as you would with “standard” events (for example, DOMContentLoaded, click, etc.).

Register your Framework event handlers on the root HTML element of your search interface. Some components trigger events on their own HTML element, but since these events bubble up, handlers registered on the root element can catch them as well.

Always register the Framework event handlers before the init call of your search interface.

The following code excerpt registers a buildingQuery event handler on the root HTML element of your search interface.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();

  root = document.querySelector("#search");
  Coveo.$$(root).on("buildingQuery", function(e, args) {
    // Some code to execute when the queryBuilder has just been instantiated...
  });

  Coveo.init(root);
});

Different ways to attach event handlers

There are three different ways to register Framework event handlers:

  • Using “pure” JavaScript (document.addEventListener("[eventName]", function(e) { [ ... Code ... ] }));

  • Using the Dom helper class (Coveo.$$(root).on("[eventName]", function(e, args) { [ ... Code ... ] }));

  • Using the Coveo jQuery extension ($(root).on("[eventName]", function(e, args) { [ ... Code ... ] })).

Examples in this article use the on method of the Dom helper class to attach event handlers.

Embedding event handlers

When the JavaScript Search Framework triggers an event, listeners are notified in the order in which they were registered. Any Coveo component that needs to register its own event handlers does so when its constructor function is executed during the init call of the search interface. Therefore, the event handlers that you register before the init call will normally be registered before any Coveo component has a chance to register its own event handlers.

In some specific cases, you may need to ensure that an event handler is registered at a later moment. For example, you might want certain Coveo event handlers to be notified (and executed) before your own. You might also want to ensure that an event handler is only registered when the end user performs a given action (which triggers a specific event) in the search interface. In these situations, you should embed event handlers.

Attaching an embedded event handler:

The following code excerpt registers an embedded buildingQuery event handler on the root HTML element of your search interface.

The buildingQuery handler is embedded within an afterComponentsInitialization handler. This implies that the buildingQuery handler will only be registered when all Coveo components have registered their own event handlers.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();

  root = document.querySelector("#search");

  // This handler will be registered after all components have registered their own handlers.
  Coveo.$$(root).on("afterComponentsInitialization", function() {
    Coveo.$$(root).on("buildingQuery", function(e, args) {
      // Some code to execute when the `queryBuilder` has just been instantiated...
    });
  });

  Coveo.init(root);
});

Global events

Global events have no direct association with any particular component. There are two types of global events in the JavaScript Search Framework: initialization events and query events.

Initialization events

Initialization events are triggered during the execution of the init call of your search interface. Typically, you will attach handlers to these events to alter Coveo components before they’re rendered, or to interact with the state object and the URL before the first query is launched. The initialization events are:

  • beforeInitialization

  • afterComponentsInitialization

  • restoreHistoryState

  • afterInitialization

Event flow

The following diagram displays the sequential flow of initialization events.

Handling initialization events

You must register all initialization event handlers before the init call of your search interface, otherwise they will have no effect.

Handling events in lazy component loading mode

In lazy component loading mode, the init function starts by asynchronously downloading the code of each required component. Downloading a component code chunks is a non-blocking process during which the execution stack processing can resume. Once the code chunk of a certain component has finished downloading, the init function resumes and sequentially calls the constructor function of each future instance of this component. Then, the execution stack processing can resume, and so on until all components have been instantiated.

Therefore, in lazy component loading mode, it’s possible to successfully register initialization event handlers (except for beforeInitialization handlers) after the init call. Such handlers will be registered at some point after the beforeInitialization event, and before the afterComponentsInitialization event. There’s no easy way to tell precisely when the event handler will be registered, though. Because of this, you should avoid registering initialization event handlers after the init call.

In conclusion, you should always handle events in lazy component loading mode precisely as you would in eager component loading mode.

Adding a filter to the query:

The following code excerpt shows how you could attach a handler to the afterInitialization event to specify a hidden query (hq) in the state object.

In this example, an advanced expression is added to the query. It requires results to be English PDF files that contain the keyword Coveo (see Query syntax).

document.addEventListener("DOMContentLoaded", function () {
  Coveo.SearchEndpoint.configureSampleEndpointV2();
 
  var root = document.querySelector("#search");
 
  Coveo.$$(root).on("afterInitialization", function() {
    Coveo.state(root, "hq", "(@filetype==pdf) (@language==English) (Coveo)");
  });
 
  Coveo.init(root);
});

Code samples

Modifying search interface options

The following code excerpt shows how you could use a beforeInitialization event handler to modify a set of SearchInterface options when a specific condition is met.

In this example, when the end user accesses the search page from a mobile device, the query result excerpt length is shortened and a special query pipeline is applied.

The userIsOnMobileDevice function isn’t implemented in this code sample. To try it, you must provide your own implementation or ensure that the function returns an arbitrary Boolean value.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();
 
  /**
   * Indicates whether the end user is on a mobile device.
   *
   * @returns {boolean} `true` if the end user is on a mobile device; `false` otherwise.
   */
  var userIsOnMobileDevice = function() {
    // ... Implementation ...
  };
 
  /**
   * Sets the `excerptLength` and `pipeline` options of the `SearchInterface` to some arbitrary "mobile" values.
   *
   * @param rootElement The root element of the search interface.
   */
  var setMobileOptionValues = function(rootElement) {
    rootElement.setAttribute("data-excerpt-length", "100");
    rootElement.setAttribute("pipeline", "mobileQueryPipeline");
  };
 
  root = document.querySelector("#search");
 
  Coveo.$$(root).on("beforeInitialization", function() {
    if (userIsOnMobileDevice()) {
      setMobileOptionValues(root);
    }
  });
 
  Coveo.init(root);
});
Selecting a tab and facet values

This example assumes that you include the following markup in your search page:

[ ... ]
 
<body id="search" data-design="new">
  <div class="coveo-tab-section">
    <a class="CoveoTab" data-id="All" data-caption="All Content"></a>
    <a class="CoveoTab" data-id="Messages" data-caption="Messages Only" data-constant="true" data-expression="@objecttype==Message"></a>
  </div>
 
  [ ... ]
 
  <div class="coveo-main-section">
    <div class="coveo-facet-column">
      <div class="CoveoFacet" data-title="Year" data-field="@year" data-tab="All,Messages"></div>
      <div class="CoveoFacet" data-title="Month" data-field="@month" data-tab="All,Messages"></div>
  </div>
 
  [ ... ]
</body>

The following code excerpt shows how you could dynamically interact with the state object and with component instances using an afterInitialization event handler.

In this example, when the search page loads, the Messages tab is automatically selected. Then, in the Year facet, the current year is selected. Finally, in the Months facet, the current month and two preceding months are selected. These selections are made before the initial query (assuming the autoTriggerQuery option of the SearchInterface is set to true), and don’t themselves trigger new queries; they simply serve as additional “filters” for the initial query.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();
 
  /**
   * Selects the **Messages** tab by modifying the `state` object.
   *
   * @param rootElement The root element of the search interface.
   */
  var selectMessagesTab = function(rootElement) {
    if (Coveo.$$(document).find(".CoveoTab[data-id='Messages']") !== null) {
      Coveo.state(rootElement, "t", "Messages");
    }
  };
 
  /**
   * Selects the current year value in the **Year** facet instance.
   */
  var selectCurrentYearFacetValue = function() {
    var yearFacetInstance = Coveo.get(Coveo.$$(document).find(".CoveoFacet[data-title='Year']"));
    if (yearFacetInstance !== null) {
      var thisYear = new Date().getFullYear().toString();
      yearFacetInstance.selectValue(thisYear);
    }
  };
 
  /**
   * Selects values corresponding to this month and the two previous months in the **Months** facet instance.
   */
  var selectRecentMonths = function() {
    var monthFacetInstance = Coveo.get(Coveo.$$(document).find(".CoveoFacet[data-title='Month']"));
    if (monthFacetInstance !== null) {
      var thisMonth = new Date().getMonth();
      for (var i=thisMonth-2; i <= thisMonth; i++) {
        monthFacetInstance.selectValue("0" + i.toString());
      }
    }
  };
 
  var root = document.querySelector("#search");
 
  Coveo.$$(root).on("afterInitialization", function() {
    selectMessagesTab(root);
    selectCurrentYearFacetValue();
    selectRecentMonths();
  });
 
  Coveo.init(root);
});

Query events

Query events are triggered during the execution of a search request to the Coveo Search API. Typically, you will attach handlers to those events to:

  • Cancel the query;

  • Alter the appearance or behavior of a component before, during, or after the query;

  • Modify the outgoing query and the incoming result set;

  • Handle query errors and result sets that contain no results;

  • Alter the way the query results are rendered.

The query events are:

  • newQuery

  • buildingQuery

  • doneBuildingQuery

  • duringQuery / duringFetchMoreQuery

  • queryError

  • preprocessResults / preprocessMoreResults

  • noResults

  • querySuccess / fetchMoreSuccess

  • deferredQuerySuccess

Query event arguments

All query event handlers receive a certain object as an argument. For example, all doneBuildingQuery event handlers receive an IDoneBuildingQueryEventArgs object as an argument. You can get or set the attributes of this object to interact with the query or with the results.

See the reference documentation of each individual query event for information about the object its handlers receive as an argument.

Event flow

The following diagram displays the sequential flow of query events.

Additional query events

This diagram doesn’t include the duringFetchMoreQuery, preprocessMoreResults, and fetchMoreSuccess events.

These events are equivalent to the duringQuery, preprocessResults, and querySuccess events respectively, except they’re triggered when certain components need to perform their own queries to fetch additional results (for example, for infinite scroll, folding, etc.).

Handling query events

In theory, you can register query event handlers either before or after the init call of your search interface.

Registering a query event handler before the init call implies that the handler will be registered before any component constructor functions are called. Registering the same handler after the init call means that it will be registered after all of the component constructors have been executed. This is equivalent to embedding the handler inside an afterInitialization handler.

You should always register query event handlers before the init call. You can embed event handlers to enforce a sequential registration flow, when necessary.

Code samples

Modifying the appearance of an element

This example assumes that you include the following markup in your search page:

[ ... ]
 
<style>
  .currently-hidden {
    display : none;
  }
</style>
 
<body id="search" class="CoveoSearchInterface" data-design="new">
  <div id="loading-status">
    <div id="query-done">Done!</div>
    <div id="query-error" class="currently-hidden">Error.</div>
    <div id="query-loading" class="currently-hidden">Loading...</div>
  </div>
 
  [ ... ]
 
</body>

Depending on the current state of the query, the following code excerpts show how you could use newQuery, queryError, and querySuccess event handlers to modify the appearance of an HTML element.

In this example, when a new query is triggered, the element displays the Loading. text. When the query successfully returns (whether it actually contains results), it displays the Done! text. If the query fails (because of a search endpoint configuration error, for example), it displays the Error. text.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();
 
  var hiddenClass = "currently-hidden";
 
  /**
   * Indicates whether the target HTML element is currently hidden by verifying whether it has the corresponding 
   * CSS class.
   * 
   * @param element The target HTML element.
   * 
   * @returns {boolean} `true` if the HTML element is currently hidden; `false` otherwise.
   */
  var isCurrentlyHidden = function(element) {
    return element.classList.contains(hiddenClass);
  };
 
  /**
   * Toggles the visibility of the target HTML element by adding or removing the corresponding CSS class.
   * 
   * @param element The target HTML element.
   */
  var toggleElementVisibility = function(element) {
    if (isCurrentlyHidden(element)) {
      element.classList.remove(hiddenClass);
    }
    else {
      element.classList.add(hiddenClass);
    }
  };
 
  root = document.querySelector("#search");
 
  Coveo.$$(root).on("newQuery", function(e, args) {
    // If the previous query returned an error, hide the `query-error` element when launching the new query.
    var error = document.querySelector("#query-error");
    if (!isCurrentlyHidden(error)) {
      toggleElementVisibility(error);
    }
  
    toggleElementVisibility(document.querySelector("#query-done"));
    toggleElementVisibility(document.querySelector("#query-loading"));
  });
 
  Coveo.$$(root).on("queryError", function(e, args) {
    toggleElementVisibility(document.querySelector("#query-error"));
    toggleElementVisibility(document.querySelector("#query-loading"));
  });
 
  Coveo.$$(root).on("querySuccess", function(e, args) {
    toggleElementVisibility(document.querySelector("#query-loading"));
    toggleElementVisibility(document.querySelector("#query-done"));
  });
 
  Coveo.init(root);
});

If you run this code sample, you should see something like this at the top of your search page:

Toggling the query cache

This example assumes that you include the following markup in your search page:

[ ... ] 
 
<body id="search" class="CoveoSearchInterface" data-design="new">
 
  [ ... ]
 
  <div class="coveo-search-section">
 
    [ ... ]
 
    <div class="CoveoSearchbox"></div>
    <input id="disable-query-cache-checkbox" type="checkbox"/>
    <label for="disable-query-cache-checkbox">Disable Query Cache</label>
  <div>
</body>

By default, the Search API tries to return cached query results when a search request is triggered. This means that sending the same search request again and again over a brief period of time doesn’t necessarily trigger many complete queries to the Coveo index, since the results are already available (and likely still up-to-date) in the cache.

The following code excerpt shows how you could use a buildingQuery event handler to allow the end user to activate or deactivate query cache in your search page by interacting with a checkbox input.

In this example, the checkbox state is saved in local storage so that when the end user reloads the search page, the previously selected state is automatically reapplied.

Since it’s embedded within an afterInitialization handler, this buildingQuery handler will only be registered after each Coveo component has registered its own event handlers, and the hash part of the URL has been applied to the state object. Consequently, this handler will be notified last when the buildingQuery event is triggered. This ensures that no internal Coveo event handler can “override” this handler.

document.addEventListener("DOMContentLoaded", function () {
  Coveo.SearchEndpoint.configureSampleEndpointV2();

  /**
   * Gets the `enableQueryCache.isEnabled` value if it exists in local storage.
   *
   * @returns {boolean|*} The `isEnabled` value if available; `null` otherwise.
   */
  var getEnableQueryCacheValue = function() {
    return JSON.parse(localStorage.getItem("enableQueryCache")).isEnabled;
  };

  /**
   * Attaches a handler to the **Disable Query Cache** checkbox so that changing its state also changes the
   * `enableQueryCache.isEnabled` value in local storage. Automatically selects the checkbox if the
   * `enableQueryCache.isEnabled` value is currently set to `false`.
   */
  var configureQueryCacheCheckbox = function() {
    var disableCacheCheckbox = document.querySelector("#disable-query-cache-checkbox");
    disableCacheCheckbox.addEventListener("change", function () {
      localStorage.setItem("enableQueryCache", JSON.stringify({"isEnabled": !this.checked}));
    });

    disableCacheCheckbox.checked = getEnableQueryCacheValue() === false;
  };

  var root = document.querySelector("#search");

  Coveo.$$(root).on("afterInitialization", function() {
    configureQueryCacheCheckbox();

    // When instantiating the `queryBuilder`, set the maximum age of cached results according to the
    // `enableQueryCache.isEnabled` value in local storage. Use the default `maximumAge` parameter value (which is
    // equivalent to 30 minutes) if `enableQueryCache.isEnabled` is either `true` or undefined.
    Coveo.$$(root).on("buildingQuery", function(e, args) {
      args.queryBuilder.maximumAge = getEnableQueryCacheValue() === false ? 0 : null;
    });
  });

  Coveo.init(root);
});

If you run this code sample, you should see a Disable Query Cache checkbox input in your search page:

If you leave the box unchecked and launch a query whose results are already available in cache (the initial query, for example), you should see something like this when you inspect the query response:

If you check the box and try sending the same query again, the response should now contain something similar to this:

Replacing special characters in the query

The query syntax allows the end user to enter complex query expressions in the query box. The enableQuerySyntax option of your Searchbox component lets you enable or disable the use of query syntax in your search page.

In certain cases, you might need to disable some of the query syntax features (for example, setting the enableQuerySyntax option to true, but ignoring certain special characters which could otherwise be interpreted as Coveo query syntax, such as $). While the Coveo Search API offers no “clean” way to do this in the query pipeline, it’s possible (although not ideal) to modify the queryBuilder to artificially achieve this kind of query syntax granularity.

Query syntax and the JavaScript Search Framework v2.x

In v2.x of the Framework, enableQuerySyntax defaults to false, but it can be overridden by end-user preferences.

The following code excerpt shows how you could use a doneBuildingQuery event handler to remove certain special characters from the basic query expression (q) before sending it to the Coveo Search API.

In this example, the $ character is replaced with the empty string.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();

  root = document.querySelector("#search");
  Coveo.$$(root).on("doneBuildingQuery", function(e, args) {
    args.queryBuilder.expression.parts[0] = args.queryBuilder.expression.parts[0].replace(/\$/g, "");
  });

  Coveo.init(root);
});
Querying commerce catalog content

The following code excerpt shows you how to query your commerce catalog content.

document.addEventListener("DOMContentLoaded", () => {
 
  // ...
 
  const root = document.getElementById("search");
  Coveo.$$(root).on("buildingQuery", (e, args) => {
    args.queryBuilder.commerce = { catalogId: "<MY_CATALOG_NAME>" };
  });
 
  // ...
 
  Coveo.init(root);
});

Where you would replace <MY_CATALOG_NAME> with the name of your catalog entity.

Modifying the query results

The following code excerpt shows how you could use a preprocessResults event handler to modify the results before the ResultList component renders them.

In this example, the handler converts the title of all results whose objecttype field value is User to uppercase.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();

  root = document.querySelector("#search");

  Coveo.$$(root).on("preprocessResults", function(e, args) {
    args.results.results.forEach(function(result) {
      if (result.raw && result.raw.objecttype === "User") {
        result.title = result.title.toUpperCase();
      }
    });
  });

  Coveo.init(root);
});

Client-side manipulations of query results such as this one are “quick and dirty” ways to fix problems and inconsistencies which actually reside within the index itself. If you frequently find yourself resorting to this kind of result manipulation in your search page, you should probably consider making adjustments in the index (for example, adding or modifying pre- and post-indexing pipeline extensions, field mapping rules, etc.).

Displaying query result information

The following code excerpt shows how you could use a querySuccess event handler to interact with the current page of query results.

In this example, when the query successfully returns, the handler renders a list containing the number of occurrences of each source type present on the current page of results.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();
 
  root = document.querySelector("#search");
 
  Coveo.$$(root).on("querySuccess", function(e, args) {
    
    /**
     * Removes the `source-type-summary` structure from the search page.
     */
    var cleanUp = function() {
      var sourceTypeSummary = document.querySelector("#source-type-summary");
      if (sourceTypeSummary !== null) {
        sourceTypeSummary.parentNode.removeChild(sourceTypeSummary);
      }
    };
 
    /**
     * Counts the number of occurrences of each source type on the current page of results.
     *
     * @returns {{}} A key-value set where each key is the name of a source type and each value is its
     * corresponding number of occurrences on the current page of results.
     */
    var getSourceOccurrences = function() {
      var sources = {};
      for (var i = 0; i < args.results.results.length; i++) {
        var currentResult = args.results.results[i];
        var currentSource = currentResult.raw.source;
        if (sources[currentSource]) {
          sources[currentSource] += 1;
        }
        else {
          sources[currentSource] = 1;
        }
      }
      return sources;
    };
 
    /**
     * Creates the `source-type-summary` HTML structure, which contains an unordered list of each source type
     * present on the current page of results and its corresponding number of occurrences. Prepends this node to
     * the `coveo-results-column` element if it exists, or to the root element of the search interface otherwise.
     */
    var createSourceTypeSummary = function() {
      var sources = getSourceOccurrences();
      if (sources instanceof Object) {
        var sourceTypeSummary = document.createElement("div");
        sourceTypeSummary.setAttribute("id", "source-type-summary");
        var sourceTypeSummaryContent = document.createTextNode("Source type summary for this page: ");
        sourceTypeSummary.appendChild(sourceTypeSummaryContent);
        var sourceTypeList = document.createElement("ul");
        for (var key in sources) {
          var sourceTypeListItem = document.createElement("li");
          var sourceTypeListItemContent = document.createTextNode(" " + key + ": " + sources[key]);
          sourceTypeListItem.appendChild(sourceTypeListItemContent);
          sourceTypeList.appendChild(sourceTypeListItem);
        }
        sourceTypeSummary.appendChild(sourceTypeList);
 
        var resultsColumn = document.querySelector(".coveo-results-column");
        if (resultsColumn) {
          resultsColumn.insertBefore(sourceTypeSummary, resultsColumn.firstChild);
        }
        else {
          root.insertBefore(sourceTypeSummary, root.firstChild);
        }
      }
    };
 
    // Remove the `source-type-summary` element if it already exists in the page to avoid carrying the existing
    // structure over when displaying another page of results.
    cleanUp();
 
    createSourceTypeSummary();
  });
 
  Coveo.init(root);
});

If you run this code sample, you should see the following at the top of your result list:

Component events

Component events are usually triggered by specific components. The following JavaScript Search Framework components have their own sets of events:

This article only discusses the most commonly used ResultList events, and the changeAnalyticsCustomData Analytics event.

See the reference documentation of the aforementioned components for more information on their respective events.

Analytics events

changeAnalyticsCustomData

The changeAnalyticsCustomData event is triggered right before sending the custom data and metadata of an analytics event to the Coveo Analytics REST service. All changeAnalyticsCustomData event handlers receive ChangeAnalyticsCustomDataEventArgs as an argument, which extends the IChangeableAnalyticsDataObject interface. You can attach handlers to this event to read and modify the information that’s about to be sent to the Analytics REST service.

Argument object
Name
Description
type The type of event that's being logged. Can be SearchEvent, ClickEvent, or CustomEvent.
metaObject

The custom event metadata. All key-value pairs included in this object will be sent as custom metadata to the Coveo Analytics service, and can then be used to create custom dimensions in analytics reports.

language

The language of the search interface.

By default, this value is populated by the localization file used by the search interface.

originLevel1

The high-level origin of the analytics event. Typically, this is the name of the current search hub, or a name which can uniquely identify the search page.

Default value is default.

originLevel2

The mid-level origin of the analytics event.

By default, this value is populated by the currently selected tab.

originLevel3

The low level origin of the analytics event. Typically, this is the HTTP identifier of the page from which the event originates.

By default, this property is left empty.

resultData

(ClickEvent only)

When the analytics event category is ClickEvents, the event object contains an additional attribute.

You can take advantage of the resultData object to push more analytics data from the results that have been clicked.

You want to include the value of the product field for the clicked result in the pushed analytics data:

Coveo.$$(root).on('changeAnalyticsCustomData', function(e, args) {
    args.metaObject.product = args.resultData.raw.product;
});

ResultList events

The ResultList component can trigger several events. Two of these events are especially useful: newResultDisplayed (singular: “result”) and newResultsDisplayed (plural: “results”). You can attach handlers to these events to alter the appearance of rendered query results.

ResultList events versus result templates

Usually, you can rely on the result template evaluation mechanism rather than attaching your own handlers to the newResultDisplayed or newResultsDisplayed events.

Event flow

The following diagram displays the part of the sequential query event flow where the ResultList component triggers the newResultDisplayed and newResultsDisplayed events.

In summary, the ResultList component triggers the newResultDisplayed event each time it renders a result. However, it triggers the newResultsDisplayed event only once, when all results have been rendered.

A word of caution about this diagram

Other querySuccess event handlers may have been registered before (and after) the ResultList querySuccess event handler.

This means that in the previous diagram, the querySuccess event could trigger other processes, which would either be executed before or after the ResultList rendering process, depending on when their corresponding event listeners were registered.

Handling the newResultDisplayed event

All newResultDisplayed event handlers receive an IDisplayedNewResultEventArgs as an argument. This object includes the current IQueryResult (the result object) as well as the current HTMLElement (the item object). Typically, you will want to get values from the result object and set values in the item object to alter the rendering of the results.

As usual, you should always register your newResultDisplayed event handlers before the init call of your search interface.

newResultDisplayed versus newResultsDisplayed

You can accomplish the exact same thing using either a newResultDisplayed or a newResultsDisplayed event handler. However the newResultDisplayed event is often slightly easier and cleaner, since it doesn’t require you to write a loop when you need to iterate through each element in the result list.

Code sample

Modifying the rendering of each result:

The following code excerpt shows how you could use a newResultDisplayed event handler to modify the appearance of each result in the result list.

In this example, the handler modifies the HTML of each rendered ResultLink component so that it displays the name of the source before the result title.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();

  root = document.querySelector("#search");

  Coveo.$$(root).on("newResultDisplayed", function(e, args) {
    // Add the source type at the beginning of the result link text.
    var formattedTitle = args.result.Title = args.result.raw.source + " - " + args.result.Title;
    args.item.querySelectorAll("div.coveo-result-cell > a.CoveoResultLink").forEach(function(element) {
      element.innerHTML = formattedTitle
    });
  });

  Coveo.init(root);
});

Handling the newResultsDisplayed event

All newResultsDisplayed event handlers receive a recursive representation (tree) of the source (the srcElement object) and target (the target object) HTML elements of the ResultList. Typically, you will want to get values from the srcElement object and set values in the target object to alter the rendering of the results.

As usual, you should always register your newResultsDisplayed event handlers before the init call of your search interface.

Code sample

Modifying the rendering of each result:

The following code excerpt shows how you could use a newResultsDisplayed event handler to modify the appearance of each result in the result list.

In this example, the handler modifies the HTML of each rendered ResultLink component so that it displays the name of the source before the result title.

document.addEventListener("DOMContentLoaded", function() {
  Coveo.SearchEndpoint.configureSampleEndpointV2();
 
  root = document.querySelector("#search");
 
  Coveo.$$(root).on("newResultsDisplayed", function(e, args) {
    // Add the source type at the beginning of the result link text.
    for (var i = 0; i < e.target.lastChild.children.length; i++) {
      var currentResult = e.target.lastChild.children[i];
      var formattedTitle = currentResult.CoveoResult.raw.source + " - " + currentResult.CoveoResult.Title;
      currentResult.children[0].querySelectorAll("div.coveo-result-cell > a.CoveoResultLink").forEach(function(element) {
        element.innerHTML = formattedTitle;
      });
    }
  });
 
  Coveo.init(root);
});