Как загружать внешние скрипты в админке только для определённого типа записей WordPress
Я продолжаю сталкиваться с этой проблемой и просто ищу лучшее и самое простое решение.
Я часто использую пользовательские типы записей в разных проектах и расширяю их с помощью кастомных метабоксов, к которым добавляю специальные скрипты, например, jQuery календари для выбора даты... Всё работает отлично, кроме одной ключевой проблемы... Я не хочу, чтобы эти кастомные jQuery скрипты загружались на каждой странице админки.
Мне нужно, чтобы эти кастомные jQuery поля загружались ТОЛЬКО когда я нахожусь на странице редактирования записи ОПРЕДЕЛЁННОГО типа.
Какое лучшее решение для этого?
ОБНОВЛЕНИЕ 1
Прежде всего, большое спасибо.
Я действительно удивлён, что разработчики плагинов не используют подобные подходы, потому что, как я выясняю, это одна из основных причин проблем с разными плагинами.
Но у меня возникли дополнительные сложности. Например...
Я изменил скрипт, добавив условие следующим образом:
if (is_admin() && $pagenow=='post-new.php' OR $pagenow=='post.php' && $typenow=='events')
Как видите, я пытаюсь настроить загрузку скриптов ТОЛЬКО при добавлении или редактировании записи типа "events".
Я не хочу, чтобы скрипт загружался на других страницах, включая список записей типа "events", поэтому мне кажется, что условие правильное.
Однако проблема в том, что скрипт загружается только при создании новой записи этого типа, но не работает при редактировании существующей записи.
Можете проверить и подсказать, что я делаю не так?
Вот точный код, который я использую... возможно, есть более правильный или простой способ?
<?php
// ПОДКЛЮЧАЕМ КАСТОМНЫЙ JQUERY DATEPICKER 2 ДЛЯ МЕТАБОКСОВ
add_action('admin_init','load_admin_datapicker_script');
function load_admin_datapicker_script() {
global $pagenow, $typenow;
if (is_admin() && $pagenow=='post-new.php' OR $pagenow=='post.php' && $typenow=='events') {
$ss_url = get_bloginfo('stylesheet_directory');
wp_enqueue_script('jquery');
wp_enqueue_script('custom_js_jquery_ui',"{$ss_url}/admin-metabox/js/jquery-ui-1.7.1.custom.min.js",array('jquery'));
wp_enqueue_script('custom_js_daterangepicker',"{$ss_url}/admin-metabox/js/daterangepicker.jQuery.js",array('jquery'));
wp_enqueue_script('custom_js_custom',"{$ss_url}/admin-metabox/js/custom.js",array('jquery'),NULL,TRUE);
wp_enqueue_style('custom_css_daterangepicker',"{$ss_url}/admin-metabox/css/ui.daterangepicker.css");
wp_enqueue_style('custom_css_jquery_ui',"{$ss_url}/admin-metabox/css/redmond/jquery-ui-1.7.1.custom.css");
}
}
Также... если мне нужно добавить три типа записей и загружать разные JS скрипты для каждого типа, стоит ли просто дублировать код выше три раза или это не лучший способ? Например... лучше ли объявлять: global $pagenow, $typenow; В начале файла functions.php или не имеет значения, если я продублирую это несколько раз?
Похожая проблема... Я использую плагин "gravity forms", но заметил, что его скрипты выполняются на каждой странице админки, что вызывает конфликты с другими плагинами. Как можно модифицировать их скрипты, чтобы они загружались только когда нужны?
ОБНОВЛЕНИЕ 2
Я изменил файл functions.php, используя код, предложенный Mike (ниже), однако похоже, что соответствующий javascript всё равно подключается при создании НОВОЙ записи или страницы. Это означает, что при попытке создать НОВУЮ запись/страницу (как стандартную WordPress, так и пользовательского типа) код не работает. Предложенный Mike код РАБОТАЕТ на всех других страницах админки и действительно работает при "РЕДАКТИРОВАНИИ" существующей записи/страницы или пользовательского типа. Есть предложения по исправлению?
Вот текущий код:
<?php
add_action('admin_init','load_admin_datapicker_script');
function load_admin_datapicker_script() {
global $pagenow, $typenow;
if (empty($typenow) && !empty($_GET['post'])) {
$post = get_post($_GET['post']);
$typenow = $post->post_type;
}
if (is_admin() && $pagenow=='post-new.php' OR $pagenow=='post.php' && $typenow=='events') {
$ss_url = get_bloginfo('stylesheet_directory');
wp_enqueue_script('jquery');
wp_enqueue_script('custom_js_jquery_ui',"{$ss_url}/admin-metabox/js/jquery-ui-1.7.1.custom.min.js",array('jquery'));
wp_enqueue_script('custom_js_daterangepicker',"{$ss_url}/admin-metabox/js/daterangepicker.jQuery.js",array('jquery'));
wp_enqueue_script('custom_js_custom',"{$ss_url}/admin-metabox/js/custom.js",array('jquery'),NULL,TRUE);
wp_enqueue_style('custom_css_daterangepicker',"{$ss_url}/admin-metabox/css/ui.daterangepicker.css");
wp_enqueue_style('custom_css_jquery_ui',"{$ss_url}/admin-metabox/css/redmond/jquery-ui-1.7.1.custom.css");
}
}
?>

