98d6d1e479b2f6d1d61596d8fbcea15ac0012383
hiram
  Tue Feb 3 12:40:07 2026 -0800
bold highlight on the autocomplete menu search results refs #36232

diff --git src/hg/js/utils.js src/hg/js/utils.js
index 4481f6713ec..26aa223a5ec 100644
--- src/hg/js/utils.js
+++ src/hg/js/utils.js
@@ -4788,33 +4788,63 @@
                     // Add a heading each time we see a new category (but not for recents)
                     if (!allRecent && item.category && item.category !== currentCategory) {
                         ul.append("<li class='ui-autocomplete-category'>" +
                                 item.category + "</li>" );
                         currentCategory = item.category;
                     }
                     that._renderItem( ul, item );
                 });
             },
             _renderItem: function(ul, item) {
                 // In order to use HTML markup in the autocomplete, one has to overwrite
                 // autocomplete's _renderItem method using .html instead of .text.
                 // http://forum.jquery.com/topic/using-html-in-autocomplete
                 // Hits to assembly hub top level (not individial db names) have no item label,
                 // so use the value instead
+                var searchTerm = this.term;
+                // remove special characters - the \W means remove anything
+                // that is not: [A-Za-z0-9_] which are 'word' == \w characters
+                // then eliminate runs of white space characters and trim any
+                // white space at the beginning or end of the string
+                var cleanTerm = searchTerm.replace(/\W/g, ' ')
+                                  .replace(/\s+/g, ' ')
+                                  .trim();
+                var label = item.label !== null ? item.label : item.value;
+
+                // Highlight matching search terms with bold tags
+                if (cleanTerm && cleanTerm.length > 0) {
+                    // Split search term into individual words (by whitespace)
+                    var words = cleanTerm.split(/\s+/).filter(function(word) {
+                        return word.length > 0;  // Filter out empty strings
+                    });
+
+                    // Apply bolding for each word separately
+                    words.forEach(function(word) {
+                       // Escape special regex characters in each word
+                       var escapedWord = word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+
+                       // Create case-insensitive regex to find all occurrences
+                       var regex = new RegExp('(' + escapedWord + ')', 'gi');
+
+                       // Replace matches with bolded version (preserves original case)
+                       label = label.replace(regex, '<b>$1</b>');
+                   });
+                }
+                console.log("label:", label);
                 return $("<li></li>")
                     .data("ui-autocomplete-item", item)
-                    .append($("<a></a>").html((item.label !== null ? item.label : item.value)))
+                    .append($("<a></a>").html(label))
                     .appendTo(ul);
             }
         }
     );
     autocompleteCat.init($("[id='"+inputId+"']"), {
         baseUrl: baseUrl !== null ? baseUrl : defaultSearchUrl,
         watermark: watermark,
         onSelect: selectFunction,
         onServerReply: onServerReply !== null ? onServerReply : processFindGenome,
         onError: onError,
         showRecentGenomes: true,
         enterSelectsIdentical: false
     });
 }