[Решено/2 способа] Добавление своего пункта (метабокса) в расширенные свойства меню
На странице редактирования меню и управления областями меню в настройках экрана можно включить показ расширенных свойств меню (Цель ссылки, Атрибут title, Классы CSS, Отношение к ссылке (XFN) и Описание) - рис1.
Как добавить к этим 5-ти пунктам, свой 6-ой пункт, допустим "Активность", чтобы в существующем/добавляемом пункте меню появился чекбокс (как в случае с "Цель ссылки" появляется чекбокс "Открывать в новой вкладке"), допустим "Сделать пункт меню неактивным". И если данный чекбокс будет задействован, то у данного пункта меню автоматически уберётся ссылка - рис2.
Меню выводится стандартной функцией wp_nav_menu().
Пока отделался костылём. В свойствах пункта меню, присваиваю класс unclickable, а в functions прописал хук
function no_link_unclickable_page( $p ) { return preg_replace( '%((unclickable)[^<]+)[^>]+>([^<]+)</a>%', '$1<a>$3</a>', $p, 1 ); } add_filter( 'wp_nav_menu', 'no_link_unclickable_page' );
Пока не разобрался ещё как сделать так, как хочется. Сделал немного по-другому. Может кому будет полезно и интересно. Решил зайти с другой стороны.
Альтернативный метод
1 шаг. Берём и добавляем в functions.php следующий код:
/** * Adds the meta box to the page screen */ add_action( 'add_meta_boxes', 'additional_page_attributes_metabox' ); function additional_page_attributes_metabox() { add_meta_box( 'additional_page_attributes', // id, used as the html id att __( 'Сделать пункт меню неактивным' ), // meta box title, like "Page Attributes" 'additional_page_attributes_callback', // callback function, spits out the content 'page', // post type or page. We'll add this to pages only 'side', // context (where on the screen 'core' // priority, where should this go in the context? ); } /** * Callback function for our meta box. Echo out the content */ function additional_page_attributes_callback( $post ) { global $custom_meta_fields, $post; $desc = 'Сделать пункт меню неактивным?'; $meta = get_post_meta($post->ID, "additional-page-attributes-checkbox", true); wp_nonce_field(basename(__FILE__), 'additional_page_attributes_nonce'); echo '<div><label for="additional-page-attributes-checkbox"><input type="checkbox" name="additional-page-attributes-checkbox" id="additional-page-attributes-checkbox" ',$meta ? ' checked="checked"' : '','/>'.$desc.'</label></div>'; } /** * When the post is saved, saves our custom data */ function save_additional_page_attributes_postdata( $post_id ) { if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return $post_id; if ( !isset( $_POST['additional_page_attributes_nonce'] ) || !wp_verify_nonce($_POST['additional_page_attributes_nonce'], basename( __FILE__ ) ) ) return $post_id; if ( !current_user_can( 'edit_page', $post_id ) ) return $post_id; $meta_box_checkbox_value = ""; if( isset( $_POST['additional-page-attributes-checkbox'] ) ) { $meta_box_checkbox_value = $_POST['additional-page-attributes-checkbox']; } update_post_meta($post_id, "additional-page-attributes-checkbox", $meta_box_checkbox_value); return $post_id; } add_action('save_post', 'save_additional_page_attributes_postdata'); /** * Making menu item unclickable if we checked our checkbox */ class YourTheme_Walker_Nav_Menu extends Walker_Nav_Menu { /** * @see Walker::start_el() * @since 3.0.0 * * @param string $output * @param object $item Объект элемента меню, подробнее ниже. * @param int $depth Уровень вложенности элемента меню. * @param object $args Параметры функции wp_nav_menu */ function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) { global $wp_query,$post; $indent = ( $depth ) ? str_repeat( "\t", $depth ) : ''; /* * Генерируем строку с CSS-классами элемента меню */ $class_names = $value = ''; $classes = empty( $item->classes ) ? array() : (array) $item->classes; $classes[] = 'menu-item-' . $item->ID; // функция join превращает массив в строку $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) ); $class_names = ' class="' . esc_attr( $class_names ) . '"'; /* * Генерируем ID элемента */ $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args ); $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : ''; /* * Генерируем элемент меню */ $output .= $indent . '<li' . $id . $value . $class_names .'>'; // атрибуты элемента, title="", rel="", target="" и href="" $attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : ''; $attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : ''; $attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : ''; $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : ''; // ссылка и околоссылочный текст $item_output = $args->before; // получаем id страницы, получаем значение нашего чекбокса для этой страницы и если значение чекбокса "on", выводим ссылку без атрибутов $pageid = get_post_meta( $item->ID, '_menu_item_object_id', true ); $checkbox_value = get_post_meta($pageid, "additional-page-attributes-checkbox", true); if ($checkbox_value == "on") { $item_output .= '<a class="unclickable">'; } else { $item_output .= '<a'. $attributes .'>'; } $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after; $item_output .= '</a>'; $item_output .= $args->after; $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args ); } }
Первая функция добавляет новый метабокс на страницу редактирования/создания ровнёхонько под "Атрибутами страницы". Вторая функция - функция обратного вызова - выводит разметку нашего метабокса, получает meta запись, создаёт временную защиту и добавляет чекбокс. Третья функция сохраняет meta описание нашей записи. Ну а дальше я взял стандартный Walker_Nav_Menu, ввёл две дополнительные переменные (одна получает id страницы, вторая получает значение чекбокса для этой страницы) и при выводе ссылки с атрибутами добавил условие, которое проверяет включен ли чекбокс, или нет. Если включен, то к ссылке данного пункта меню добавляется класс unclickable (его можно использовать, чтобы сделать курсор дефолтным), а атрибуты ссылки удалены.
2 шаг. Дальше, просто-напросто, изменяем вывод меню, где в аргументах указываем наш walker:
$args = array( 'theme_location' => 'YourLocation', 'walker' => new YourTheme_Walker_Nav_Menu() ); wp_nav_menu( $args );
В общем, пока только такой способ. Если у кого будут мысли, как всё таки сделать такую фишку именно в управлении менюшками, буду признателен, если поделитесь.
В общем, есть вот такой класс.
Только он там недоделанный какой-то, кусок из другого кода как-будто. Поэтому я его доделал, вот тебе готовое решение:
Получим:
Значения храняться в метаполях с ключами:
'menu-item-(key)'
. Т.е. где-то во фронте получаешь так:Дальше ты уже сам описал, как через «nav_menu волкер» можно использовать эти значения. Тебе только поле чекбокса нужно вывести и заюзать его на фронте.
Спасибо огромное! Всё сделал, всё работает.
Я себе еще добавил в класс геттер
а за пределами
if (is_admin()) {
добавил вот такой фильтр
который добавляет в поле expand_field в виде массива значений, если они конечно есть
Отличное дополнение