Загрузка сценариев только при наличии определенного шорткода или виджета

17

Мне нужен был способ фильтрации содержимого страницы / публикации перед его загрузкой, чтобы я мог добавить сценарии в заголовок, если присутствовал определенный шорткод. После долгих поисков я наткнулся на это на http://wpengineer.com

function has_my_shortcode($posts) {
    if ( empty($posts) )
        return $posts;

    $found = false;

    foreach ($posts as $post) {
        if ( stripos($post->post_content, '[my_shortcode') )
            $found = true;
            break;
        }

    if ($found){
        $urljs = get_bloginfo( 'template_directory' ).IMP_JS;

    wp_register_script('my_script', $urljs.'myscript.js' );

    wp_print_scripts('my_script');
}
    return $posts;
}
add_action('the_posts', 'has_my_shortcode');

который абсолютно блестящий и сделал именно то, что мне нужно.

Теперь мне нужно немного расширить его и сделать то же самое для боковых панелей. Это может быть определенный тип виджета, шорткод, фрагмент кода или что-то еще, что будет работать для определения необходимости загрузки скрипта.

Проблема в том, что я не могу понять, как получить доступ к содержимому боковых панелей до загрузки боковой панели (у рассматриваемой темы будет несколько боковых панелей)

Эшли Г
источник
Являются ли скрипты в заголовке жестким требованием для вашей ситуации? Сценарии в конце страницы легче иметь условно и рекомендуется для повышения производительности.
Первый
Сначала я попробовал это в wp_footer, что исключает необходимость предварительной фильтрации содержимого, но, хотя скрипты загружались нормально, они не работали. Эти скрипты должны быть в wp_head, чтобы делать то, что им нужно.
Эшли Г

Ответы:

20

Вы можете использовать функцию is_active_widget . Например:

function check_widget() {
    if( is_active_widget( '', '', 'search' ) ) { // check if search widget is used
        wp_enqueue_script('my-script');
    }
}

add_action( 'init', 'check_widget' );

Чтобы загрузить скрипт на странице, где загружен только виджет, вам нужно добавить код is_active_widget () в ваш класс виджетов. Например, посмотрите виджет недавних комментариев по умолчанию (wp-includes / default-widgets.php, строка 602):

class WP_Widget_Recent_Comments extends WP_Widget {

    function WP_Widget_Recent_Comments() {
        $widget_ops = array('classname' => 'widget_recent_comments', 'description' => __( 'The most recent comments' ) );
        $this->WP_Widget('recent-comments', __('Recent Comments'), $widget_ops);
        $this->alt_option_name = 'widget_recent_comments';

        if ( is_active_widget(false, false, $this->id_base) )
            add_action( 'wp_head', array(&$this, 'recent_comments_style') );

        add_action( 'comment_post', array(&$this, 'flush_widget_cache') );
        add_action( 'transition_comment_status', array(&$this, 'flush_widget_cache') );
    }
sorich87
источник
Можно ли это назвать ДО того, как загрузятся виджеты. Чтобы было ясно, это должно произойти еще до загрузки страницы. Мой пример кода использует the_posts для фильтрации содержимого на странице, но он не получает боковые панели / виджеты.
Эшли Г
Да, посмотрите пример, который я добавил к своему ответу.
sorich87
Ваш пример на самом деле не работает. Я что-то упускаю из виду?
Эшли Г
На самом деле я был. wp_enqueue_script, кажется, не работает при применении к wp_head, но wp_print_scripts работает. Скрипт wp_enqueue_script работает, хотя и применяется к init следующим образом: add_action ('init', 'check_widget');
Эшли Г
Однако он загружает скрипты на каждую страницу сайта, даже если виджет активен только на одной боковой панели. например, если у меня есть боковая панель для страниц блога и другая боковая панель для других страниц. Я добавляю виджет поиска на боковую панель блога, и скрипты загружаются, но он также загружается на страницах, на которых нет боковой панели блога. Мне нужно иметь возможность загружать скрипт, только если виджет присутствует на этой странице.
Эшли Г
3

Просто хотел поделиться решением, над которым я работал, что позволило мне быть немного более универсальным с моей реализацией. Вместо того, чтобы проверять функцию на наличие различных шорткодов, я изменил ее, чтобы найти единственный шорткод, который ссылается на функцию сценария / стиля, которую необходимо поставить в очередь. Это будет работать как для методов в других классах (например, для плагинов, которые сами этого не делают), так и для функций в области. Просто поместите приведенный ниже код в functions.php и добавьте следующий синтаксис на любую страницу / пост, где вы хотите конкретные CSS и JS.

Синтаксис страницы / поста: [loadCSSandJS function = "(class-> method / function name)"]

код functions.php:

function page_specific_CSSandJS( $posts ) {
  if ( empty( $posts ) )
    return $posts;

  foreach ($posts as $post) {

    $returnValue = preg_match_all('#\[loadCSSandJS function="([A-z\-\>]+)"\]#i', $post->post_content, $types);

    foreach($types[1] as $type) {
      $items = explode("->",$type);
      if (count($items) == 2) {
        global $$items[0];      
        if( method_exists( $$items[0], $items[1] ))
          add_action( 'wp_enqueue_scripts', array(&$$items[0], $items[1]) );
      }
      else if( !empty( $type ) && function_exists( $type ))
        add_action( 'wp_enqueue_scripts', $type );
    }
  }

  return $posts;
}

Это также позволит вам добавить столько, сколько вы хотите на странице. Имейте в виду, что вам нужен метод / функция для загрузки.

Ник Капорин
источник
1

Спасибо, что поделились этим советом! Это вызвало у меня небольшую головную боль, потому что сначала это не работало. Я думаю, что есть пара ошибок (возможно, опечатки) в коде выше, has_my_shortcodeи я переписал функцию, как показано ниже:

function has_my_shortcode( $posts ) {

        if ( empty($posts) )
            return $posts;

        $shortcode_found = false;

        foreach ($posts as $post) {

            if ( !( stripos($post->post_content, '[my-shortcode') === false ) ) {
                $shortcode_found = true;
                break;
            }
        }

        if ( $shortcode_found ) {
            $this->add_scripts();
            $this->add_styles();
        }
        return $posts;
    }

Я думаю, что было две основные проблемы: проблема breakне была включена в оператор if, и это приводило к тому, что цикл всегда прерывался на первой итерации. Другая проблема была более тонкой и трудной для обнаружения. Код выше не работает, если шорткод - самое первое, что написано в посте. Я должен был использовать ===оператор, чтобы решить это.

В любом случае, большое спасибо за то, что поделились этой техникой, она очень помогла.

jekbau
источник
1

В Wordpress 4.7 есть еще один способ добиться этого в вашем functions.phpфайле,

add_action( 'wp_enqueue_scripts', 'register_my_script');
function register_my_script(){
  wp_register_script('my-shortcode-js',$src, $dependency, $version, $inFooter);
}

сначала вы регистрируете свой скрипт , который на самом деле не печатается на вашей странице, если вы не ставите его в очередь, если вызывается ваш шорткод,

add_filter( 'do_shortcode_tag','enqueue_my_script',10,3);
function enqueue_my_script($output, $tag, $attr){
  if('myShortcode' != $tag){ //make sure it is the right shortcode
    return $output;
  }
  if(!isset($attr['id'])){ //you can even check for specific attributes
    return $output;
  }
  wp_enqueue_script('my-shortcode-js'); //enqueue your script for printing
  return $output;
}

do_shortcode_tagбыл введен в WP 4.7 и могут быть найдены в новых разработчиков документации страниц.

Aurovrata
источник