Как загружать внешние скрипты в админке только для определённого типа записей WordPress

31 авг. 2010 г., 10:31:20
Просмотры: 18.1K
Голосов: 16

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

Я часто использую пользовательские типы записей в разных проектах и расширяю их с помощью кастомных метабоксов, к которым добавляю специальные скрипты, например, 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");
    }
   }
?> 
1
Комментарии

@NetConstuctor.com: Не удивляйтесь, многие люди, пишущие плагины, научились программировать именно для того, чтобы создать свой плагин, поэтому у них очень мало опыта в программировании. Они решают конкретную задачу, а не следуют лучшим практикам.

MikeSchinkel MikeSchinkel
4 сент. 2010 г. 03:45:18
Все ответы на вопрос 7
13
14

Во-первых, я предполагаю, что вы используете 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'));
    }
  }
}
31 авг. 2010 г. 13:07:15
Комментарии

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

NetConstructor.com NetConstructor.com
4 сент. 2010 г. 01:15:23

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

MikeSchinkel MikeSchinkel
4 сент. 2010 г. 03:43:05

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

NetConstructor.com NetConstructor.com
6 сент. 2010 г. 03:17:33

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

NetConstructor.com NetConstructor.com
6 сент. 2010 г. 03:22:13

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

NetConstructor.com NetConstructor.com
6 сент. 2010 г. 03:38:25

@NetConstuctor.com: Смотри ОБНОВЛЕНИЕ #2.

MikeSchinkel MikeSchinkel
6 сент. 2010 г. 08:43:22

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

NetConstructor.com NetConstructor.com
6 сент. 2010 г. 11:19:30

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

MikeSchinkel MikeSchinkel
6 сент. 2010 г. 13:18:42

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

Lemon Bacon Lemon Bacon
22 сент. 2010 г. 09:51:42

Обновление: я изменил код следующим образом:

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' ); }

чтобы подключать мои скрипты только на страницах или записях. Это работает нормально, ЗА ИСКЛЮЧЕНИЕМ экрана создания новой записи, где они почему-то не загружаются. Редактирование записей или страниц и создание новых страниц работает нормально, но создание новых записей - нет.

Lemon Bacon Lemon Bacon
22 сент. 2010 г. 10:06:40

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

Lemon Bacon Lemon Bacon
22 сент. 2010 г. 10:32:37

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

Anh Tran Anh Tran
5 сент. 2012 г. 20:06:58

@Rilwis Чтобы было понятно, на момент написания этого кода текущий экран не всегда имел все необходимое.

MikeSchinkel MikeSchinkel
6 сент. 2012 г. 00:23:04
Показать остальные 8 комментариев
0

Я хотел бы поделиться кодом, который решил похожую проблему. В моем случае я пытался загружать 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' );

 }
22 сент. 2010 г. 10:31:57
0

По словам Джастина Тадлока, для подключения скриптов в админке плагинов следует использовать хук 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');
5 сент. 2012 г. 19:36:36
0

Я знаю, что вопрос уже был отвечен. Думаю, это более простое решение.

<?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");
    }

}
?> 
24 июл. 2013 г. 21:40:44
1

Я создал версию, которая не использует переменную $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;
}
17 февр. 2012 г. 02:30:23
Комментарии

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

kaiser kaiser
20 февр. 2012 г. 17:29:20
0

Как насчёт:

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' ) );


}
14 июл. 2012 г. 02:03:56
0

Это

$typenow не имеет значения во время admin_init

не совсем верно. Эта переменная действительно имеет значение, установленное на хуке admin_init в большинстве экранов типов записей, таких как "Добавить новую", список таксономий, редактирование таксономии и список записей. Однако она не имеет значения на экране "Редактировать YourPostType".

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

28 янв. 2015 г. 18:33:36