Программное добавление иконок Font-Awesome к виджету категорий
Я использую виджет "Категории" в сайдбаре(ах) и хотел бы отображать иконку Font Awesome рядом с каждой категорией в виджете. Пока иконка будет одинаковой для всех категорий, но в будущем я хочу назначить каждой категории свою уникальную иконку.
Я хочу модифицировать виджет "Категории" с помощью кода в файле functions.php, добавив иконку путем вставки разметки типа <i class="fa fa-chevron-right"></i>
в элемент ссылки/якоря категории после названия категории. Я мог бы сделать это через CSS, но тогда потеряю возможность программно определять, какую иконку отображать, а также гибкость для других улучшений/изменений, которые я могу захотеть сделать в будущем.
По сути, я хочу добиться такого эффекта:
Кат 1 > Кат 2 > Кат 3 >
(Символ '>' обозначает расположение иконки относительно названия категории)
Я подключил Font Awesome в файле functions.php с помощью хука wp_enqueue_scripts
следующим образом, и он загружается и отображает иконки идеально. Обратите внимание, что я не использую никаких плагинов Font Awesome для WordPress.
/* Подключение скриптов
-----------------------------------------------------------------*/
add_action( 'wp_enqueue_scripts', 'essentials_enqueue_scripts' );
function essentials_enqueue_scripts() {
/* jQuery */
wp_enqueue_script('jquery');
wp_enqueue_script( 'jquery_ui', "http" . ($_SERVER['SERVER_PORT'] == 443 ? "s" : "") . "://ajax.googleapis.com/ajax/libs/jqueryui/2.0.3/jquery-ui.min.js", false, null);
wp_enqueue_script( 'waypoints', get_template_directory_uri() . '/js/waypoints.min.js');
wp_enqueue_script( 'essentials_main', get_template_directory_uri() . '/js/essentials_main.js', array(), '1.0.0', true );
wp_enqueue_script( 'essentials_show_stuff', get_template_directory_uri() . '/js/essentials_show_stuff.js', array(), '1.0.0', true );
/* Google Fonts */
wp_register_style('GoogleFonts','http://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700,800|Bad+Script');
wp_enqueue_style( 'GoogleFonts');
/* Font Awesome Fonts */
wp_register_style('Font Awesome','//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css');
wp_enqueue_style( 'Font Awesome');
}
Несмотря на все мои усилия в поисках решения, мне не удалось найти способ модификации виджета категорий.
Предположения:
Вы не объясняете, как именно хотите установить пакет Font Awesome, поэтому я предполагаю, что вы используете плагин Font Awesome Icons.
Вы написали:
Прежде чем кто-то предложит использовать фоновое изображение, я не хочу этого делать. Мне нужно физическое отображение.
поэтому я предполагаю, что вы хотите использовать тег <i>
напрямую, например:
<i class="fa icon-caret-right"></i>
после каждой ссылки на категорию в виджете списка категорий.
Идея:
Вы можете использовать фильтр wp_list_categories
для изменения вывода виджета списка категорий.
Пример:
Вот простой пример, как вставить его в список категорий через фильтр wp_list_categories
:
/**
* Добавляет тег Font Awesome <i> после каждой ссылки в виджете категорий
*
* @param string $output
* @return string $output
*/
function custom_wp_list_categories( $output )
{
remove_filter( current_filter(), __FUNCTION__ );
return str_ireplace( '</li>', '<i class="fa icon-caret-right"></i></li>', $output);
}
add_action( 'widgets_init', function(){
add_filter( 'wp_list_categories', 'custom_wp_list_categories' );
});
Это даст вам вывод, похожий на этот:

Отличный фрагмент кода, я проверю его, когда вернусь чуть позже. Я опубликую результаты.

Просто не забудьте изменить имя класса в соответствии с вашими потребностями ;-) Я использовал icon-caret-right
, потому что это правило именования классов согласно плагину. В других случаях это может быть fa-caret-right
.

return str_ireplace( '</li>', '<i class="fa fa-chevron-right"></i></li>', $output);
сработало, а return str_ireplace( '</a></li>', '<i class="fa fa-chevron-right"></i></a></li>', $output);
— нет.

хорошо, вы хотите добавить это внутри тега <a></a>
, тогда попробуйте это: return preg_replace( '/<\/a>\s*<\/li>/i', ' <i class="fa fa-chevron-right"></i></a></li>', $output );

Хорошо, теперь я запутался в новой части... как именно это работает? Я понимаю последнюю часть, но не первую.

Не буду ставить минус за законное решение/попытку помочь автору вопроса, но честно: использование замены строк в PHP, когда простое CSS-правило справилось бы, кажется излишним.

Извините, что не был более конкретным в моем исходном 'Вопросе', но это не ограничится чем-то настолько малым, как просто добавление иконки. В будущем это будет расширено, и CSS не удовлетворил мои потребности, поэтому я и разместил вопрос здесь ;).

