2f18a9c643ecf990e9525610fdda0a31620ca530 hiram Fri Aug 30 22:40:54 2024 -0700 first pass at highlighting the match strings refs #32596 diff --git src/hg/js/assemblySearch.js src/hg/js/assemblySearch.js index f6f8332..9258d16 100644 --- src/hg/js/assemblySearch.js +++ src/hg/js/assemblySearch.js @@ -229,59 +229,131 @@ // call with visible true to make visible, false to hide function advancedSearchVisible(visible) { var advancedSearchButton = document.getElementById("advancedSearchButton"); var searchOptions = document.getElementById("advancedSearchOptions"); if (visible) { searchOptions.style.display = "flex"; advancedSearchButton.textContent = "hide advanced search options"; stateObject.advancedSearchVisible = true; } else { searchOptions.style.display = "none"; advancedSearchButton.textContent = "show advanced search options"; stateObject.advancedSearchVisible = false; } } +// Function to highlight words in the result that match the words +// in the queryString. Work through each item of the rowData object, +// for each string, find out if it matches any of the words in the +// queryString. This is tricky, there are extra characters besides +// just [a-zA-Z] that are getting in the way of these matches, where +// the MySQL could match, for example: checking: +// 'HG02257' =? '(HG02257.pat' +// 'HG02257' =? 'HG02257.alt.pat.f1_v2' +// doesn't match here, but MySQL match did + +function highlightMatch(queryString, rowData) { + // fixup the queryString words to get rid of the special characters + var words = queryString.split(/\s+/); + var wholeWord = []; // going to be words that match completely + var prefix = []; // going to be words that match prefix + for (let word of words) { + var noPrefix = word.replace(/^[-+]/, ''); // remove + - beginning + if (noPrefix.endsWith("*")) { + prefix.push(noPrefix.replace(/\*$/, '')); + } else { + wholeWord.push(noPrefix); + } + } + if (wholeWord.length > 0) { + for (let word of wholeWord) { + for (let key in rowData) { + if (rowData.hasOwnProperty(key)) { + if (typeof rowData[key] === 'string') { + let value = rowData[key]; + let subWords = value.split(/\s+/); + let newString = "" + for (let subWord of subWords) { + if ( word.toLowerCase() === subWord.toLowerCase() ) { + newString += " <span class='highlight'>" + subWord + "</span>"; + } else { + newString += " " + subWord; + } + } + newString = newString.trim(); + if (newString !== rowData[key]) + rowData[key] = newString; + } + } + } + } + } + if (prefix.length > 0) { + for (let word of prefix) { + for (let key in rowData) { + if (rowData.hasOwnProperty(key)) { + if (typeof rowData[key] === 'string') { + let value = rowData[key]; + let subWords = value.split(/\s+/); + let newString = "" + for (let subWord of subWords) { + if ( subWord.toLowerCase().startsWith(word.toLowerCase())) { + newString += " <span class='highlight'>" + subWord + "</span>"; + } else { + newString += " " + subWord; + } + } + newString = newString.trim(); + if (newString !== rowData[key]) + rowData[key] = newString; + } + } + } + } + } +} + // Function to generate the table and extra information function populateTableAndInfo(jsonData) { var tableHeader = document.getElementById('tableHeader'); var tableBody = document.getElementById('tableBody'); var metaData = document.getElementById('metaData'); document.getElementById('resultCounts').innerHTML = ""; document.getElementById('elapsedTime').innerHTML = "0"; // Clear existing table content tableHeader.innerHTML = ''; tableBody.innerHTML = ''; metaData.innerHTML = ''; // Extract the genomic entries and the extra info var genomicEntries = {}; var extraInfo = {}; for (var key in jsonData) { if (jsonData[key].scientificName) { genomicEntries[key] = jsonData[key]; } else { extraInfo[key] = jsonData[key]; } } headerRefresh(tableHeader); var count = 0; for (var id in genomicEntries) { + highlightMatch(extraInfo.q, genomicEntries[id]); var dataRow = '<tr>'; var browserUrl = id; var asmInfoUrl = id; if (genomicEntries[id].browserExists) { if (id.startsWith("GC")) { browserUrl = "<a href='/h/" + id + "?position=lastDbPos' target=_blank>view</a>"; asmInfoUrl = "<a href='https://www.ncbi.nlm.nih.gov/assembly/" + id + "' target=_blank>" + id + "</a>"; } else { browserUrl = "<a href='/cgi-bin/hgTracks?db=" + id + "' target=_blank>view</a>"; asmInfoUrl = "<a href='https://hgdownload.soe.ucsc.edu/goldenPath/" + id + "/bigZips/' target=_blank>" + id + "</a>"; } dataRow += "<th>" + browserUrl + "</th>"; } else { dataRow += "<th><button type=button' onclick='asmOpenModal(this)' name=" + id + "'>request</button></th>"; }