コンテキスト制御、セクション、およびパネル

WordPress 4.0 および 4.1 では、カスタマイザーのプレビューウィンドウ内でユーザーがプレビューしているサイトの部分に応じて、カスタマイザー UI の一部を表示または非表示にするサポートが追加されました。シンプルなコンテキスト制御の例として、テーマがフロントページでのみヘッダー画像とサイトのタグラインを表示する場合があります。これは、カスタマイザー マネージャーの get_ メソッドを使用するのに最適なユースケースであり、これらの設定のコアコントロールを直接変更してフロントページにコンテキストを持たせることができます:

  1. // Hide core sections/controls when they aren't used on the current page.
  2. $wp_customize->get_section( 'header_image' )->active_callback = 'is_front_page';
  3. $wp_customize->get_control( 'blogdescription' )->active_callback = 'is_front_page';

ユーザーエクスペリエンス向上のためのツール(Tools for Improved User Experience) - img1
このコンテキスト制御の例では、テーマはフロントページでのみサイトのタグラインを表示するため、ユーザーがプレビューウィンドウ内の別のページに移動すると、カスタマイザー内の対応するフィールドは非表示になります。

パネル、セクション、およびコントロールの active_callback パラメーターは、コールバック関数名(コアまたはカスタム)を取ります。このパラメーターは、追加したオブジェクトの登録時にも設定できます。以下は、Twenty Fourteen テーマからの例です:

  1. $wp_customize->add_section( 'featured_content', array(
  2. 'title' => __( 'Featured Content', 'twentyfourteen' ),
  3. 'description' => //...
  4. 'priority' => 130,
  5. 'active_callback' => 'is_front_page',
  6. ) );