@MrJustin спасибо за голосование, я также впечатлен гениальными ответами, предоставленными другими пользователями. PS: \s*
соответствует любому пробельному символу, такому как пробел, табуляция и новая строка.

@MrJustin не могли бы вы, пожалуйста, расширить ваш вопрос, детализировав эти "будущие потребности", для которых CSS недостаточен? В текущем виде ваш вопрос касается исключительно CSS и не связан с WordPress, поэтому находится на шаткой почве для закрытия как не по теме.

Я также могу добавить, что фильтр WordPress был избыточным, учитывая масштаб вопроса MrJustin. Вряд ли стоит направлять его к регулярным выражениям... Не могу избавиться от ощущения, что регулярные выражения находятся на противоположном полюсе от простоты статической CSS-реализации. Я переживаю за любого будущего посетителя WPSE, который придет сюда, чтобы отобразить один символ из шрифта иконок, а в итоге получит кучу регулярных выражений в своем бэкенде. Пощадите новичков!

также можно использовать: return str_ireplace( '</a>', ' <i class="fa fa-chevron-right"></i></a>', $output);

Этот ответ содержит довольно простое CSS-решение.
По сути, вам нужно добавить следующее в вашу таблицу стилей:
.cat-item cat-item-7 {
list-style-image: url('my-epic-news-icon');
}
cat-item cat-item-11 {
list-style-image: url('my-epic-jquery-icon');
}
и так далее
Да, это не самое динамичное решение, но ваши категории, вероятно, не будут часто меняться.

То, что ответ предполагает использование чистого CSS, говорит о том, что исходный вопрос не соответствует тематике WPSE. Тем не менее: я думаю, что в ваших CSS-селекторах неправильный синтаксис. Вам следует использовать .cat-item.cat-item-7
— или, поскольку предполагается использование одного и того же иконки-шрифта для всех элементов списка, просто .cat-item
. Кроме того: иконка-шрифт использует атрибут content
и применяется к псевдоклассу :after
, например: .cat-item:after { content: '\f18d'; }
.

Справедливые замечания. Да, я допустил ошибку в синтаксисе. Мы уверены, что автор вопроса хочет одну и ту же иконку, а не разные для каждой категории? (Я понял вопрос именно так). Я просто хотел предложить самое простое решение, хотя это действительно выводит вопрос/ответ за рамки тематики.

Это не то решение, которое я искал, так как я уже говорил, что не хочу использовать background и что мне нужно, чтобы иконка была после текста. Хотя это может и не быть background, но это всё равно изображение, а не Font Awesome. Хорошее решение, но не подходящее для меня.

