特定のショートコードまたはウィジェットが存在する場合にのみスクリプトをロードする


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にある必要があります。
アシュリーG

回答:


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

ウィジェットがロードされる前に呼び出すことができます。明確にするために、これはページがロードされる前に行われなければなりません。私のサンプルコードはthe_postsを使用してページのコンテンツをフィルタリングしますが、サイドバー/ウィジェットを取得しません。
アシュリーG

はい、回答に追加した例を参照してください。
-sorich87

あなたの例は実際には機能しません。明らかな何かが欠けていますか?
アシュリーG

実はそうだった。wp_enqueue_scriptはwp_headに適用すると機能しないようですが、wp_print_scriptsは機能します。wp_enqueue_scriptは、initに次のように適用した場合でも機能します。add_action( 'init'、 'check_widget');
アシュリーG

ただし、ウィジェットが1つのサイドバーでのみアクティブな場合でも、サイトのすべてのページにスクリプトがロードされます。たとえば、ブログページ用のサイドバーと他のページ用の別のサイドバーがある場合。ブログのサイドバーに検索ウィジェットを追加すると、スクリプトは読み込まれますが、ブログのサイドバーがないページにも読み込まれます。そのページにウィジェットが存在する場合にのみ、スクリプトをロードできる必要があります。
アシュリーG

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

主な問題は2つあったと思います。それはbreakifステートメントのスコープ内になかったため、最初の繰り返しでループが常に中断していました。もう1つの問題は、より微妙で発見が困難でした。ショートコードが投稿で最初に書かれたものである場合、上記のコードは機能しません。===これを解決するには、演算子を使用する必要がありました。

とにかく、このテクニックを共有してくれてありがとう、それは大いに役立った。


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_tagWP 4.7で導入され、新しい開発者向けドキュメントページで見つけることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.