THU GỌN VÀ MỞ RỘNG TÍCH CHỌN Ô TÍCH DANH MỤC TRONG CẬP NHẬT BÀI VIẾT

by daiphucminh

 * Cho phép thay đổi chiều cao ô danh mục, Thêm ô tìm kiếm cho các hộp danh mục
* Thu gọn và mở rộng để chọn tích khi viết bài

Khi quản lý một website WordPress có cấu trúc danh mục bài viết (Categories) hoặc danh mục chuyên ngành (Custom Taxonomies) phức tạp với nhiều cấp cha – con, khu vực chọn danh mục trong màn hình soạn thảo rất dễ bị kéo dài, gây rối mắt và mất thời gian cuộn chuột để tìm kiếm.

Thay vì phải cài đặt thêm các plugin nặng nề, bài viết này sẽ hướng dẫn bạn cách tối ưu hóa khung chọn danh mục ngay trong giao diện Classic Editor bằng một đoạn mã jQuery ngắn gọn.

Các tính năng vượt trội sau khi nâng cấp

  • Thu gọn / Mở rộng thông minh: Tự động ẩn toàn bộ danh mục con và thêm nút [+] bên cạnh danh mục cha. Khi cần chọn, bạn chỉ việc click để bung nhánh con ra.

  • Ô tìm kiếm nhanh cố định: Tự động chèn một ô nhập liệu ngay trên đầu danh sách danh mục. Khi gõ từ khóa, hệ thống sẽ lọc ngay lập tức và tự động mở bung nhánh cha nếu danh mục khớp nằm ở cấp con.

  • Tùy chỉnh chiều cao (Resize): Thêm góc kéo giãn ở góc dưới bên phải hộp chứa, cho phép bạn chủ động kéo rộng hoặc thu hẹp chiều cao khung danh mục bằng chuột.

Hướng dẫn cách cài đặt mã nguồn

Bạn chỉ cần sao chép đoạn code phía dưới và chèn vào cuối file functions.php của theme đang sử dụng (hoặc thêm thông qua một plugin quản lý code snippet tùy biến).

Kết quả đạt được

Thêm mở rộng và thu gọn tất cả ô tìm kiếm có thể co dãn chiều cao



/* ==========================================================================
   THU GỌN VÀ MỞ RỘNG TÍCH CHỌN Ô TÍCH DANH MỤC TRONG CẬP NHẬT BÀI VIẾT
   --------------------------------------------------------------------------
 * Cho phép thay đổi chiều cao ô danh mục, Thêm ô tìm kiếm cho các hộp danh mục
 * Thu gọn và mở rộng để chọn tích khi viết bài và mở rộng tất cả
   ========================================================================== */