Предположим, вы хотите использовать иконку fa-chevron-right
, вам просто нужно стилизовать элемент списка через CSS. Используйте псевдокласс :after
:
.list-item:after {
font-family: FontAwesome; // или другое имя шрифта FontAwesome, если оно было изменено
content: '\f054';
}
Редактирование
Чтобы показать, как можно передавать динамический CSS (который легко адаптируется под настройки плагина) через callback, вот пример:
(Примечание: термины "плагин" и "тема" взаимозаменяемы ниже.)
Сначала модифицируем CSS, чтобы стилизовать элементы списка внутри виджета. WordPress добавляет класс .widget
к контейнеру виджета. Можно использовать его:
.widget .list-item:after {}
Или, если это будет частью плагина, который регистрирует пользовательский виджет, можно использовать CSS-класс, определённый в вашем виджете через массив $widget_ops
:
$widget_ops = array(
'classname' => 'custom-widget-classname',
'description' => __( 'Описание пользовательского виджета', 'namespace' )
);
Теперь можно стилизовать по этому классу:
.custom-widget-classname .list-item:after {}
Если нужно стилизовать стандартный виджет "Категории", используйте класс .widget_categories
. Для примера воспользуемся этим подходом.
Поместим стили в callback, подключённый к wp_head
, хотя можно также использовать wp_print_styles
:
function pluginslug_fontawesome_styles() {
// Код будет здесь
}
add_action( 'wp_head', 'pluginslug_fontawesome_styles' );
Внутри просто выведем стили с нашим правилом:
function pluginslug_fontawesome_styles() {
?>
<script type="text/css">
.widget_categories .list-item:after {
font-family: FontAwesome; // или другое имя шрифта FontAwesome, если оно было изменено
content: '\f054';
}
</script>
<?php
}
add_action( 'wp_head', 'pluginslug_fontawesome_styles' );
На этом всё. Но, раз мы уже внутри PHP-функции, можно легко сделать эти стили динамическими, используя переменную:
function pluginslug_fontawesome_styles() {
// Определяем переменную для иконки списка
$list_item_icon = '\f054';
// ...пропуск:
content: <?php echo $list_item_icon; ?>;
Теперь можно использовать значение из настроек плагина, просто передав его в переменную:
function pluginslug_fontawesome_styles() {
// Получаем настройки плагина (предполагается, что это массив)
$plugin_options = get_option( 'pluginslug_plugin_options' );
// Определяем переменную для иконки списка
$list_item_icon = $plugin_options['list_item_icon'];
// Выводим стили
?>
<script type="text/css">
.widget_categories .list-item:after {
font-family: FontAwesome; // или другое имя шрифта FontAwesome, если оно было изменено
content: <?php echo $list_item_icon; ?>;
}
</script>
<?php
}
add_action( 'wp_head', 'pluginslug_fontawesome_styles' );
Вот и всё! Динамический CSS, выводящий реальную иконку (не фоновое изображение), берущий значение из настроек плагина.
Так как это просто CSS, метод легко расширяется на любые селекторы — не только на элементы списка внутри виджетов.

Вы знаете, что можно обернуть CSS-правила в колбэк и добавить их через wp_head
или wp_print_styles
, верно? Но эта часть реализации — отдельный вопрос и выходит за рамки заданного.

Да, я знаю, как добавлять стили. Однако я не хочу использовать CSS. Я понимаю, что это быстрый и эффективный способ, и я действительно ценю ваш подход... но, возможно, мне следовало сказать «мне нужна» вместо «хотелось бы», когда речь идет о функции.

Пожалуйста, ознакомьтесь с отредактированным вопросом. Я добавил пример, чтобы показать, как всю эту задачу действительно можно решить с помощью CSS — динамично, расширяемо и с учетом пользовательских настроек плагина.

Хорошо, но что, если я хочу, чтобы иконка всплывала справа? В моем обычном CSS я прикрепил ее к li a:after {content}
и попробовал: text-align: right
, но это не сработало. Чтобы уточнить, я имею в виду, что если я хочу, чтобы все иконки были справа от LI, а текст — слева. Допустим, ul/li установлен на 250px, текст всегда является ссылкой, но я задал ему display: block. Затем я добавил 'иконку' и хочу, чтобы она располагалась справа от li. С помощью <i...></i> я могу легко сделать это через float.

Чтобы ответить на этот конкретный вопрос: вместо li a:after
используйте li a:before
. Но вопросы стилизации/позиционирования элементов: помимо знания разметки, предоставляемой WordPress (включая конкретные CSS-классы и HTML-разметку списка), это вопросы CSS/HTML. Интересно, что в ответе, который вы отметили как принятый, используется только CSS. (Подключенный таблица стилей Font Awesome, который использует класс, добавленный через замену строки, применяет псевдокласс :after
и атрибут content
для вывода иконки.)

Я бы сделал это так:
// Если виджет используется только на определённых страницах,
// здесь можно добавить соответствующие условия
add_action('wp_enqueue_scripts', function() {
wp_enqueue_style('font-awesome',
'//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css');
});
function wpse_128247_font_awesome_categories($cat_name) {
// Определите желаемую иконку здесь
$icon = ' <i class="fa fa-smile-o"></i>';
return $cat_name.$icon;
} // function wpse_128247_font_awesome_categories
function wpse_128247_add_filter($cat_args) {
add_filter('list_cats', 'wpse_128247_font_awesome_categories');
// Поскольку мы перехватываем этот фильтр, просто передаём его данные дальше
return $cat_args;
} // function wpse_128247_add_filter
add_filter('widget_categories_args', 'wpse_128247_add_filter');
function wpse_128247_remove_filter($output) {
remove_filter('list_cats', 'wpse_128247_font_awesome_categories');
// Поскольку мы перехватываем этот фильтр, просто передаём его данные дальше
return $output;
} // function wpse_128247_remove_filter
add_filter('wp_list_categories', 'wpse_128247_remove_filter');
Сначала мы подключаем стили Font Awesome. Затем перехватываем некоторые фильтры, чтобы добавить/удалить наш собственный фильтр для списка категорий. Вот и всё.
// РЕДАКТИРОВАНИЕ:
Без комментариев, с учётом того, что Font Awesome уже подключён, используя замыкания и позволяя фильтру удалить себя, код выглядит следующим образом:
function wpse_128247_font_awesome_categories($cat_name) {
remove_filter(current_filter(), __FUNCTION__);
return $cat_name.' <i class="fa fa-smile-o"></i>';
} // function wpse_128247_font_awesome_categories
function wpse_128247_add_filter($cat_args) {
add_filter('list_cats', 'wpse_128247_font_awesome_categories');
return $cat_args;
} // function wpse_128247_add_filter
add_filter('widget_categories_args', 'wpse_128247_add_filter');
Я бы не назвал это избыточным. Но да, мой код содержит больше строк, чем текущее решение birgire.

Ваше решение было неплохим, но избыточным по сравнению с вариантом birgire. У меня уже подключен Font-Awesome, извините, что не уточнил.

Да, этот код нельзя назвать избыточным, я согласен. Возможно, он просто выглядел объемнее из-за 4 функций вместо 2 и количества комментариев. Я ценю комментарии, я не против них. Просто визуально казалось, что кода больше :).