前の例では、is_front_page が直接使用されています。しかし、現在のビューがページであるか(または特定のページであるかを ID で確認するなど)、より複雑なロジックの場合は、カスタム関数を使用できます(詳細については #30251 を参照してください)。PHP 5.2 をサポートする必要がない場合、これはインラインで行うことができます:

  1. 'active_callback' => function () { return is_page(); }

PHP 5.2 のサポートは、名前付き関数を作成し、active_callback パラメーターで参照するだけで簡単です:

  1. //...
  2. 'active_callback' => 'prefix_return_is_page';
  3. //...
  4. function prefix_return_is_page() {
  5. return is_page();
  6. }

カスタムコントロール、セクション、およびパネル内では、カスタムカスタマイザーオブジェクトクラス内で active_callback 関数を直接オーバーライドするオプションもあります:

  1. class WP_Customize_Greeting_Control extends WP_Customize_Control {
  2. // ...
  3. function active_callback() {
  4. return is_front_page();
  5. }
  6. }

最後に、他のすべての active_callback 動作をオーバーライドするために使用できるフィルターがあります:

  1. // Hide all controls without a description when previewing single posts.
  2. function title_tagline_control_filter( $active, $control ) {
  3. if ( '' === $control->description ) {
  4. $active = is_singular();
  5. }
  6. return $active;
  7. }
  8. add_filter( 'customize_control_active', 'title_tagline_control_filter', 10, 2 );

active_callback API は、すべてのカスタマイザーオブジェクトタイプ(コントロール、セクション、および パネル)に対して正確に同じように機能します。追加のボーナスとして、すべてのコントロールがコンテキスト的に非表示の場合、セクションは自動的に非表示になり、パネルにも同じことが適用されます。

選択的リフレッシュ: 高速で正確な更新

WordPress 4.5 で導入された選択的リフレッシュは、カスタマイザーの「プレビュー」で関連する設定が変更された領域のみを更新します。変更された要素のみを更新することで、完全な iframe リフレッシュよりもはるかに高速で、干渉が少なくなります。他の利点として、カスタマイザーにおける選択的リフレッシュで指摘されているのは:

  • 繰り返しを避ける (DRY) ロジック
  • 正確なプレビュー更新
  • プレビューの部分と関連する設定およびコントロールとの関連、および WordPress 4.7 以降の可視編集ショートカット

純粋な JavaScript postMessage 更新のロジックは重複しています。カスタマイザー内の JavaScript は、マークアップを生成する PHP を反映する必要があるか、近似するためのショートカットを取る必要があります。しかし、選択的リフレッシュは

DRY であり、JavaScript と PHP の重複はありません。Ajax リクエストがプレビュー用の新しいマークアップを取得します。

この Ajax 呼び出しのおかげで、リフレッシュは 正確 です。マークアップを変更できるフィルターを使用します。フロントエンドに表示されるのと同じ結果を示します。

さらに、選択的リフレッシュの部分は、プレビューの領域とそれに対応する設定との関連を提供します。カスタマイザーは、この関係を利用して、ユーザーがサイトの特定の部分に関連するコントロールを見つけるのを助ける可視編集ショートカットを提供します。将来的には、部分 API が拡張され、プレビュー内で設定を直接編集できるようにし、部分を使用して設定をプレビューするための構造化された JS API を含む可能性があります。

これらの理由から、すべての設定は、ユーザーエクスペリエンスを向上させるために選択的リフレッシュトランスポートを利用することを強く推奨されており、設定のプレビューをさらに強化するために追加の JavaScript ベースのトランスポートを提供するオプションがあります。

部分の登録

設定のプレビューは、必要な部分を登録することで選択的リフレッシュを使用することを選択する必要があります。この例は、テーマ Twenty Sixteen から主に取られたもので、blogdescription 設定に対して選択的リフレッシュが追加され、同じ名前の部分が追加されます。

  1. function foo_theme_customize_register( WP_Customize_Manager $wp_customize ) {
  2. $wp_customize->selective_refresh->add_partial( 'blogdescription', array(
  3. 'selector' => '.site-description',
  4. 'container_inclusive' => false,
  5. 'render_callback' => function() {
  6. bloginfo( 'description' );
  7. },
  8. ) );
  9. }
  10. add_action( 'customize_register', 'foo_theme_customize_register' );

settings 引数が提供されていない場合、コントロールの設定がコントロール ID にデフォルトであるのと同じように、部分 ID と同じになるのがデフォルトです。部分に関するいくつかの重要な引数は次のとおりです:

変数 タイプ 説明
settings 配列 部分に関連付けられた設定 ID。
selector 文字列 更新されるページマークアップ内の要素をターゲットにします。
container_inclusive ブール値 true の場合、リフレッシュは全体のコンテナを置き換えます。そうでない場合、コンテナの子要素のみを置き換えます。デフォルトは false です。
render_callback 関数 リフレッシュ時にレンダリングされるマークアップを生成します。
fallback_refresh ブール値 部分がドキュメント内に見つからない場合、完全なページリフレッシュが発生するかどうか。

選択的リフレッシュの JavaScript イベント

これらは wp.customize.selectiveRefresh で発生します:

  • partial-content-rendered
    配置がレンダリングされるとき。前述のように、JavaScript ドリブンウィジェットはこのイベントで再構築できます。
  • render-partials-response
    部分レンダリングのリクエスト後にデータが返されるとき。サーバーはこのデータを ‘customize_render_partials_response’ でフィルタリングします。
  • partial-content-moved
    ウィジェットがサイドバー内で移動したとき。上記のように、JavaScript ドリブンウィジェットはこのイベントでリフレッシュできます。
  • widget-updated
    WidgetPartialrenderContent メソッドでリフレッシュされるとき。
  • sidebar-updated
    サイドバーにリフレッシュまたは更新されたウィジェットがあるとき。あるいは、サイドバーのウィジェットが reflowWidgets() を使用してソートされるとき。

ウィジェット: 選択的リフレッシュへのオプトイン

テーマとウィジェットの両方が 選択的リフレッシュを使用するためにオプトインする必要があります。すべてのコアウィジェットとテーマは、すでにこれを有効にしています。

サイドバーにおけるテーマサポート

テーマのサイドバーでウィジェットの部分的リフレッシュを許可するために:

  1. add_theme_support( 'customize-selective-refresh-widgets' );

重要: ウィジェットの選択的リフレッシュには、ウィジェットの ID を含む各ウィジェットの周りに before_widget/after_widget ラッパー要素を含める必要があります。このようなラッパーは、register_sidebar() を使用するとデフォルトで作成されます。例えば:

  1. function example_widgets_init() {
  2. register_sidebar(
  3. array(
  4. 'name' => esc_html__( 'Sidebar', 'example' ),
  5. 'id' => 'sidebar-1',
  6. 'description' => esc_html__( 'Add widgets here.', 'example' ),
  7. 'before_widget' => '<section id="%1$s" class="widget %2$s">', // <= Key for selective refresh.
  8. 'after_widget' => '</section>',
  9. 'before_title' => '<h2 class="widget-title">',
  10. 'after_title' => '</h2>',
  11. )
  12. );
  13. }
  14. add_action( 'widgets_init', 'example_widgets_init' );

ウィジェットサポート

テーマが選択的リフレッシュをサポートしている場合でも、ウィジェットもオプトインする必要があります。すべてのコアウィジェットはすでにこれを有効にしています。以下は、選択的リフレッシュのサポートを追加するウィジェットの例です:

  1. class Foo_Widget extends WP_Widget {
  2. public function __construct() {
  3. parent::__construct(
  4. foo’,
  5. __( 'Example', 'bar-plugin' ),
  6. array(
  7. 'description' => __( An example widget’, bar-plugin ),
  8. 'customize_selective_refresh' => true,
  9. )
  10. );
  11. if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) {
  12. add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
  13. }
  14. }
  15. ...

上記の行 9 は選択的リフレッシュを有効にします:

  1. 'customize_selective_refresh' => true,

上記の行 13 は、ウィジェットのスタイルシートが常にカスタマイザーセッションに表示されることを保証します。ウィジェットを追加しても、スタイリングを取得するためにフルページリフレッシュは発生しません:

  1. if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) {
  2. add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
  3. }

