16eee40c920d259c10ee345472708d0cc0cc3393 chmalee Tue Mar 3 11:25:23 2026 -0800 Adds an hg.conf defined 'popular' species list to the new search bar as a 'default' list of results upon focus of the search bar. Combines with 'recents' list. Add a chevron next to the search bar so users know the autocomplete has some default options, refs #36232 diff --git src/hg/js/react/lib/SpeciesSearch.jsx src/hg/js/react/lib/SpeciesSearch.jsx index 73cef5c46d9..d6e9847e67f 100644 --- src/hg/js/react/lib/SpeciesSearch.jsx +++ src/hg/js/react/lib/SpeciesSearch.jsx @@ -1,71 +1,96 @@ /** @jsx React.DOM */ /* global ImmutableUpdate, PathUpdate, Icon, Modal, TextInput */ var pt = React.PropTypes; var SpeciesSearch = React.createClass({ // Text input for position or search term, optionally with autocomplete if // props includes geneSuggestTrack, and a PositionPopup (defined below) // for multiple position/search matches. mixins: [PathUpdate, ImmutableUpdate], // update(path + 'position', newValue) called when user changes position // update(path + 'hidePosPopup') called when user clicks to hide popup // update(path + 'positionMatch', matches): user clicks position link in popup // (matches obj is from hgFind) propTypes: { // Immutable.Map { // position: initial value of position input // loading (bool): display spinner next to position input // positionMatches (Immutable.Vector of Maps): multiple search results for popup // Optional className: pt.string, // class(es) to pass to wrapper div org: pt.string, // name of organism currently selected (ex. Human) db: pt.string, // name of database currently selected (ex. hg38) }, // No-op update function for TextInput - we don't want blur to trigger model updates, // only the autocomplete selection should update the model via onSpeciesSelect noOpUpdate: function() {}, onSpeciesSelect: function(selectEle, item) { if (item.disabled || !item.genome) return; selectEle.innerHTML = item.label; this.props.update(this.props.path, item.genome); }, onSearchError: function(jqXHR, textStatus, errorThrown, term) { return [{label: 'No genomes found', value: '', genome: '', disabled: true}]; }, componentDidMount: function() { // If we have a geneSuggest track, set up autocomplete. var inputNode, $input; inputNode = this.refs.input.getDOMNode(); var sel = document.getElementById("genomeLabel"); var boundSel = this.onSpeciesSelect.bind(null, sel); initSpeciesAutoCompleteDropdown(inputNode.id, boundSel, null, null, null, this.onSearchError); + + // Wire up toggle button for the autocomplete dropdown + var toggle = this.refs.toggle && this.refs.toggle.getDOMNode(); + if (toggle) { + var inputId = inputNode.id; + var wasOpen = false; + toggle.addEventListener('mousedown', function() { + var $inp = $('[id=\'' + inputId + '\']'); + wasOpen = $inp.autocompleteCat('widget').is(':visible'); + }); + toggle.addEventListener('click', function() { + var $inp = $('[id=\'' + inputId + '\']'); + if (wasOpen) { + $inp.autocompleteCat('close'); + } else { + $inp.val(''); + $inp.autocompleteCat('search', ''); + $inp.focus(); + } + }); + } }, render: function() { return ( <div className={this.props.className}> <label className="genomeSearchLabelDefault" for="genomeSearch"> Change selected genome: </label> <div className="searchBarAndButton"> <TextInput id='speciesSearchInput' placeholder="Search for any species, genome or assembly name" size={45} ref='input' update={this.noOpUpdate} /> + <button ref='toggle' type='button' className='genomeSearchToggle' + tabIndex='-1' aria-label='Show popular assemblies' + title='Show recent and popular assemblies' + dangerouslySetInnerHTML={{__html: '▼'}} /> <div className="searchCell"> Current Genome: <span id="genomeLabel">{this.props.org + " (" + this.props.db + ")"}</span> </div> </div> </div> ); } }); // SpeciesSearch // Without this, jshint complains that SpeciesSearch is not used. Module system would help. SpeciesSearch = SpeciesSearch;