function custom_admin_universal_category_search_script() {
    // Ép chiều cao mặc định 400px và mở khóa tính năng kéo cho TẤT CẢ các module
    echo '<style>
        .categorydiv .tabs-panel, 
        .taxonomydiv .tabs-panel, 
        .inside .tabs-panel,
        .taxonomydiv .categorydiv .tabs-panel {
            height: 400px !important;      /* Ép chiều cao mặc định ban đầu 400px cho mọi module */
            min-height: 200px !important;  /* Giới hạn mức nhỏ nhất khi dùng chuột co lại */
            max-height: none !important;   /* Mở khóa để có thể kéo cao lên vô hạn */
            resize: vertical !important;   /* Kích hoạt lại góc kéo cao thấp tự do */
            overflow: auto !important;
        }
        .cat-search-control-wrapper {
            display: flex;
            gap: 5px;
            margin-bottom: 8px;
            align-items: center;
        }
        .cat-search-input {
            flex: 1 !important;
            height: 28px !important;
            font-size: 13px !important;
        }
        .cat-action-btn {
            height: 28px !important;
            padding: 0 10px !important;
            line-height: 26px !important;
            font-weight: bold !important;
            cursor: pointer !important;
            user-select: none;
        }
        /* Cấu trúc ép thụt lề sâu 35px cho các cấp danh mục con trong ô tick */
        .categorychecklist ul.children {
            padding-left: 35px !important;
            margin: 4px 0 4px 0 !important;
            border-left: 2px dotted #ccd0d4 !important; /* Đường kẻ dọc dóng hàng tinh tế */
        }
        .categorychecklist li {
            margin-bottom: 6px !important;
            position: relative;
        }
        /* Căn chỉnh lại vị trí nút đóng mở lẻ cho cân đối với độ lùi lề mới */
        .toggle-search-cat-btn {
            display: inline-block;
            width: 12px;
            text-align: center;
        }
    </style>';

    echo '<script type="text/javascript">
        jQuery(document).ready(function($) {
            
            // Hàm khởi tạo bộ tìm kiếm cho tất cả các khung checklist danh mục tìm thấy
            function khoiTaoBoTimKiemDanhMuc() {
                $(".categorychecklist").each(function() {
                    var $checklist = $(this);
                    var $panel = $checklist.closest(".tabs-panel");
                    
                    if ($panel.length === 0 || $panel.find(".cat-search-control-wrapper").length > 0) {
                        return;
                    }

                    // 1. Chèn ô tìm kiếm và cặp nút điều khiển hàng loạt lên đầu panel
                    var controls = \'<div class="cat-search-control-wrapper">\' +
                        \'<input type="text" class="cat-search-input" placeholder="Tìm nhanh danh mục...">\' +
                        \'<button type="button" class="button cat-action-btn btn-expand-cats" title="Mở rộng tất cả">+</button>\' +
                        \'<button type="button" class="button cat-action-btn btn-collapse-cats" title="Thu gọn tất cả">-</button>\' +
                    \'</div>\';
                    $panel.prepend(controls);

                    // 2. Định dạng cây thư mục dấu cộng/trừ lẻ cho các mục cha
                    function tinhChinhCayDanhMuc() {
                        $checklist.find("li").each(function() {
                            var $li = $(this);
                            if ($li.children("ul.children").length > 0) {
                                $li.addClass("has-children-cat");
                                if ($li.children(".toggle-search-cat-btn").length === 0) {
                                    $li.children("label").before("<span class=\"toggle-search-cat-btn\" style=\"cursor:pointer; font-weight:bold; color:#007cba; margin-right:5px; font-family:monospace; font-size:16px; user-select:none;\">+</span>");
                                }
                            }
                        });
                    }

                    // Thực thi và mặc định ẩn toàn bộ danh mục con ban đầu
                    tinhChinhCayDanhMuc();
                    $checklist.find("ul.children").hide();

                    // Đồng bộ lại nếu có thêm danh mục nhanh bằng Ajax
                    $checklist.on("wpListAddEnd", function() {
                        tinhChinhCayDanhMuc();
                    });
                });
            }

            // Kiểm tra liên tục mỗi 500ms để bắt trọn các khung danh mục load chậm bằng plugin
            var checkExist = setInterval(function() {
                if ($(".categorychecklist").length) {
                    khoiTaoBoTimKiemDanhMuc();
                    clearInterval(checkExist);
                }
            }, 500);

            // 3. Sự kiện click đóng/mở lẻ từng mục
            $(document).on("click", ".toggle-search-cat-btn", function(e) {
                e.preventDefault();
                var $btn = $(this);
                var $subList = $btn.siblings("ul.children");
                
                if ($subList.is(":hidden")) {
                    $subList.show();
                    $btn.text("-");
                } else {
                    $subList.hide();
                    $btn.text("+");
                }
            });

            // 4. Sự kiện nút MỞ RỘNG TẤT CẢ (+)
            $(document).on("click", ".btn-expand-cats", function(e) {
                e.preventDefault();
                var $localPanel = $(this).closest(".tabs-panel");
                $localPanel.find(".categorychecklist li").show();
                $localPanel.find(".categorychecklist ul.children").show();
                $localPanel.find(".toggle-search-cat-btn").text("-");
            });

            // 5. Sự kiện nút THU GỌN TẤT CẢ (-)
            $(document).on("click", ".btn-collapse-cats", function(e) {
                e.preventDefault();
                var $localPanel = $(this).closest(".tabs-panel");
                $localPanel.find(".categorychecklist ul.children").hide();
                $localPanel.find(".toggle-search-cat-btn").text("+");
            });

            // 6. Xử lý bộ lọc tìm kiếm từ khóa trực tiếp
            $(document).on("keyup fontchange paste", ".cat-search-input", function() {
                var $input = $(this);
                var $localPanel = $input.closest(".tabs-panel");
                var $localChecklist = $localPanel.find(".categorychecklist");
                var searchVal = $input.val().trim().toLowerCase();
                
                if (searchVal === "") {
                    $localChecklist.find("li").show();
                    $localChecklist.find("ul.children").hide();
                    $localChecklist.find(".toggle-search-cat-btn").text("+");
                    return;
                }

                $localChecklist.find("li").hide();

                $localChecklist.find("li").each(function() {
                    var $li = $(this);
                    var catName = $li.children("label").text().toLowerCase();

                    if (catName.indexOf(searchVal) > -1) {
                        $li.show();
                        $li.parents("ul.children").show().each(function() {
                            $(this).siblings(".toggle-search-cat-btn").text("-");
                            $(this).parent("li").show();
                        });
                        if ($li.hasClass("has-children-cat")) {
                            $li.children("ul.children").show();
                            $li.children(".toggle-search-cat-btn").text("-");
                            $li.find("li").show();
                        }
                    }
                });
            });
        });
    </script>';
}
add_action('admin_print_footer_scripts', 'custom_admin_universal_category_search_script', 99);

