Đa số các plugin toc+ hay table of content đang có đều không hỗ trợ mục lục cho mô tả danh mục sản phẩm nên mình đã tự viết + tham khảo thêm chat GPT, cuối cùng đã viết được mục lục cho mô tả danh mục sản phẩm rồi. Chia sẻ cùng các bạn sử dụng luôn nếu cần nhé
Các bạn chỉ cần copy đoạn code sau vào functions.php của theme đang sử dụng (wp-content/themes/{your-theme}/functions.php) là được. Áp dụng cho mô tả danh mục sản phẩm với mọi theme có sử dụng Woocommerce nhé
/* * Thêm mục lục cho mô tả danh mục sản phẩm * Author: levantoan.com */ add_action('wp_footer', 'devvn_add_heading_style'); function devvn_add_heading_style(){ ?> <style> .devvn_heading_wrap { background: rgba(243,243,243,0.95); border: 1px solid rgb(197 197 197); width: 100%; color: #333; margin: 0 0 20px 0; padding: 0; } .devvn_heading_title { padding: 10px 15px; background: #c5c5c5; position: relative; cursor: pointer; } .devvn_heading_wrap > ol { margin: 10px 0 10px 33px; } .devvn_heading_wrap > ol > li { margin: 0; padding: 0; } .devvn_heading_wrap > ol > li ul { margin: 0; padding: 0; } .devvn_heading_wrap > ol > li ul li { margin: 0; padding: 0; list-style: none; } .devvn_heading_wrap > ol { counter-reset: List; } .devvn_heading_wrap > ol > li { counter-increment: List; } .devvn_heading_wrap > ol > li ul { counter-reset: List; } .devvn_heading_wrap > ol > li ul li { counter-increment: List; } .devvn_heading_wrap > ol > li ul li:before { content: counters(List,"."); } .devvn_heading_title strong { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAQAAACJ4248AAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAACYktHRAAAqo0jMgAAAAlwSFlzAAAAYAAAAGAA8GtCzwAAAAd0SU1FB+cJBA8RMDu7ID0AAAKXSURBVFjD7ZVNSBtBGIa/mV1Nfw6BtgoVidp6KPbSZj20CppCL6WHeqhgTDZGCIJSUGOQlGiagElIicHUQ+qaQGx0D+mp0EOhPyAoQssuCqXXUkIoVKWtFamszfQQTKKbg4fJyTynmXkG3vmGbxiACqcd1PxMo9EmfD4Y6+kBRlGIThDktmAQIJsFAGhJVVef/eHxkOs8jxz19VRS7ZkM3BfF3y8mJ5H+y/Q04u32Yk+CIyPy3UgEAED/aGoKrblcZSnfEgphaO7tVV3LX7M5P+lSe1qQQbMZw+rBgcowipI/zM8SntoJFAUjQzyuuoFALJaf7Kk9NTZiMdTdzTBf342NEavJRAz7+8grCJIcjwMQktuFcWvd8HBWsFjQdkMDleD1dJp8W1y8yoTDZSuuwklBnL6qCgYmJuCi0QiMohBhfl5+E4kc9kAnYdnduNNJdDyPvtfUUEk9t7UFD0UROJ8PcVwgAOB0Ht0xNCRJ0SgAgP6j240Gvd6ylL/q92OAvr7j6+SD1Zqf7BSNadPe34/h9uFzK4DuFNbQeO5PKAv2bBbDtYUFlXiSSBROU8JTgqwlErkmlFwu8tZohH+KglyCIMmzs8VN+IcfHwfBYkEva2upBF/e3ISUKCLZ7y9XcRVODOokLLvb6nBAh9EIWFFIx9yc/CAWK/6MOG50FNw8D790Oiqp6+k03BDFK69DIcQ993ph3u0+smHKZpPu5b5hjnM6AQKBclRPbno8GD7bbCrzvmiNlPC0MNlsmIQxVgkDy+bzn5bwtGhnWYxuLS2phDuZzI8vlPCUQHvJJHP+8fLymbBGA5caG0nX9jZqCQal6MzMYRPWfVpZIW0YQ6qpCcW1WirJ9kyGDESjO6+O9V6FU8l/eGH2Ze896egAAAAASUVORK5CYII=) no-repeat left center; background-size: 22px 22px !important; padding-left: 32px; text-transform: uppercase; } .devvn_heading_title::after { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAQAAACJ4248AAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAACYktHRAAAqo0jMgAAAAlwSFlzAAAAYAAAAGAA8GtCzwAAAAd0SU1FB+cJBA8REu7bYdkAAAHLSURBVFjD7ZS9S8NAGId/l0a0QaiuDl3cXIScg2CrRQhSuruKf4GggthSN1P6KYKTi7vtVmIpQehgFzHFycmPQfBjakGpIsI5SEtr05qmaQXJD27J+949T94jAezYsQNggfE8FV2uQfGm2djYAuN5AOBoRZJeis/PIJWK+JBOUyoI/QJTKgjiYSbDz5TLL59PT7QiSYSK19cgk5O1JqYWCkQKBDStWrUazlRFIZLPV3/Ibm44oHn0RPL5mKooVk5CFw4AcLk4cheP/9xgpUR7OIC1RIK7KMdiKMqyngSQz08dj472AoeUzerB2dLenrYSjZJ68/vuLuaCwdZjzs7etvz+q+XXVzNwqIuLevCSvL4OAKRpk0USRuEtAlZIdAPXFehFolt4WwEzEmbgAMC1E9BGQiGsRiKtFY/HGc3lGr8Os3AAcKBDHk9OTydCw8O49HqbK273UHF+fnw/nXbf8rxZeMcraBqvmEiAbGy0ANRCAaj9M34Wk0mttLn529mGBACAHsgyjra3jfQaefNaHEaagE7XYR7elYARiW7hpkMPZJlSxhqXGEyl+g5ujHi+s0Ppx8f3CocHCq9PggrC7L3T+SdwO3b+Tb4AHn8FI1FdY6oAAAAASUVORK5CYII=) no-repeat center center; width: 12px; height: 12px; background-size: 100% 100%; right: 15px; top: 50%; margin-top: -6px; content: ""; position: absolute; transition: all .3s linear; -moz-transition: all .3s linear; -webkit-transition: all .3s linear; } .devvn_heading_wrap.active .devvn_heading_title::after { transform: rotate(180deg); -moz-transform: rotate(180deg); -webkit-transform: rotate(180deg); } </style> <script> (function ($){ $('body').on('click', '.devvn_heading_title', function (){ let thisBox = $(this).closest('.devvn_heading_wrap'); if(thisBox.hasClass('active')){ $('> ol', thisBox).slideUp(); }else{ $('> ol', thisBox).slideDown(); } thisBox.toggleClass('active'); }); $('.devvn_heading_wrap a').on('click', function (){ let idElement = $(this).attr("href"); let top = $(idElement).offset().top; $('html, body').animate({scrollTop:top-44}, 500 ); return false; }) })(jQuery); </script> <?php } add_filter('woocommerce_taxonomy_archive_description_raw', 'devvn_auto_add_heading_ids'); function devvn_auto_add_heading_ids($content) { $content = wp_kses_post( $content ); $dom = new DOMDocument(); if(!$content) return $content; $dom->loadHTML(mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8')); $xpath = new DOMXPath($dom); $headings = $xpath->query('//h2|//h3'); $table_content = array(); $h2 = 0; foreach ($headings as $index => $heading) { $headingText = $heading->textContent; $id = sanitize_title($headingText); $id = ensure_unique_id($id, $xpath, $index); $heading->setAttribute('id', $id); if($heading->tagName == 'h2') { $h2++; $table_content[$h2] = array( 'title' => $headingText, 'href' => '#'.$id, ); }elseif($heading->tagName == 'h3') { $table_content[$h2]['child'][] = array( 'title' => $headingText, 'href' => '#'.$id, ); } } $newContent = $dom->saveHTML(); $table_content_out = ''; if($table_content){ ob_start(); ?> <div class="devvn_heading_wrap active"> <div class="devvn_heading_title"> <strong><?php _e('Mục lục', 'devvn');?></strong> </div> <ol> <?php foreach ($table_content as $item):?> <?php $title = isset($item['title']) ? sanitize_text_field($item['title']) : ''; $href = isset($item['href']) ? esc_attr($item['href']) : ''; $child = isset($item['child']) ? (array) $item['child'] : array(); if(!$title) continue; ?> <li><a href="<?php echo $href;?>" title="<?php echo $title;?>"><?php echo $title;?></a><?php if($child){?><ul><?php foreach ($child as $child_item):?> <?php $child_title = isset($child_item['title']) ? sanitize_text_field($child_item['title']) : ''; $child_href = isset($child_item['href']) ? esc_attr($child_item['href']) : ''; if(!$child_title) continue; ?> <li> <a href="<?php echo $child_href;?>" title="<?php echo $child_title;?>"><?php echo $child_title;?></a> </li> <?php endforeach;?></ul><?php }?></li> <?php endforeach;?> </ol> </div> <?php $table_content_out = ob_get_clean(); } return $table_content_out . $newContent; } if(!function_exists('ensure_unique_id')) { function ensure_unique_id($id, $xpath, $index) { $existingIds = []; $existingHeadings = $xpath->query('//h2[@id] | //h3[@id]'); foreach ($existingHeadings as $existingHeading) { $existingId = $existingHeading->getAttribute('id'); $existingIds[] = $existingId; } if (in_array($id, $existingIds)) { $i = 1; $newId = $id . '-' . $i; while (in_array($newId, $existingIds)) { $i++; $newId = $id . '-' . $i; } return $newId; } return $id; } }
Hiện tại code trên hỗ trợ cho thẻ H2 và H3 nha. Có style cơ bản rồi. Các bạn tự style lại cho đẹp nếu muốn nhé
Chúc các bạn thành công!