Gravatar for kevin.bernaerts@amplexor.com

Question by kevin bernaerts, Jun 6, 2014 1:54 PM

Omnibox results not updated when keyword gets appended between REST call and the response

Especially when the backend is slow (because of heavy load for instance) the search query runs behind. And when the keyword is already appended with some extra characters before the results of the first query are returned, the list of results in the omnibox dropdown does not correspond to the keyword at that moment.

For instance:

  • I want to search for "special" so I start to enter "spe".

  • An query gets triggered to the backend with q = spe

  • Because the backend is on heavy load, Coveo.Rest.SearchEndpoint.endpoints["default"].search(query) doesn't return its results immediately.

  • of course I continue typing my keyword: special

  • I'm still waiting for results

  • the query finally returns results but for q = spe

  • I'm confused because I actually entered "special" and not just "spe".

    function buildOmniboxContent(regex) { return findValuesThatMatch(regex); }

    function findValuesThatMatch(q) { try { var builder = new Coveo.Ui.QueryBuilder(); builder.expression.add(q); var query = builder.build(); return Coveo.Rest.SearchEndpoint.endpoints["default"].search(query); } catch(e) { window.console && console.log("Exception caught: " + e.message); } return null; }

    function onPopulateOmniBox(e, populateOmniBoxObject) { var wordToSearch = populateOmniBoxObject.completeQueryExpression.word; var regexToSearch = populateOmniBoxObject.completeQueryExpression.regex;

    if (wordToSearch.length > 0) {
    var searchDeferred;
    var deferred = $.Deferred();
    
    window.console && console.log("wordToSearch: " + wordToSearch);
    searchDeferred = buildOmniboxContent(wordToSearch); // when the backend is slow, by the time it returns a result the keyword might already be different
    

One solution might be to extend the above javascript code with some extra logic which verifies if the initial query is still the same as the one currently in the search box. However, for this I need to know the search box jquery element because there might be multiple omniboxes on the same page. (it's the case, we have one in the header and another one in the middle of the page) So I need the jquery context within the onPopulateOmniBox(e, populateOmniBoxObject) function.

searchDeferred = buildOmniboxContent(wordToSearch);    

while (wordToSearch != KEYWORD_CURRENTLY_IN_SEARCHBOX ) {
    wordToSearch = KEYWORD_CURRENTLY_IN_SEARCHBOX;
    window.console && console.log("wordToSearch: " + wordToSearch);
    searchDeferred = buildOmniboxContent(wordToSearch);
}
1 Reply
Gravatar for olamothe@coveo.com

Answer by olamothe, Jun 6, 2014 3:40 PM

So I need the jquery context within the onPopulateOmniBox(e, populateOmniBoxObject) function.

Are the multiple search box inside the same SearchInterface ? If they are in different interface, then you can use the first argument of the function (e, the JQueryEventObject and the attribute target) to know from which interface it comes from.

Otherwise, you will need to manually check.

You can either use an HTML id for each box and check if the content match the one provided by the populateOmniBoxObject. If yes, then they are the same.

You can also bind a keyup/keydown function on each search box and just have a flag that tell you wich one is currently active.

Also, the omnibox will always wait until you resolve your deferred object. If you see that your query is taking too long, you can always resolve the deferred with undefined , like so :

  if(myQueryIsTakingTooLong){
     deferred.resolve({
       element : undefined
      })
  }

Too long can be arbitrary here : you can use a timer, or just check the difference between the number of letters of your last request and the current keyword inside the search box, whatever you think is best suited for your case.

When you resolve your deferred object with undefined, the omnibox should trigger a new "populateOmniBox" event immediately after and you can begin the loop again to trigger an updated query.

I hope it helps !

Ask a question