ウィジェットの選択的リフレッシュサポートの実装を参照してください。

JavaScript ドリブンウィジェットサポート

マークアップに JavaScript に依存するウィジェットは、ウィジェットの選択的リフレッシュサポートの実装 に示されているように、追加の手順が必要です:

  • 1. 上記のスタイルシートのように、is_customize_preview() に基づいて任意の JavaScript ファイルをエンキューします。
  • 2. partial-content-rendered イベントのハンドラーを追加し、必要に応じてウィジェットをリフレッシュします:
  1. wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
  2. // logic to refresh
  3. } );
  • 1. ウィジェットに iframe が含まれている場合、部分をリフレッシュするためのハンドラーを追加します:
  1. wp.customize.selectiveRefresh.bind( 'partial-content-moved', function( placement ) {
  2. // logic to refresh, perhaps conditionally
  3. }

改善された設定プレビューのための PostMessage の使用

カスタマイザーは、すべての設定のプレビューを自動的に処理します。これは、設定がその Ajax 呼び出しで PHP によってフィルタリングされる形で、プレビューウィンドウ全体を静かに再読み込みすることで行われます。この方法はうまく機能しますが、すべての設定変更のたびにフロントエンド全体を再読み込みする必要があるため、非常に遅くなる可能性があります。選択的リフレッシュは、この体験を改善し、変更された要素のみをリフレッシュしますが、Ajax 呼び出しのため、プレビューで変更を確認するのにまだ遅延があります。

ユーザーエクスペリエンスをさらに向上させるために、カスタマイザーは、JavaScript で設定変更を直接管理するための API を提供し、真にライブプレビューを可能にします。以下の画像は、この技術を利用したカスタム CSS オプション(postMessage)と標準リフレッシュオプションの比較を示しています:

ユーザーエクスペリエンス向上のためのツール(Tools for Improved User Experience) - img2
PostMessage 設定トランスポートを使用したカスタマイザー内のカスタム CSS 設定。

ユーザーエクスペリエンス向上のためのツール(Tools for Improved User Experience) - img3
デフォルトのリフレッシュ設定トランスポートを使用したカスタマイザー内のカスタム CSS 設定。

PostMessage を使用するには、設定を追加する際に transport パラメーターを postMessage に設定します。多くのテーマは、タイトルやタグラインなどのコア設定を変更して、これらの設定のトランスポートプロパティを変更することで postMessage を利用します:

  1. $wp_customize->get_setting( 'blogname' )->transport = 'postMessage';
  2. $wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage';

設定のトランスポートが postMessage に設定されると、その値が変更されてもプレビューのリフレッシュはトリガーされなくなります。フロントエンドのプレビュー内で設定を更新するための JavaScript を実装するには、まず JavaScript ファイルを作成してエンキューします:

  1. function my_preview_js() {
  2. wp_enqueue_script( 'custom_css_preview', 'path/to/file.js', array( 'customize-preview', 'jquery' ) );
  3. }
  4. add_action( 'customize_preview_init', 'my_preview_js' );

あなたの JavaScript ファイルは次のようになります:

  1. ( function( $ ) {
  2. wp.customize( 'setting_id', function( value ) {
  3. value.bind( function( to ) {
  4. $( '#custom-theme-css' ).html( to );
  5. } );
  6. } );
  7. wp.customize( 'custom_plugin_css', function( value ) {
  8. value.bind( function( to ) {
  9. $( '#custom-plugin-css' ).html( to );
  10. } );
  11. } );
  12. } )( jQuery );

PostMessage を使用するために、必ずしも JavaScript に精通している必要はありません。ほとんどのコードはボイラープレートです。PostMessage トランスポートの恩恵を受ける設定の種類は、jQuery の .html() や .text() メソッドを使用するなどの簡単な JS 変更を必要とし、<body> または他の要素のクラスを入れ替えて異なる CSS ルールのセットをトリガーします。これを行うことで、選択的リフレッシュで完全に正確な変更が更新されるインスタントプレビューのロジックを簡素化することで、ユーザーエクスペリエンスを高速化し、すべての PHP ロジックを JS に重複させることなく実現できます。

設定の検証

WordPress 4.6 には、カスタマイザー設定値の検証に関連する新しい API が含まれています。カスタマイザーは、導入以来設定値のサニタイズを行ってきました。サニタイズは、値をデータベースに永続化するために安全なものに強制的に変換することを含みます。一般的な例としては、値を整数に変換したり、テキスト入力からタグを削除したりすることがあります。このように、サニタイズは ロスのある 操作です。設定の検証が追加されることで:

  • 1. すべての変更された設定は、保存される前に事前に検証されます。
  • 2. いずれかの設定が無効な場合、カスタマイザーの保存リクエストは拒否されます。したがって、保存はすべての設定が汚れたまま再保存を試みるトランザクションになります。(カスタマイザーの トランザクション提案 は、ここでの設定検証に密接に関連しています。)
  • 3. 検証エラーメッセージがユーザーに表示され、間違いを修正して再試行するように促されます。

サニタイズと検証は、WP_REST_Request::sanitize_params() および WP_REST_Request::validate_params() を介して REST API インフラストラクチャの一部でもあります。設定の値は、サニタイズを通過する前に検証を受けます。

検証の動作や追加のコード例については、機能発表ポストを参照してください。

PHP における設定の検証

設定を登録する際に sanitize_callback を提供できるように、validate_callback 引数を提供することもできます:

  1. $wp_customize->add_setting( 'established_year', array(
  2. 'sanitize_callback' => 'absint',
  3. 'validate_callback' => 'validate_established_year'
  4. ) );
  5. function validate_established_year( $validity, $value ) {
  6. $value = intval( $value );
  7. if ( empty( $value ) || ! is_numeric( $value ) ) {
  8. $validity->add( 'required', __( 'You must supply a valid year.' ) );
  9. } elseif ( $value &lt; 1900 ) {
  10. $validity->add( 'year_too_small', __( 'Year is too old.' ) );
  11. } elseif ( $value > gmdate( 'Y' ) ) {
  12. $validity->add( 'year_too_big', __( 'Year is too new.' ) );
  13. }
  14. return $validity;
  15. }

sanitize_callback 引数を提供すると customize_sanitize_{$setting_id} のフィルターが追加されるのと同様に、validate_callback 引数を提供すると customize_validate_{$setting_id} のフィルターが追加されます。WP_Customize_Setting インスタンスがその validate メソッドでこれらにフィルターを適用する場合、以前に追加された設定の検証を追加する必要がある場合は、このフィルターを追加できます。

validate_callback および customize_validate_{$setting_id} フィルターコールバックは、最初の引数として WP_Error インスタンスを受け取ります(最初は追加されたエラーが空です)、次にサニタイズされる $value、最後に検証される WP_Customize_Setting インスタンスです。

カスタム設定クラスは、設定クラスの validate メソッドを直接オーバーライドすることもできます。

クライアント側の検証

設定が純粋に JavaScript を介してプレビューされる場合(および選択的リフレッシュなしの postMessage トランスポート)、クライアント側の検証も追加する必要があります。そうしないと、検証エラーは完全なリフレッシュが発生するまで、または保存が試みられるまで持続します。クライアント側の検証は、サーバー側の検証の代わりにはならず、悪意のあるユーザーがサーバー側の検証が行われていない場合に無効な値を保存するためにクライアント側の検証を回避できる可能性があるためです。

validate メソッドは、wp.customize.Setting JS クラス(実際には wp.customize.Value 基底クラス)で利用可能です。その名前は少し誤解を招くもので、実際には WP_Customize_Setting::sanitize() PHP メソッドと非常に似た動作をしますが、JS で値をサニタイズおよび検証するために使用できます。この JS はプレビューではなくカスタマイザー ペイン のコンテキストで実行されるため、そのような JS は customize-controls を依存関係として持ち(customize-preview ではなく)、customize_controls_enqueue_scripts アクション中にエンキューされる必要があります。いくつかの例の JS 検証:

  1. wp.customize( 'established_year', function ( setting ) {
  2. setting.validate = function ( value ) {
  3. var code, notification;
  4. var year = parseInt( value, 10 );
  5. code = 'required';
  6. if ( isNaN( year ) ) {
  7. notification = new wp.customize.Notification( code, {message: myPlugin.l10n.yearRequired} );
  8. setting.notifications.add( code, notification );
  9. } else {
  10. setting.notifications.remove( code );
  11. }
  12. code = 'year_too_small';
  13. if ( year &lt; 1900 ) {
  14. notification = new wp.customize.Notification( code, {message: myPlugin.l10n.yearTooSmall} );
  15. setting.notifications.add( code, notification );
  16. } else {
  17. setting.notifications.remove( code );
  18. }
  19. code = 'year_too_big';
  20. if ( year > new Date().getFullYear() ) {
  21. notification = new wp.customize.Notification( code, {message: myPlugin.l10n.yearTooBig} );
  22. setting.notifications.add( code, notification );
  23. } else {
  24. setting.notifications.remove( code );
  25. }
  26. return value;
  27. };
  28. } );

通知

エラーノーティフィケーション通知は、通常、コントロールの設定の値に基づいてユーザーにフィードバックを提供します。設定の検証ルーチンが WP_Error インスタンスを返すと、設定の notifications コレクションにエラーノーティフィケーションが追加されます。PHP WP_Error インスタンスに追加された各エラーは、JavaScript では wp.customize.Notification として表されます:

  • WP_Errorcode は、JS では notification.code として利用可能です。
  • WP_Errormessage は、JS では notification.message として利用可能です。PHP で特定のエラーコードに追加された複数のメッセージがある場合、それらは JS で単一のメッセージに連結されます。
  • WP_Errordata は、JS では notification.data として利用可能です。これは、サーバーからクライアントに追加のエラーコンテキストを渡すのに便利です。

サーバー上の検証ルーチンから WP_Error が返されるたびに、wp.customize.Notification が作成され、type プロパティが「エラー」となります。

PHP からの非エラー通知の設定は現在サポートされていません(#37281 を参照)、ただし、次のように JS で非エラー通知を追加することもできます:

  1. wp.customize( 'blogname', function( setting ) {
  2. setting.bind( function( value ) {
  3. var code = 'long_title';
  4. if ( value.length > 20 ) {
  5. setting.notifications.add( code, new wp.customize.Notification(
  6. code,
  7. {
  8. type: 'warning',
  9. message: 'This theme prefers title with max 20 chars.'
  10. }
  11. ) );
  12. } else {
  13. setting.notifications.remove( code );
  14. }
  15. } );
  16. } );

通知の type として「info」を提供することもできます。デフォルトの type は「エラー」です。カスタムタイプも提供でき、通知は notice.notice-foo に一致する CSS セレクタでスタイル設定できます。「foo」は提供されたタイプです。コントロールは、wp.customize.Control.renderNotifications メソッドをオーバーライドすることで、通知のレンダリング方法のデフォルトの動作をオーバーライドすることもできます。