3
\$\begingroup\$

This is front end code for a search feature that searches for characters. It uses the users search query to return an array of matching characters, which then gets displayed in a search list for the user to view and select. Please let me know how I can simplify or improve this code. Thanks for your time!

//Champ Search
const $searchInput = $('.search__input');
const $searchChampList = $('.search__champ-list');
const highlightedChamp = '.search__champ-list-item_highlighted';
let queryString;
let typingTimer;

const doSearch = () => {
    //Assign querystring to the inputs text value.
    queryString = $searchInput.val();
    //Empty the search list when a new search is initiated.
    $searchChampList.empty();
    //Ajax call to end point using the stored querystring.
    api.get(`${siteUrl}api/search?input=${queryString}`, (res) => {
        //Append a list item for each object in the returned array.
        $.each(res, (index, value) => {
            $searchChampList.append(
                `<a class="search__champ-link" href="/champ/${utils.formatChampName(value.name)}">
                    <li class="search__champ-list-item">
                        <div class="search__champ-img-wrapper">
                            <img class="search__champ-img" src="/public/img/${utils.formatChampName(value.name)}.jpg"></img>
                        </div>
                        <div class="search__champ-name">${value.name}</div>
                    </li>
                </a>`
            );
            //Add the highlighted class to the first item in the search list.
            $('.search__champ-link:first').addClass('search__champ-list-item_highlighted');
        });
    });
}

//Debounce Search Function
const debounceSearch = (debounceTime) => {
    typingTimer = setTimeout(doSearch, debounceTime);
}

$searchInput.keyup(function(key) {
    const inputValue = $(this).val();

    const keyPressed = {
        backspace: key.keyCode == 8,
        enter: key.keyCode == 13,
        down: key.keyCode == 40,
        up:  key.keyCode == 38,
        alphabet: key.keyCode >= 65 && key.keyCode <= 90
    }

    //Navigate the search list with down arrow and enter the champs name into the input for feedback.
    const navigateChampList = (direction) => {
        key.preventDefault();
        if (direction === 'down') {
            $(highlightedChamp).next().addClass('search__champ-list-item_highlighted')
            $(highlightedChamp).prev().removeClass('search__champ-list-item_highlighted');
        } else {
            $(highlightedChamp).prev().addClass('search__champ-list-item_highlighted')
            $(highlightedChamp).next().removeClass('search__champ-list-item_highlighted');
        }
        $searchInput.val($(highlightedChamp).find('.search__champ-name').text());
    }

    //Restart the debounce timer everytime the keyup event occurs to prevent the server from being spammed.
    clearTimeout(typingTimer);

    if (inputValue && keyPressed.alphabet || inputValue && keyPressed.backspace) {
        //Start a search when the user stops typing letters (a-z) for a specified amount of time, or, if they erase input.
        debounceSearch(1000);
    } else if (!inputValue) {
        //Empty the search list if user erases everything in the input.
        $searchChampList.empty();
    } else if (inputValue && keyPressed.down) {
        navigateChampList('down');
    } else if (inputValue && keyPressed.up) {
        navigateChampList('up');
    } else if ($searchChampList.children().length >= 1 && keyPressed.enter) {
        //Pressing enter goes to the highlighted champs page.
        window.location.href = $(highlightedChamp).attr('href');
    }
});

//Hide search list when search input loses focus and show the search list if the user clicks on the search input.  
$searchInput.on('focusin focusout', (event) => {
    event.type == 'focusin' ? $searchChampList.fadeIn(300) : event.type == 'focusout' ? $searchChampList.fadeOut(300) : null;
});

let searchVisible = false;
//Toggle visiblity of search input when search button is clicked.
$('.navbar__search-button').click(() => {
    if (!searchVisible) {
        searchVisible = true;
        $('.search').addClass('search_show');
        $('.navbar__search-button-text').hide();
        $('.navbar__search-button-icon').html('<span class="icon-cross navbar__button-icon_cross"></span>');
        setTimeout(() => {
            $searchInput.focus();
        }, 300);
    } else {
        searchVisible = false;
        $('.search').removeClass('search_show');
        $('.navbar__search-button-text').show();
        $('.navbar__search-button-icon').html('<span class="icon-search"></span>');
    }
});
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.