テーマを HTML5 にしてみた!けれど…
<!DOCTYPE html> から始まって <section> <article> を駆使して HTML5でテーマを作った!と思ったら、
wp_enqueue_style()して出力されるlinkタグにtype="text/css"がついていたりwp_enqueue_script()して出力されるscriptタグにtype="text/javascript"がついていて
げんなりしてしまったこと、ありませんか? 私はあります。デフォルトのタイプ属性として定義済だから省略できるわけで、あっても間違いではないのですが、HTML ソースがシンプルになって気持ちがいいのも HTML5 の効果だとすれば、無くてもいいものは無い方がいいですね。
それじゃぁ、と header.php に直接タグを書こうとすると「それは違うよね」とどこからか声が聞こえてきます…
こんなときは WordPress カスタマイズ虎の巻 をひも解いてみましょう。
その壱 フィルターで書き換えるべし
スタイルの方は style_loader_tag というフィルターフックで link タグを書き換えることができます。
preg_replace( array( "| type='.+?'\s*|", '| />|' ), array( ' ', '>' ), $tag );
こんな感じで良さそうです。type 属性を削除するついでに />(これは何と呼ぶんでしょうか…)を > に置換しています。HTML5 的には /> でも良いのですが、無くてもいいものは無い方がいいルールに従ってシンプルに徹します。
一方、スクリプトの方は style_loader_tag に相当するフィルターが無く、タグがいきなり echo されています。困りましたね… WordPress カスタマイズ虎の巻 を読み進めましょう。
その弐 クラスを継承すべし
スクリプト関連の処理は WP_Scripts クラスが担っていて、必要になったときにこれを new したインスタンスがグローバル変数の $wp_scripts に代入されます。ということは、WP_Scripts クラスを継承して処理を書き換えてグローバル変数の $wp_scripts に突っ込めば、こちらの思うがままということになります。というわけで継承してみました。
継承ついでに header.php に html5.js の条件付きコメントを直書きしなくて済むようにしておきました。
スクリプトで条件付きコメントを使う
wp_enqueue_style() したスタイルは条件付きコメントで囲って link タグを出力することができます。wp_enqueue_styles アクションをフックして、
wp_enqueue_style( 'ie7', get_stylesheet_directory_uri() . '/css/ie7.css' ); $GLOBALS['wp_styles']->add_data( 'ie7', 'conditional', 'lte IE 7' );
とすれば、HTML ソースに、
<!--[if lte IE 7]> <link rel='stylesheet' href='http://example.com/wp-content/themes/mytheme/css/ie7.css?ver=3.5' media='all'> <![endif]-->
のように出力されます。どちらかというとスクリプトの方が需要がある気がしますが、WordPress はスタイルしかサポートしていないため、上記の PM_Scripts クラスで実装しました。wp_enqueue_scripts アクションをフックして、
wp_enqueue_script( 'html5', get_stylesheet_directory_uri() . '/js/html5.js' ); $GLOBALS['wp_scripts']->add_data( 'html5', 'conditional', 'lt IE 9' );
とすれば、HTML ソースに、
<!--[if lt IE 9]> <script src='http://example.com/wp-content/themes/mythemes/js/html5.js?ver=3.5'></script> <![endif]-->
のように出力されます。
IE のためだけの対応をしなくてよい未来は、もうすぐやってきますよ…きっと…
add_data() 豆知識
使う機会はあまりありませんが WP_Styles, WP_Scripts クラスの add_data() メソッドでいろいろなことができます。
$GLOBALS['wp_styles']->add_data( 'スタイルのID', 'alt', true );
-----> link タグの rel 属性を rel='alternate stylesheet' にします
$GLOBALS['wp_styles']->add_data( 'スタイルのID', 'title', 'タイトルですよ' );
-----> link タグに title='タイトルですよ' を追加します
$GLOBALS['wp_scripts']->add_data( 'スクリプトのID', 'data', 'JavaScript のコード' );
-----> script タグの前にインラインでスクリプトを出力します。
wp_localize_script() 豆知識
話題がどんどんそれてますが、Ajax でポストするデータを PHP から JavaScript に渡すときに良く使う関数を紹介します。本来は wp_localize_script() の名のとおり、スクリプト内で使うテキストをローカライズするためのものだと思われます。なお、この関数は対象とするスクリプトを enqueue した後で呼ぶ必要があります。以下のように書くと、
wp_enqueue_script( 'my_script', get_stylesheet_directory_uri() . '/js/my_script.js' );
$params = array(
'action' => 'my_action'
, '_ajax_nonce' => wp_create_nonce( 'my_action' )
, 'post_id' => $post->ID
);
wp_localize_script( 'my_script', 'my_var', array(
'ajaxurl' => admin_url( 'admin-ajax.php' )
, 'params' => $params
) );
HTML ソースには以下のように出力されます。
<!--
var my_var = { json_encode() された変数の値 };
//-->
インラインの方は HTML5 ぽく CDATA を無くしてあります。これで my_script.js 内の JavaScript から my_var.ajaxurl my_var.params.action などの値を使うことができますね。
まとめ
style_loader_tag フィルターと PM_Scripts クラスの使い方は以下のとおり。ここでは link タグに付く ID も消しています。
WP_Styles, WP_Scripts, enqueue 関連は concat(enqueue された内容を連結して出力)の仕組みもあったりと、結構奥の深いつくりになっていますよ。ぜひコードを読んでみてください。
また、今回のクラスを継承してカスタマイズする方法は、適切なフックがない場合に有効なケースが多いです。覚えておいて損はないですよ。
ではまた。