Web Components(Webコンポーネント)は、再利用が可能なカスタムHTML要素を作成するための仕様です。Polymerは、Webコンポーネントを使ったWebアプリを作るための、オープンソースのJavaScriptライブラリーです。グーグルの切れ者たちが開発したこのライブラリーは、標準のWebコンポーネントに追加機能を加え、ポリフィル(新旧ブラウザーの機能差を埋めるもの)ですべての主要ブラウザー(最新版)に対応します。
このチュートリアルでは、WordPressでWebコンポーネントとPolymerを簡単に活用する方法を解説します。WordPressにPolymerを統合し、WebサイトのサイドバーにGoogle Mapsコンポーネントを追加します。レストランをはじめ訪問者に所在地を示す必要があるサイトで使えます。
Google Mapウィジェットに限らず幅広い種類のあらかじめ用意されたコンポーネントを選んで、コンポーネントを自作することも可能です。
本チュートリアルのすべてのコードはGitHubリポジトリで入手できます。
Polymerを使う理由
Webコンポーネントの標準対応が進むなかで、ブラウザーの互換性のためにPolymerを使う理由を説明します。
PolymerはさまざまなWebコンポーネントのポリフィルを活用しています。互換性のためのポリフィルはいつかは不要になると思いますが、PolymerにはWebコンポーネントAPIを包含するラッパーの機能があり、新しいコンポーネントを早く実装できます。たとえば一方ないし双方向データバインディング、計算型プロパティ(computed property)、ジェスチャーイベントなど、標準のWebコンポーネントに対してさまざまな機能が追加されます。洗練されたCLIでプロジェクトの構築やテストの実行、ローカルサーバーの立ち上げが可能です。大人気のマテリアルデザイン要素ライブラリーをはじめ、あらかじめ用意された幅広い要素を活用できます。
PolymerはUSA Today、コカ・コーラ、Electronic Artsなどの大企業サイトに採用されている強力なフレームワークです。
WordPressでの設定
始める前にWordPressの環境設定をします。本チュートリアルではScotchBox Vagrant VMを使い、あらかじめ用意されたツールでWordPressサイトを準備します。
すでにWordPressがインストール済み、もしくは別の方法を使う場合、この節は飛ばしてもかまいません。セットアップでVagrant VMを使いたくない場合は、install WordPress locally(ローカルにWordPressをインストールする方法)でGoogle検索して最新のチュートリアルを参考にしてください。
Git、Vagrant、Virtual Boxをインストールしています。そしてあらかじめ用意されたScotchBoxのVagrantfileでGitHubリポジトリのクローンを作ります。
git clone https://github.com/scotch-io/scotch-box sitepoint-wp-polymer
vagrant upを実行する準備が整いました。マシンが起動したらデフォルトの静的ファイル「/public/index.php」を削除し、WordPressをインストールします。
cd sitepoint-wp-polymer/public
rm index.php
git clone https://github.com/WordPress/WordPress.git .
wp-config-sample.phpファイルのコピーを作ります。ファイル名はwp-config.phpとします。
cp wp-config-sample.php wp-config.php
値を編集します。
// wp-config.php
// ...
define('DB_NAME', 'scotchbox');
define('DB_USER', 'root');
define('DB_PASSWORD', 'root');
// ...
準備ができました。ブラウザーを立ち上げてhttp://192.168.33.10を開きます。管理者アカウントへのログインとサイトタイトルを入力します。自分の希望するものを入力してください。
SitePointベースのテーマを追加する
WordPressの準備が整ったので、テーマを追加します。初期状態ではTwenty Seventeenになっていますが、平凡で必要ないものまで含まれています。ここではSitePoint WordPressベーステーマを使います。
このテーマは「理想のWordPressベースのテーマ」に答えるために作られました。機能は以下の通りです。
- 余計なものがなく、高速
- ミニマルな外観。デザインは作り手にゆだねる
- 一見良さそうでも、使わない機能はない
- SEOに強い
- モバイルフレンドリー
- 100%オープンソースで無料
このテーマは新規プロジェクトの出発点にぴったりです。モバイルフレンドリーで、使いやすく、完全無料です。このチュートリアル通りに作業するならダウンロードしてください。
テーマをダウンロードしたら展開し、wp-content/themesフォルダーにコピー&ペーストします。wp-content/themesに新規フォルダー「sitepoint-base-child」を作成します。フォルダー内にstyle.cssファイルとfunctions.phpファイルを作ります。
cd wp-content/themes/
mkdir sitepoint-base-child
cd sitepoint-base-child
touch functions.php style.css
style.cssファイルを開き、以下をコピーします。
/*
Theme Name: SitePoint Base Child
Author: Almir B.
Author URI: http://almirbijedic.rocks
Template: sitepoint-base
Version: 1.0.0
Text Domain: ab-sitepoint-base
*/
functions.phpファイルに以下をコピーします。
<?php
//functions.php
add_action( 'wp_enqueue_scripts', 'sp_theme_enqueue_styles' );
function sp_theme_enqueue_styles() {
wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
}
これで親テーマのベースCSSが渡されます。ベーステーマ(親テーマ)のファイルを変更せずに、機能を追加した子テーマができました。カスタマイズは子テーマに加えます。
最後に管理者ダッシュボードを開き、サイドメニューからAppearance > Themesを選択し、SitePoint Base Childテーマの下のActivateをクリックします。
WordPressにPolymerを導入する
bowerでPolymerをインストールします。public/wp-content/themes/sitepoint-base-childフォルダーに移動してから以下のコマンドを実行します。
bower init
質問はすべて初期値でかまいません。次に依存オブジェクトをインストールします。
bower install --save Polymer/polymer#^2.0.0 PolymerElements/paper-input#2.0-preview
Polymerと、格好良いマテリアルデザインの入力コンポーネントをすぐに使えるpaper-inputコンポーネントがインストールされます。paper-inputや後述のGoogle Map要素に対して#2.0-previewタグを付けないと最新版(2.0)のPolymerでは動作しません。
Polymerを使うにはHTMLからインポートするとき、旧型ブラウザー対応のためWebコンポーネント用ポリフィルも読み込みます。
子テーマのfunctions.phpファイルを開き、既存のenqueue関数にenqueueを追加します。
<?php
//functions.php
add_action( 'wp_enqueue_scripts', 'sp_theme_enqueue_styles' );
function sp_theme_enqueue_styles() {
wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
wp_enqueue_script( 'polymer', get_stylesheet_directory_uri() . '/bower_components/webcomponentsjs/webcomponents-lite.js' );
}
WordPressにはHTMLのインポートをキューに入れるenqueue関数がありません。代わりにページの<head>要素内に出力するwp_headフックがあります。
<?php
//functions.php
add_action( 'wp_enqueue_scripts', 'sp_theme_enqueue_styles' );
function sp_theme_enqueue_styles() {
wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
wp_enqueue_style( 'polymer', get_stylesheet_directory_uri() . '/bower_components/webcomponentsjs/webcomponents-lite.min.js' );
}
add_action( 'wp_head', 'include_polymer_elements' );
function include_polymer_elements() {
?>
<link rel="import"
href="<?php echo get_stylesheet_directory_uri() ?>/bower_components/polymer/polymer.html">
<link rel="import"
href="<?php echo get_stylesheet_directory_uri() ?>/bower_components/paper-input/paper-input.html">
<?php
}
WordPressでPolymerを使うための作業は以上です。次はデモで使うWordPressウィジェットを作成します。
ウィジェットの登録
新規ウィジェットを作成するには、WP_Widgetクラスを継承した子クラスを新規作成し、それをwidgets_initフックに登録します。
子テーマのフォルダー内に新規フォルダー「lib」を作成し、sitepoint-map-widget.phpを新規作成します。
mkdir lib
cd lib
touch sitepoint-map-widget.php
このファイルに下記のコードをコピーします。
<?php
// lib/sitepoint-map-widget.php
class SitepointMapWidget extends WP_Widget {
function __construct() {
// Instantiate the parent object
parent::__construct( false, 'Google Paper Input' );
}
function widget( $args, $instance ) {
echo '<paper-input raised always-float-label label="Floating label"></paper-input>';
}
}
WP_Widetクラスの子クラスを新規作成し、親クラスのコンストラクタを呼び出してウィジェットに名前を付けてwidget関数でウィジェットを出力しました。ここではpaper-input要素のコレクションにある<paper-input>要素を出力します。
最後に、新規PHPファイルをfunctions.phpファイルの先頭で読み込みます。
<?php
// functions.php
require_once( 'lib/sitepoint-map-widget.php' );
// ...
ファイルの最後にウィジェットを登録します。
<?php
// functions.php
// ...
add_action( 'widgets_init', 'sp_register_widgets' );
function sp_register_widgets() {
register_widget( 'SitepointMapWidget' );
}
WordPressの管理者ダッシュボードへ移動します。メインメニューから外観 > ウィジェットへ移動すると、左にウィジェット「Google Paper Input」があります。
右のMain Sidebarの、「SitePointベーステーマのほかの初期ウィジェット」にドラッグ&ドロップします。
これでページを開くと、右側の検索欄の上にマテリアルデザインの入力欄がラベル付きで表示されます。
ここまでがPolymerの「Hello, World!」の解説です。Polymerのインストール、WordPressとの共存方法、サンプルウィジェットの読み込みなど、ここまででもかなり多くのことを学びました。次の節ではさらに進めて、Google Mapコンポーネントを実装していきます。
Webコンポーネントライブラリー入門
WebComponents.orgで最初から用意されているコンポーネントを活用します。「Google Map」で検索すると必要なカスタム要素が出てきます。ページURLの末尾で、bowerのパッケージ名が分かります。
sitepoint-base-childフォルダーに移動して、以下のコマンドを実行します。
bower install --save GoogleWebComponents/google-map#2.0-preview
sitepoint-base-childフォルダーに新規フォルダーを作成して、webcomponentsと名付けます。ここにPolymer関係のファイルを保存します。
mkdir webcomponents
Polymerコンポーネントの新規作成
webcomponentsフォルダーに新規ファイル「sitepoint-map.html」を作成します。
cd webcomponents
touch sitepoint-map.html
各Polymerコンポーネントはそれぞれ別々のHTMLファイルで、各ファイルが新しいカスタムHTMLタグを構成します。HTMLファイルは大きく3つの部分で成っています。
1.依存オブジェクトの読み込み
// sitepoint-map.html
<link rel="import" href="../bower_components/google-map/google-map.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
先ほどインストールしたGoogle Map要素と、Hello, World!のサンプルで使ったpaper-input要素が読み込まれています。
2.テンプレート
// sitepoint-map.html
<link rel="import" href="../bower_components/google-map/google-map.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<dom-module id="sitepoint-map">
<template>
<style>
google-map {
height: 300px;
}
</style>
<google-map id="spMap"
fit-to-marker
mouse-events="true"
on-google-map-mousemove="trackCoords"
on-google-map-mouseout="resetCoords"
api-key="[[clientId]]">
<google-map-marker latitude="37.78"
longitude="-122.4"
draggable="true"></google-map-marker>
</google-map>
<paper-input raised id="coords" label="Coordinates"></paper-input>
</template>
</dom-module>
<dom-module>要素のIDは、要素の実際の名称、すなわちタグ名です。ファイル名と同じ名前にするのがコツです。この中に<template>タグがあり、新しいカスタム要素の中身が書かれています。分解すると、カスタム要素は基本的なHTML要素から構成されています。<google-map>タグも、スクリプトと標準HTML要素、ほかのカスタムHTML要素(これも同じように分解できる)を集めて構成されています。
カスタム要素のIDで、後述するようにスクリプトからthis.$.id構文で簡単に要素にアクセスできます。今回、この入力要素を参照するにはthis.$.coordsを使います。
<google-map>タグの属性は2つのイベントです。google-map-mouseoverはユーザーがウィジェット(地図)にマウスカーソルを載せた際に実行され、google-map-mouseoutは地図からマウスカーソルが離れたときに実行されます。今回は、それほど実用的な意味をもちませんが、コンポーネントにイベント実行機能を追加する方法を示すために加えています。on-event-nameキーワードを追加して、イベントで実行したい関数名を渡す方法がおすすめです。イベントリスナーのターゲット指定のために要素にID名を付けなくて済みます。メソッド、イベント、プロパティの全リストはこちらで確認できます。
fit-to-marker属性も渡すことで、地図上のマーカーがすべて見えるよう地図の大きさと表示位置が再調整されます。
client-id属性には自分の(Google APIの)クライアントIDを記入します。IDはGoogle公式の手順説明に従って入手します。GET A KEYボタンで開始します。
3.スクリプト
// sitepoint-map.html
<link rel="import" href="../bower_components/google-map/google-map.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<dom-module id="sitepoint-map">
<template>
...
</template>
<script>
class SitepointMap extends Polymer.Element {
static get is() { return 'sitepoint-map'; }
static get properties() {
return {
clientId: String
}
}
trackCoords(e) {
this.$.coords.value = e.detail.latLng.lat() + ", " + e.detail.latLng.lng();
}
resetCoords() { this.$.coords.value = "" }
}
window.customElements.define(SitepointMap.is, SitepointMap);
</script>
</dom-module>
要素を作るのに必要最小限の記述は以下の部分です。
class SitepointMap extends Polymer.Element {
static get is() { return 'sitepoint-map'; }
}
window.customElements.define(SitepointMap.is, SitepointMap);
クラス名は<dom-template>要素のID名と同じにします。名称はキャメルケース(連結された英単語の各先頭文字だけ大文字にする)を使い、staticなis関数から<dom-template>要素のIDを返すのがベストプラクティスとされています。
propertiesオブジェクトは、要素のどんな属性も登録できる関数名として予約語になっています。2語以上からなる属性名がダッシュ記号で区切ってあるとき、
<sitepoint-map client-id="..."></sitepoint-map>
参照するには「clientId」になります。つまりコンポーネント内ではキャメルケースになるのです。
名称にキャメルケースを使うと、
<sitepoint-map clientId="..."></sitepoint-map>
コンポーネント内で属性名はすべて小文字になります。参照するときにはclientidを使います。
propertiesのあとに2つのカスタムメソッドがありますが、それぞれmousemoverおよびmouseoutイベントのコールバックに使います。trackCoordsメソッドは単純に地図上にあるマウスカーソルの位置の緯度と経度を取得して入力欄に表示します。
Webコンポーネントの準備ができたので、残る作業はあと少しです。
<sitepoint-map>コンポーネントの読み込み
webcomponentsフォルダー内にindex.htmlファイルを新規作成します。ここからすべてのカスタムコンポーネントを読み込みます。このファイルを一度キューに追加(enqueue)すれば、新しいコンポーネントを加えるときに、index.htmlファイルだけをインポートすればよく、HTMLのインポートを追加する手間が省けます。PHPでwp_headフックを使うよりも楽です。
新規作成したindex.htmlファイルに以下を記述します。
// webcomponents/index.html
<link rel="import" href="sitepoint-map.html">
functions.phpファイルに戻り、ヘッダー内のpaperボタンとPolymerのHTMLインポートへ移動します。paperボタンのインポートは不要なので削除し、代わりにwebcomponentsフォルダー内のindex.htmlファイルを読み込みます:
<?php
// functions.php
add_action( 'wp_head', 'include_polymer_elements' );
function include_polymer_elements() {
?>
<link rel="import"
href="<?php echo get_stylesheet_directory_uri() ?>/bower_components/polymer/polymer.html">
<link rel="import"
href="<?php echo get_stylesheet_directory_uri() ?>/webcomponents/index.html">
<?php
}
今後はカスタムコンポーネントはすべてindex.htmlに追加します。たとえばGoogle Calenderコンポーネントを導入したり、paper-progressをはじめ始めから使えるコンポーネントを使ったり、今後はカスタムコンポーネントはすべてindex.htmlに追加します。
// webcomponents/index.html
<link rel="import" href="sitepoint-map.html">
<link rel="import" href="sitepoint-calendar.html">
<link rel="import" href="../bower_components/paper-progress/paper-progress.html">
サンプルなので、そのままコピーしないでください。
カスタムHTMLタグ<sitepoint-map>の出力
カスタムHTMLタグ<sitepoint-map>を、paper入力欄を置いた場所に出力します。
<?php
// lib/sitepoint-map-widget.php
class SitepointMapWidget extends WP_Widget {
function __construct() {
// Instantiate the parent object
parent::__construct( false, 'Google Map' );
}
function widget( $args, $instance ) {
echo '<sitepoint-map client-id="' . GOOGLE_MAP_API_KEY . '"></sitepoint-map>';
}
}
定数GOOGLE_MAP_API_KEYを定義してGoogle APIのIDを入力します。記述する場所は、子テーマのfunctions.phpファイルの先頭部分が良いでしょう。
<?php
// functions.php
require_once( 'lib/sitepoint-map-widget.php' );
define('GOOGLE_MAP_API_KEY', '<your-key-here>');
WordPress用Google Mapウィジェットが完成しました。この機能を提供するプラグインは数百行ものPHPのコードが含まれています。今回のwebcomponentsフォルダーの構成は分かりやすく、すべてが一元管理されていて、拡張も改造も簡単です。
最後に
WordPress上でPolymerを使う方法やカスタムコンポーネントを追加する方法を学びました。さらに腕を磨きたいなら、WordPressウィジェットの属性(attribute)をコンポーネントの属性に反映しましょう。外観 > ウィジェットの設定画面からマーカーの位置、クライアントIDなどの値をコンポーネントに渡せます。
時間をかけて美しいWebコンポーネントの世界を掘り下げ、ライブラリーを覗いてWordPressサイトで使えそうなものを見つけてください。
本記事はSimon Codringtonが査読を担当しています。最高のコンテンツに仕上げるために尽力してくれたSitePointの査読担当者のみなさんに感謝します。
(原文:Using Polymer in WordPress: Build a Custom Google Maps Component)
[翻訳:西尾 健史/編集:Livit]