ashleyg
  • 0
Учитель

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

  • 0

Мне нужен был способ фильтровать содержимое страницы/сообщения до его загрузки, чтобы я мог добавлять скрипты в заголовок, если присутствовал определенный шорткод. После долгих поисков я наткнулся на 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');

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

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

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

Share
  1. Являются ли сценарии в заголовке жесткими требованиями для вашей ситуации? Сценарии в конце страницы проще использовать условно и рекомендуется для повышения производительности.

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

      • 0
    • Может ли это быть вызвано ДО загрузки виджетов. Чтобы было ясно, это должно произойти еще до того, как страница загрузится. Мой пример кода использует the_posts для фильтрации контента на странице, но не получает боковые панели/виджеты.

      • 0
    • Да, смотрите пример, который я добавил к своему ответу.

      • 0
    • Ваш пример на самом деле не работает. Я упускаю что-то очевидное?

      • 0
    • На самом деле я был. wp_enqueue_script не работает при применении к wp_head, но wp_print_scripts работает. Однако wp_enqueue_script работает, если применяется к инициализации следующим образом: add_action(‘init’, ‘check_widget’);

      • 0
    • Однако он загружает скрипты на каждой странице сайта, даже если виджет активен только на одной боковой панели. например, если у меня есть боковая панель для страниц блога и другая боковая панель для других страниц. Я добавляю виджет поиска на боковую панель блога, и скрипты загружаются, но также загружаются на страницах, на которых нет боковой панели блога. Мне нужно иметь возможность загружать скрипт, только если виджет присутствует на этой странице.

      • 0
  2. Вы можете использовать функцию 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') );
        }
    
    • 0
  3. Просто хотел поделиться решением, над которым я работал, которое позволило мне быть более универсальным в своей реализации. Вместо того, чтобы функция проверяла различные шорткоды, я изменил ее, чтобы найти один шорткод, который ссылается на функцию сценария/стиля, которую необходимо поставить в очередь. Это будет работать как для методов в других классах (таких как плагины, которые могут не делать этого сами), так и для функций в области видимости. Просто поместите приведенный ниже код в functions.php и добавьте следующий синтаксис на любую страницу/публикацию, где вам нужны определенные CSS и JS.

    Синтаксис страницы/сообщения: [loadCSSandJS function=»(class->имя метода/функции)»]

    Код 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;
    }
    

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

    • 0
  4. с 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, и его можно найти на новых страницах документации для разработчиков.

    • 0
  5. Спасибо, что поделились этим советом! Это дало мне небольшую головную боль, потому что сначала это не работало. Я думаю, что в приведенном выше коде есть пара ошибок (возможно, опечатки), 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, и это приводило к тому, что цикл всегда прерывался на первой итерации. Другая проблема была более тонкой и трудной для обнаружения. Приведенный выше код не работает, если шорткод — это самое первое, что написано в сообщении. Мне пришлось использовать === оператор, чтобы решить эту проблему.

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

    • 0

Оставить ответ

You must login to add an answer.