Tạo ô tìm kiếm nhanh bằng Ajax trong WordPress

Nếu bạn muốn nâng cấp chức năng tìm kiếm trên website WordPress của mình và tạo trải nghiệm tìm kiếm nhanh chóng cho người dùng, bài viết này sẽ hướng dẫn bạn cách thực hiện bằng Ajax.

Tạo ô tìm kiếm nhanh bằng Ajax trong WordPress
Mục lục

HTML

Đầu tiên, bạn cần tạo một form tìm kiếm đơn giản trong HTML. Đoạn mã dưới đây sẽ giúp bạn tạo một ô tìm kiếm cơ bản:

<div class="search-wrapper form-group">
    <input class="form-control search-txt" type="text" placeholder="Tìm kiếm gì đó..." />
    <button type="button" class="search-btn"><i class="glyphicon glyphicon-search"></i></button>
</div>

CSS

Dưới đây là một số style cơ bản để ô tìm kiếm trông đẹp mắt. Bạn có thể tùy chỉnh theo nhu cầu của mình.

.search-wrapper {
	padding: 25px;
	background: #efefef;
	position: relative;
}
.search-txt {
	font-size: 16px;
	padding: 10px;
	height: auto;
}
.search-wrapper .search-btn {
    position: absolute;
    top: 35px;
    right: 35px;
    border: none;
    background: 0 0;
    padding-top: 1px;
    padding-bottom: 0;
    color: #414a51;
}
.search-result {
	width: 100%;
	margin-top: 25px;
}
.search-result ul {
	padding-left: 0;
	list-style: none;
}
li.focus-ing a {
	text-decoration: underline;
}
.lds-ellipsis {
    display: inline-block;
    position: relative;
    width: 80px;
    height: 10px;
}
.lds-ellipsis span {
    position: absolute;
    top: 0;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #d9dbdd;
    animation-timing-function: cubic-bezier(0, 1, 1, 0);
}
.lds-ellipsis span:nth-child(1) {
    left: 8px;
    animation: lds-ellipsis1 0.6s infinite;
}
.lds-ellipsis span:nth-child(2) {
    left: 8px;
    animation: lds-ellipsis2 0.6s infinite;
}
.lds-ellipsis span:nth-child(3) {
    left: 32px;
    animation: lds-ellipsis2 0.6s infinite;
}
.lds-ellipsis span:nth-child(4) {
    left: 56px;
    animation: lds-ellipsis3 0.6s infinite;
}
@keyframes lds-ellipsis1 {
    0% {
        transform: scale(0);
    }
    100% {
        transform: scale(1);
    }
}
@keyframes lds-ellipsis3 {
    0% {
        transform: scale(1);
    }
    100% {
        transform: scale(0);
    }
}
@keyframes lds-ellipsis2 {
    0% {
        transform: translate(0, 0);
    }
    100% {
        transform: translate(24px, 0);
    }
}

CSS có sử dụng bài viết:

PHP

Để xử lý tìm kiếm Ajax, bạn cần thêm phương thức tìm kiếm vào functions.php. Đoạn mã dưới đây sẽ giúp bạn lấy kết quả tìm kiếm từ bài viết và taxonomy (danh mục, series, khóa học).

/**
 * Tìm kiếm bằng Ajax
 */
add_action('wp_ajax_search', 'init_search');
add_action('wp_ajax_nopriv_search', 'init_search');

function init_search() {
    if (!isset($_POST['keyword']) || empty($_POST['keyword'])) {
        wp_send_json_error(['message' => 'Không có từ khóa tìm kiếm.']);
        die();
    }

    $keyword = sanitize_text_field($_POST['keyword']);
    $res = [];

    // Tìm kiếm trong các taxonomy (Danh mục, series, khóa học)
    $term_results = search_in_terms($keyword);
    if ($term_results) {
        $res = array_merge($res, $term_results);
    }

    // Tìm kiếm trong bài viết
    $post_results = search_in_posts($keyword);
    if ($post_results) {
        $res = array_merge($res, $post_results);
    }

    // Gửi kết quả về cho client
    wp_send_json_success($res);
    die();
}