Mở rộng bình thường


/* ==========================================================================
   THU GỌN VÀ MỞ RỘNG TÍCH CHỌN Ô TÍCH DANH MỤC TRONG CẬP NHẬT BÀI VIẾT
   --------------------------------------------------------------------------
 * Cho phép thay đổi chiều cao ô danh mục, Thêm ô tìm kiếm cho các hộp danh mục
 * Thu gọn và mở rộng để chọn tích khi viết bài
   ========================================================================== */

function custom_admin_classic_editor_category_search_script() {
    // Ép khung hiển thị danh mục cho phép kéo thay đổi chiều cao tự do
    echo '<style>
        .categorydiv .tabs-panel {
            resize: vertical !important;
            overflow: auto !important;
            min-height: 150px !important;
            max-height: none !important;
        }
        .cat-search-control-wrapper {
            display: flex;
            gap: 5px;
            margin-bottom: 8px;
            align-items: center;
        }
        .cat-search-input {
            width: 100% !important;
            height: 28px !important;
            font-size: 13px !important;
        }
        .cat-action-btn {
            height: 28px !important;
            padding: 0 8px !important;
            line-height: 26px !important;
            font-weight: bold !important;
            cursor: pointer;
        }
    </style>';

    echo '<script type="text/javascript">
        jQuery(document).ready(function($) {
            var $checklist = $("#categorychecklist");
            var $panel = $checklist.closest(".tabs-panel");
            
            // 1. Chèn ô tìm kiếm và cặp nút điều khiển hàng loạt lên đầu khung
            if ($panel.find(".cat-search-control-wrapper").length === 0) {
                var controls = \'<div class="cat-search-control-wrapper">\' +
                    \'<input type="text" class="cat-search-input" placeholder="Tìm nhanh danh mục...">\' +
                    \'<button type="button" class="button cat-action-btn btn-expand-cats" title="Mở rộng tất cả">+</button>\' +
                    \'<button type="button" class="button cat-action-btn btn-collapse-cats" title="Thu gọn tất cả">-</button>\' +
                \'</div>\';
                $panel.prepend(controls);
            }

            // 2. Quét qua toàn bộ danh mục để phân cấp dựa trên class của WordPress (children)
            $checklist.find("li").each(function() {
                var $li = $(this);
                if ($li.children("ul.children").length > 0) {
                    $li.addClass("has-children-cat");
                    
                    // Chèn dấu cộng thô trước nhãn chọn
                    if ($li.children(".toggle-search-cat-btn").length === 0) {
                        $li.children("label").before("<span class=\"toggle-search-cat-btn\" style=\"cursor:pointer; font-weight:bold; color:#007cba; margin-right:5px; font-family:monospace; font-size:16px; user-select:none;\">+</span>");
                    }
                }
            });

            // 3. Mặc định ẩn toàn bộ các danh mục con khi tải trang
            $checklist.find("ul.children").hide();

            // 4. Xử lý click nút dấu cộng/trừ lẻ tại từng dòng chuyên mục
            $(document).on("click", ".toggle-search-cat-btn", function(e) {
                e.preventDefault();
                var $btn = $(this);
                var $subList = $btn.siblings("ul.children");
                
                if ($subList.is(":hidden")) {
                    $subList.show();
                    $btn.text("-");
                } else {
                    $subList.hide();
                    $btn.text("+");
                }
            });

            // 5. Nút điều khiển hàng loạt: Mở rộng tất cả (+)
            $panel.on("click", ".btn-expand-cats", function(e) {
                e.preventDefault();
                $checklist.find("ul.children").show();
                $checklist.find(".toggle-search-cat-btn").text("-");
            });

            // 6. Nút điều khiển hàng loạt: Thu gọn tất cả (-)
            $panel.on("click", ".btn-collapse-cats", function(e) {
                e.preventDefault();
                $checklist.find("ul.children").hide();
                $checklist.find(".toggle-search-cat-btn").text("+");
            });

            // 7. Xử lý tính năng lọc tìm kiếm danh mục trực tiếp theo từ khóa
            $panel.on("keyup fontchange paste", ".cat-search-input", function() {
                var searchVal = $(this).val().trim().toLowerCase();
                
                if (searchVal === "") {
                    // Nếu ô tìm kiếm trống, quay về trạng thái ẩn hết mục con ban đầu
                    $checklist.find("li").show();
                    $checklist.find("ul.children").hide();
                    $checklist.find(".toggle-search-cat-btn").text("+");
                    return;
                }

                // Ẩn tất cả các mục trước khi lọc
                $checklist.find("li").hide();

                // Lọc các mục khớp từ khóa
                $checklist.find("li").each(function() {
                    var $li = $(this);
                    var catName = $li.children("label").text().toLowerCase();

                    if (catName.indexOf(searchVal) > -1) {
                        $li.show(); // Hiện mục khớp
                        
                        // Mở toàn bộ nhánh cha chứa mục này lên để không bị khuất
                        $li.parents("ul.children").show().each(function() {
                            $(this).siblings(".toggle-search-cat-btn").text("-");
                            $(this).parent("li").show();
                        });
                        
                        // Nếu bản thân mục này có con, cũng cho hiện luôn các con trực tiếp của nó
                        if ($li.hasClass("has-children-cat")) {
                            $li.children("ul.children").show();
                            $li.children(".toggle-search-cat-btn").text("-");
                            $li.find("li").show();
                        }
                    }
                });
            });
        });
    </script>';
}
add_action('admin_footer-post.php', 'custom_admin_classic_editor_category_search_script');
add_action('admin_footer-post-new.php', 'custom_admin_classic_editor_category_search_script');


Sau khi lưu file, bạn hãy quay lại trang viết bài mới hoặc chỉnh sửa bài viết cũ để kiểm tra. Đoạn mã sử dụng phương pháp định vị bằng position: absolute nên đảm bảo tính năng đóng mở hoạt động mượt mà, thẳng hàng, không xảy ra hiện tượng vỡ giao diện hay nhảy dòng trên mọi phiên bản WordPress Classic Editor. Việc tìm kiếm và phân loại bài viết giờ đây sẽ nhanh chóng và chuyên nghiệp hơn rất nhiều!

Related Posts

Leave a Comment

-
00:00
00:00
Update Required Flash plugin
-
00:00
00:00