Во-первых, я предполагаю, что вы используете wp_enqueue_script()
для загрузки своих скриптов, верно?
Если я правильно понял ваш вопрос, то вам понадобится что-то вроде следующего кода. Вам, конечно, придется адаптировать его под свои нужды, но он дает общую структуру.
Мы используем хук admin_init
с функцией load_my_script()
, чтобы проверить глобальную переменную $pagenow
на соответствие админ-странице edit.php
, а также глобальную переменную $typenow
, чтобы убедиться, что тип записи соответствует нужному вам.
Остальное — это детали, о которых вы можете прочитать здесь, если хотите узнать больше:
<?php
add_action('admin_init','load_my_script');
function load_my_script() {
global $pagenow, $typenow;
if ($pagenow=='edit.php' && $typenow=='my-custom-type') {
$ss_url = get_bloginfo('stylesheet_directory');
wp_enqueue_script('jquery');
wp_enqueue_script('my-custom-script',"{$ss_url}/js/my-custom-script.js",array('jquery'));
}
}
ОБНОВЛЕНИЕ
Отвечаю на ваше уточнение. К сожалению (по неизвестной причине), переменная $typenow
не имеет значения во время выполнения admin_init
, поэтому вам нужно получить post_type
, загрузив запись на основе URL-параметра 'post'
, как показано в следующем примере (я скопировал строку выше и ниже из вашего примера, чтобы вы видели, куда его вставить):
<?php
global $pagenow, $typenow;
if (empty($typenow) && !empty($_GET['post'])) {
$post = get_post($_GET['post']);
$typenow = $post->post_type;
}
if (is_admin() && $pagenow=='post-new.php' OR $pagenow=='post.php' && $typenow=='events') {
P.S. Что касается ваших других вопросов, пожалуйста, задавайте их как новые вопросы на сайте, чтобы я или другие могли на них ответить. Поскольку мы прилагаем много усилий, чтобы помочь вам, пожалуйста, постарайтесь дать вашему вопросу максимально точный заголовок, а также формулируйте вопросы как можно четче и лаконичнее, с хорошим форматированием и правильным английским языком. Это поможет другим пользователям быстрее находить ответы на похожие вопросы и облегчит работу тем, кто отвечает.
Я прошу вас об этом (и всех, кто задает вопросы на WordPress Answers) в обмен на время и усилия, потраченные на ответы, потому что я и другие модераторы хотим сделать WordPress Answers отличным ресурсом для сообщества, а не еще одним небрежным форумом, где трудно найти ответы, как на многих других сайтах.
ОБНОВЛЕНИЕ #2
Я подумал, что у вас может быть проблема с приоритетом операторов в условии if, но когда я тестировал раньше, не столкнулся с этим. Если все происходит так, как вы говорите, то почти наверняка проблема в этом, поэтому попробуйте следующий вариант (извините, у меня нет времени проверить это прямо сейчас, чтобы точно убедиться, что это работает):
<?php
add_action('admin_init','load_my_script');
function load_my_script() {
global $pagenow, $typenow;
if (empty($typenow) && !empty($_GET['post'])) {
$post = get_post($_GET['post']);
$typenow = $post->post_type;
}
if (is_admin() && $typenow=='events') {
if ($pagenow=='post-new.php' OR $pagenow=='post.php') {
$ss_url = get_bloginfo('stylesheet_directory');
wp_enqueue_script('jquery');
wp_enqueue_script('my-custom-script',"{$ss_url}/js/my-custom-script.js",array('jquery'));
}
}
}

привет, майк... смотри мой комментарий ниже... извини, я отправил не в тот раздел

@NetConstuctor.com: Пожалуйста, не оставляйте уточнения к вашему вопросу в разделе для ответов. Я перенес содержимое, которое вы разместили в ответе, в ваш вопрос и голосую за закрытие этого ответа.

Привет, Майк... твой код работает идеально, за исключением одной проблемы... Когда находишься в админке на странице добавления нового поста или страницы (я говорю о стандартных записях/страницах), javascript-код, который должен загружаться только для пользовательского типа записи, ТАК И ЗАГРУЖАЕТСЯ. Кроме этой проблемы, все работает отлично, и скрипт загружается только для указанных типов записей. Можешь предложить какие-то изменения для исправления?

Извини, Майк - моё первоначальное предположение было неверным. Похоже, что предоставленный тобой код ВКЛЮЧАЕТ javascript и в других типах записей, которые у меня есть. Я вставил скрипт именно так, как ты предложил. Не мог бы ты ещё раз проверить это?

Хорошо... После более детального изучения я обнаружил, что код Майка действительно работает правильно везде, кроме случая, когда вы создаёте "НОВУЮ" запись. Насколько я вижу, javascript некорректно включается при создании НОВОЙ СТРАНИЦЫ, НОВОЙ ЗАПИСИ для стандартных страниц/записей WordPress, а также для любых пользовательских типов записей. Код РАБОТАЕТ (то есть javascript не включается) при РЕДАКТИРОВАНИИ существующей записи или страницы, будь то стандартная запись/страница WordPress или пользовательский тип записи. Может кто-то предложить модификацию для исправления этой проблемы?

Друг мой... кажется, это полностью решило проблему!!! Оценка A++

@NetConstuctor.com: Пожалуйста, и спасибо за плюс и за выбор моего ответа как решения вашего вопроса.

Потрясающе! Я два дня бился над собственным решением, а тут нашел гораздо лучшее!

Обновление: я изменил код следующим образом:
if ( is_admin() && ( ( $typenow == 'page') || ( $typenow == 'post') ) ){
if ( $pagenow == 'post-new.php' OR $pagenow == 'post.php' ) { wp_enqueue_script( 'imp_jquerytools' ); wp_enqueue_style( 'rpanel-css' ); }
чтобы подключать мои скрипты только на страницах или записях. Это работает нормально, ЗА ИСКЛЮЧЕНИЕМ экрана создания новой записи, где они почему-то не загружаются. Редактирование записей или страниц и создание новых страниц работает нормально, но создание новых записей - нет.

Обновление: смотрите мой ответ с рабочим решением (не знаю, оптимальное ли оно, но работает)

Хотя вопрос уже имеет ответ, я хочу добавить небольшое улучшение: мы можем использовать функцию get_current_screen()
для получения всей информации о текущем экране. Использование глобальных переменных не рекомендуется.

Я хотел бы поделиться кодом, который решил похожую проблему. В моем случае я пытался загружать JavaScript и CSS только на страницах записей и материалов (при их редактировании и создании), и нигде больше.
Я нашел рабочее решение, используя basename( $_SERVER[ 'SCRIPT_FILENAME' ] )
для определения текущего раздела админки. Однако меня беспокоило, что доступность $_SERVER[ 'SCRIPT_FILENAME' ]
может отличаться на разных серверах (кто-нибудь знает, насколько вероятно отсутствие $_SERVER[ 'SCRIPT_FILENAME' ]
на сервере?).
Затем я нашел этот вопрос и ответ MikeSchinkel. С небольшими изменениями я заставил его работать, за исключением одного момента — при создании новой записи через "Добавить новую" он не работал.
Следующие доработки позволили решить проблему, и я делюсь ими здесь, надеясь помочь другим и улучшить решение:
add_action( 'admin_init','imp_add_admin_scripts' );
function imp_add_admin_scripts() {
$urljs = get_bloginfo( 'template_directory' ).IMP_JS;
$urlcss =get_bloginfo( 'template_directory' ).IMP_STYLES;
// Регистрируем наши скрипты
wp_register_script('imp_jquerytools', $urljs.'jquery/imp_tabs_jquery.tools.min.js' );
wp_register_style( 'rpanel-css', $urlcss.'impoweradmin.css' );
global $pagenow, $typenow;
if ( empty( $typenow ) && !empty( $_GET['post'] ) ) {
$post = get_post( $_GET['post'] );
$typenow = $post->post_type;
} elseif ( empty( $typenow ) && ( $pagenow == 'post-new.php' ) ){
$typenow = 'post';
}
if ( is_admin() && ( ( $typenow == 'page') || ( $typenow == 'post') ) ){
if ( $pagenow == 'post-new.php' OR $pagenow == 'post.php' ) {
wp_enqueue_script( 'imp_jquerytools' );
wp_enqueue_style( 'rpanel-css' );
}
}
}
Теперь я пытаюсь ограничить загрузку некоторых скриптов только для страницы настроек темы, что нельзя сделать на основе $pagenow, так как URL выглядит как admin.php?page=themeoptions, и мне не нужны эти скрипты на всех страницах admin.php, только на конкретной странице настроек темы.
Кто-нибудь знает, как это лучше реализовать?
И чтобы ответить на свой же вопрос:
if( is_admin() && ( $_GET['page'] == 'themeoptions' ) ){
wp_enqueue_script( 'my-script' );
}

По словам Джастина Тадлока, для подключения скриптов в админке плагинов следует использовать хук admin_enqueue_scripts вместо wp_enqueue_scripts:
http://justintadlock.com/archives/2011/07/12/how-to-load-javascript-in-the-wordpress-admin
add_action('admin_enqueue_scripts','load_admin_datapicker_script');

Я знаю, что вопрос уже был отвечен. Думаю, это более простое решение.
<?php
add_action( 'admin_enqueue_scripts', 'load_admin_datapicker_script' );
function load_admin_datapicker_script() {
$current_screen = get_current_screen();
if ( $current_screen->post_type === 'events' ) {
$ss_url = get_bloginfo('stylesheet_directory');
wp_enqueue_script('jquery');
wp_enqueue_script('custom_js_jquery_ui',"{$ss_url}/admin-metabox/js/jquery-ui-1.7.1.custom.min.js",array('jquery'));
wp_enqueue_script('custom_js_daterangepicker',"{$ss_url}/admin-metabox/js/daterangepicker.jQuery.js",array('jquery'));
wp_enqueue_script('custom_js_custom',"{$ss_url}/admin-metabox/js/custom.js",array('jquery'),NULL,TRUE);
wp_enqueue_style('custom_css_daterangepicker',"{$ss_url}/admin-metabox/css/ui.daterangepicker.css");
wp_enqueue_style('custom_css_jquery_ui',"{$ss_url}/admin-metabox/css/redmond/jquery-ui-1.7.1.custom.css");
}
}
?>

Я создал версию, которая не использует переменную $typenow:
function isPostEditPage($strCheckType="")
{
//Эта функция проверяет тип записи и возвращает true, если это страница редактирования данного типа
//пустое значение означает проверку для стандартного (не пользовательского) типа записи
$strCheckType=$strCheckType==""?"post":$strCheckType;
$blnReturn=false;
if(is_Admin())
{
$strPage=basename($_SERVER['SCRIPT_FILENAME']);
switch($strPage)
{
case "post.php":
if(isset($_GET["post"]))
{
$intPostID=$_GET["post"];
$strThisPostType=get_post_type($intPostID);
if($strCheckType==$strThisPostType)
{
$blnReturn=true;
}
}
break;
case "post-new.php":
$strThisPostType="post";
if(isset($_GET["post_type"]))
{
$strThisPostType=$_GET["post_type"];
}
if($strCheckType==$strThisPostType)
{
$blnReturn=true;
}
break;
}
}
return $blnReturn;
}

Глобальные переменные не изменятся, поэтому их использование безопасно. Более того, для этих страниц существуют специфические хуки, поэтому вам не нужна эта функция и связанные с ней усилия. И последнее, но не менее важное: вы проверяете строки нестрого и не в стиле "йода", поэтому проверка может не сработать. Также полагаться только на $_GET
может привести к ошибкам. В любом случае: добро пожаловать на WPSE.

Как насчёт:
add_action( 'admin_init', 'scripts_admin' );
function scripts_admin($hook){
global $typenow;
if (empty($typenow) && !empty($_GET['post'])) {
$post = get_post($_GET['post']);
$typenow = $post->post_type;
}
if( 'post.php' != $hook && 'CUSTOMPOSTTYPE' != $typenow)
return;
wp_enqueue_script( 'google-api','http://maps.googleapis.com/maps/api/js?key=AIzaSyCD5TwT3vXLfYEv9WD-kOcEg7YQLcncsls&sensor=true', array( 'jquery' ) );
}

Это
$typenow не имеет значения во время admin_init
не совсем верно. Эта переменная действительно имеет значение, установленное на хуке admin_init в большинстве экранов типов записей, таких как "Добавить новую", список таксономий, редактирование таксономии и список записей. Однако она не имеет значения на экране "Редактировать YourPostType".
Кроме того, как уже отмечали другие, правильный хук для добавления таблиц стилей и скриптов в админку WordPress - это admin_enqueue_scripts
. При использовании этого хука вам не нужно проверять is_admin()
, поскольку он срабатывает только в админке WordPress, и вы получаете текущий экран в качестве параметра.
http://codex.wordpress.org/Plugin_API/Action_Reference/admin_enqueue_scripts