// Tìm kiếm trong các taxonomy
function search_in_terms($keyword) {
    $args = [
        'taxonomy' => ['category', 'series', 'course'],
        'hide_empty' => true,
        'fields' => 'all',
        'name__like' => $keyword,
        'number' => 5
    ];

    $term_query = new WP_Term_Query($args);
    $results = [];

    if (!empty($term_query->terms)) {
        foreach ($term_query->terms as $term) {
            $results[] = [
                'title' => $term->name,
                'link' => get_category_link($term->term_id)
            ];
        }
    }

    return $results;
}

// Tìm kiếm trong các bài viết
function search_in_posts($keyword) {
    $query = new WP_Query([
        'post_type' => ['post', 'glossary', 'lesson'],
        'posts_per_page' => 5,
        'post_status' => 'publish',
        's' => $keyword
    ]);

    $results = [];

    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            $results[] = [
                'title' => get_the_title(),
                'link' => get_the_permalink()
            ];
        }
    }
    wp_reset_postdata();

    return $results;
}

JavaScript

JavaScript sẽ giúp gửi và nhận dữ liệu tìm kiếm từ server mà không cần tải lại trang. Dưới đây là đoạn mã JavaScript giúp bạn thực hiện điều này:

var initAjax = '<?php echo admin_url('admin-ajax.php'); ?>';

$(document).ready(function() {
    var typingTimer;
    var doneTypingInterval = 500; // Thời gian tối đa người dùng cần ngừng gõ trước khi tìm kiếm
    var $input = $('input.search-txt');
    var ctrlDown = false;

    // Sự kiện khi người dùng gõ trên ô input
    $input.on('keyup', function(event) {
        // Xử lý cho điện thoại di động
        if (detectMobile()) {
            clearTimeout(typingTimer);
            typingTimer = setTimeout(function() {
                if ($input.val() !== '' && !$input.hasClass('selecting')) {
                    showLoadingSpinner();
                    searchPost($input.val());
                }
            }, doneTypingInterval * 2); // Tăng thời gian đợi trên mobile
        } else { 
            // Xử lý cho máy tính bàn
            handleDesktopKeyEvents(event);
        }
    });

    // Sự kiện khi người dùng nhấn các phím đặc biệt
    $input.on('keydown', function(event) {
        clearTimeout(typingTimer);
        var keycode = event.keyCode || event.which;

        if (keycode === 17) {
            ctrlDown = true; // Bắt phím Ctrl
        }

        // Di chuyển qua lại giữa các kết quả tìm kiếm bằng phím mũi tên
        handleArrowKeyNavigation(event, keycode);

        if (keycode === 27) { // Bấm Esc để đóng kết quả tìm kiếm
            removeSearchResult();
        }
    });

    function handleDesktopKeyEvents(event) {
        var keycode = event.keyCode || event.which;

        if ((keycode >= 48 && keycode <= 57) || (keycode >= 65 && keycode <= 90) || [13, 32, 46, 8].includes(keycode)) {
            if (ctrlDown && [65, 67].includes(keycode)) {
                return false; // Ngăn chặn Ctrl + A và Ctrl + C
            }

            clearTimeout(typingTimer);
            typingTimer = setTimeout(function() {
                if ($input.val() !== '' && !$input.hasClass('selecting')) {
                    showLoadingSpinner();
                    searchPost($input.val());
                }
            }, doneTypingInterval);
        }

        if (keycode === 13 && $('.search-result ul li.focus-ing').length) {
            window.location = $('.search-result ul li.focus-ing a').attr('href');
        }
    }

    function handleArrowKeyNavigation(event, keycode) {
        if ($('.search-result').length) {
            if (keycode === 38 || keycode === 40) { // Phím mũi tên lên và xuống
                var $focusedItem = $('.search-result ul').find('li.focus-ing');
                var $items = $('.search-result ul li');

                if (keycode === 38) { // Phím mũi tên lên
                    navigateSearchResult($focusedItem.prev(), $items);
                } else if (keycode === 40) { // Phím mũi tên xuống
                    navigateSearchResult($focusedItem.next(), $items);
                }
            } else if (keycode === 36) { // Phím Home
                focusFirstItem();
            } else if (keycode === 35) { // Phím End
                focusLastItem();
            }
        }
    }

    function navigateSearchResult($newItem, $items) {
        if ($newItem.length) {
            $items.removeClass('focus-ing');
            $newItem.addClass('focus-ing');
            $input.val($newItem.text().trim()).addClass('selecting');
        } else {
            $items.removeClass('focus-ing');
            $input.val('').removeClass('selecting');
        }
    }

    function focusFirstItem() {
        var $firstItem = $('.search-result ul li').first();
        if ($firstItem.length) {
            $('.search-result ul li').removeClass('focus-ing');
            $firstItem.addClass('focus-ing');
            $input.val($firstItem.text().trim()).addClass('selecting');
        }
    }

    function focusLastItem() {
        var $lastItem = $('.search-result ul li').last();
        if ($lastItem.length) {
            $('.search-result ul li').removeClass('focus-ing');
            $lastItem.addClass('focus-ing');
            $input.val($lastItem.text().trim()).addClass('selecting');
        }
    }

    // Hiển thị loading spinner khi tìm kiếm
    function showLoadingSpinner() {
        if ($('.search-wrapper .search-result').length > 0) {
            $('.search-wrapper .search-result').html('<div class="text-center"><span class="lds-ellipsis"><span></span><span></span><span></span><span></span></span></div>');
        } else {
            $('.search-wrapper').append('<div class="search-result"><div class="text-center"><span class="lds-ellipsis"><span></span><span></span><span></span><span></span></span></div></div>');
        }
    }

    // Gửi yêu cầu AJAX để tìm kiếm bài viết
    function searchPost(keyword) {
        if (keyword !== '' && keyword.length < 100) {
            $.ajax({
                type: 'POST',
                dataType: 'json',
                url: initAjax,
                data: {
                    'action': 'search',
                    'keyword': keyword
                },
                success: function(response) {
                    if (response.success) {
                        var resultHTML = response.data.length > 0 ?
                            '<div class="search-result"><ul>' + response.data.map(item => `<li><a href="${item.link}" title="${item.title}">${item.title}</a></li>`).join('') + '</ul></div>' :
                            '<div class="search-result"><ul><li>Không tìm thấy kết quả.</li></ul></div>';

                        $('.search-wrapper .search-result').remove();
                        $('.search-wrapper').append(resultHTML);
                    }

                    $('.search-btn').addClass('turn-search-off').html('<i class="glyphicon glyphicon-remove"></i>').on('click', removeSearchResult);
                }
            });
        }
    }

    // Xóa kết quả tìm kiếm
    function removeSearchResult() {
        $('.search-wrapper .search-result').remove();
        $('.search-btn').removeClass('turn-search-off').html('<i class="glyphicon glyphicon-search"></i>');
        $input.val('').blur();
    }

    // Kiểm tra xem người dùng có đang sử dụng thiết bị di động không
    function detectMobile() {
        const toMatch = [
            /Android/i,
            /webOS/i,
            /iPhone/i,
            /iPod/i,
            /BlackBerry/i,
            /Windows Phone/i
        ];
        return toMatch.some(item => navigator.userAgent.match(item));
    }
});

Với các bước trên, bạn đã có thể tích hợp chức năng tìm kiếm nhanh bằng Ajax vào website WordPress của mình. Hy vọng bài viết sẽ giúp ích cho bạn trong việc nâng cấp website.

Chúc các bạn thành công!

Bình Luận


1 bình luận