wordpress WordPress のテーマを jQuery Mobile でスマートフォン対応に

2013年8月1日

PC 用に作成した WordPress のテーマを jQuery Mobile を使ってスマートフォン対応にする際のメモ。

PC とタブレット端末には、すでに作成してあるテーマを使用し、ユーザーエージェントによりテーマを切り替えるプラグインを利用して、スマートフォン用に jQuery Mobile を使ってテーマを作成。

以下は参考にした主なサイト。

大まかな工程

  • jQuery Mobile の「ThemeRoller」を利用して配色や角丸の値などをカスタマイズ。
  • WordPress の既存のテーマをコピーして、スマートフォン用のテーマとする。
  • jQuery Mobile のファイルをスマートフォン用のテーマに読み込む。
  • スマートフォン用のテーマを適宜修正。
  • プラグイン「Multi Device Switcher」をインストール。

「ThemeRoller」の利用

以下のサイトを参考に「ThemeRoller」を利用してテーマに合う配色や角丸の値をカスタマイズ。

テーマローラーの概要(jQuery Mobile 1.0.1 日本語リファレンス)

  • カスタマイズした jQuery Mobile のファイルをダウンロード。
  • ダウンロードの際、テーマにはサイト名など分かりやすい名前を付けることができる。
  • ダウンロードしたファイルを解凍すると「index.html」ファイルと「themes」フォルダがある。
  • 「index.html」を開くと以下のようなファイルのリンク方法が記載されている。(以下の例ではテーマ名は「wpsm」と指定してダウンロードした)
    Your theme was successfully downloaded. You can use this page as a reference for how to link it up!
    
    <link rel="stylesheet" href="themes/wpsm.min.css" />
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile.structure-1.3.2.min.css" />
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
  • 最初にカスタマイズした CSS(wpsm.min.css)を読み込み、その後で CDN で必要な CSS と JavaScript ファイルを読み込むようになっている。
  • 「themes」フォルダには CSS ファイルと画像フォルダ「images」が入っている。

WordPress の既存のテーマをコピー

既存のテーマ(PC用)をコピーして、「wp-content/themes」に配置する。この際「screenshot.png」と「style.css」は新しいものを作成し、「style.css」の冒頭の「Theme Name」を最低限記述する。

/*
Theme Name: smartphone
Description: smartphone Template
*/
  • 「style.css」の冒頭の記述の後にテーマローラーでカスタマイズした CSS(wpsm.css)の内容をコピー&ペーストする。その際、ミニファイされていない CSS を使った方が、その部分を修正したり確認するには便利。
  • または、「style.css」の冒頭の記述の後にテーマローラーでカスタマイズした CSS をインポートする。
  • jQuery Mobile の CSS で使用する画像は以下のように指定されているので、ダウンロードした「themes」フォルダ中の画像フォルダ「images」に入っている画像を WordPress のテーマの「images」フォルダにコピーしておく。
    .ui-icon-alt .ui-icon-searchfield:after {
      background-image: url(images/icons-18-black.png);
      background-repeat: no-repeat;
    }
  • 大きな画像がはみ出さないように以下を記述しておく。
    img {
      max-width: 100%;
      height: auto;
    }

jQuery Mobile のファイルの読み込み

WordPress のスマートフォン用のテーマのhead 要素内に jQuery Mobile のファイルを読み込む。

  • テーマローラーでカスタマイズした CSS は「style.css」に内容をコピーしてあるので、「style.css」をまず読み込む。
  • その後にダウンロードしたファイルに入っていた「index.html」ファイルに指定してあるように他のファイルを読み込む。
  • また、meta 要素の viewport には「width=device-width, initial-scale=1」を指定する。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mobileテーマ</title>
  <link rel="stylesheet" href="<?php echo get_stylesheet_uri(); ?>" type="text/css" />  //style.css の読み込み
  <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile.structure-1.3.2.min.css" /> 
  <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> 
  <script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script> 
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>

スマートフォンでの表示を PCで確認出来るシミュレータ

スマートフォンでどのように見えるかは実機で確認するのが一番良いが、簡単な方法として以下のようなツールを使用。

  • Mobilizer:iPhone, Android, Blackberry や HTC等での表示を PCで確認出来るシミュレータ
  • User Agent Switcher:Firefox のアドオンで、ユーザーエージェントを切り替えられる。

スマートフォン用のテーマの作成

jQuery Mobile ではカスタムデータ属性「data-role=”page”」を持つ div 要素が1ページになり、各ページ内のレイアウトも div 要素にカスタムデータ属性を指定して定義する。

jQuery Mobileのページ構成は、ページ(<div data-role=”page”>~</div>)の中に

  • ヘッダー (<div data-role=”header”>~</div>)
  • コンテンツ (<div data-role=”content”>~</div>)
  • フッター (<div data-role=”footer”>~</div>)

で構成する。

data-role 属性の値に、”header” や ”content” など、用意されている「UIタイプ」を指定することにより、そのUIタイプとして表示されるようになる。

jQuery Mobile のページ構成

ページの作成 data-role=”page”
div要素などにdata-role属性「page」を指定して、HTML内にページを作成。data-role=”page”を指定した要素には他と重複しないページ ID を付け、id属性に記述。1ファイル、1ページで作成する場合はこの限りではない。
ヘッダーの表示 data-role=”header”
ページ内の要素に data-role 属性「header」を指定すると、ヘッダーとして表示される。ヘッダー内は h1〜h6 要素で包んだテキストがセンタリングして表示される。
コンテンツの表示 data-role=”content”
ページ内の要素に data-role 属性「content」を指定すると、コンテンツ領域として表示される。
フッターの表示 data-role=”footer”
ページ内の要素に data-role 属性「footer」を指定すると、フッターが表示される。フッター内は h1〜h6 要素で包んだテキストがセンタリングして表示される。
  • ヘッダー、フッターは省略が可能
  • 1ファイル、1ページで作成する場合は、page要素(<div data-role=”page”>~</div>)も省略可

header.php と footer.php

header.php と footer.php を修正して、data-role 属性の値に”page”、”header” 、 ”content” などを指定してページ、ヘッダー、コンテンツ、フッターを作成。”page”は一番外側の div 要素に指定する。以下の例では、既存の<div id=”container”>に data-role=”page” data-theme=”a” を指定してページを作成。また、以下は 1ファイル、1ページで作成する場合の例。

//header.php
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
・・・省略・・・
</head>
<body <?php body_class(); ?>>
<div data-role="page" data-theme="a" id="container">  //page 要素
<div data-role="header" data-theme="z">  //header 要素
<div id="header">  //既存の要素をそのまま残してある(上の要素とまとめることも可能)
<a href="<?php echo is_front_page() ? '#' : home_url(); ?>"><h1 id="toptitle">Title</h1>
<p id="language"><a data-role="button" class="ui-btn-right"  href="<?php echo get_site_url(1); ?><?php echo $is_jp || $is_root ? '/en' : '/jp'; ?>" data-mini="true" data-theme="a"><?php echo $is_jp || $is_root ? 'English' : 'Japanese'; ?></a></p>  //button 要素(言語切換え用)
</div><!-- end of #header -->
</div><!-- end of #data-role="header" -->
<div data-role="content">  //content 要素

以下は「footer.php」

//footer.php
</div><!-- end of #data-role="content" -->  //content 要素終了
<div data-role="footer" id="footer">  //footer 要素
<small>Copyright &copy; Mysite. All rights reserved. </small>
</div><!-- end of #footer (data-role="footer") -->
</div><!-- end of #container (data-role="page") -->
<?php wp_footer(); ?>
</body>
</html>

sidebar.php

メニューの部分を、data-role=”navbar”とし、ナビゲーションバーとして表示。

<div data-role="navbar" data-iconpos="right" id="sidebar">  //navbar 要素
<ul>
<li><a data-icon="home" href="<?php echo home_url(); ?>">Home</a></li>
<li><a data-icon="back" data-rel="back" href="<?php echo home_url(); ?>">Back</a></li>
</ul>
<ul>
<li><a href="<?php echo home_url(); ?>/news/">What's New</a></li>
・・・省略・・・
<li><a href="<?php echo home_url(); ?>/contact/">Contact</a></li>
</ul>
</div><!-- end of #sidebar -->

テンプレートファイルと「style.css」の修正

スマートフォン用のテーマは PC 用のテーマのテンプレートをコピーして作成したので、それらを修正する。

  • スマートフォン用には不要な画像などの要素や JavaScript 等の記述を削除や変更。
  • スタイルの指定を「style.css」に追記(jQuery Mobile の CSS の記述の後)。ブラウザのコードインスペクタで jQuery Mobile が付加する class 名を確認しながら作業。
  • PC 用のテーマの「style.css」から使えるものは利用する。
  • 必要であれば functions.php を変更。

jQuery の記述

jQuery Mobile では、Ajax によって各ページが読み込まれてコンテンツが DOM に追加されるため、DOM の ready ハンドラはサイトの最初のページを開いた時にしか呼ばれないので注意が必要。以下は参考にしたサイト。

独自の jQuery の記述は「jquery-1.9.1.min.js」と「jquery.mobile-1.3.2.min.js」の間に記述する。

<link rel="stylesheet" href="<?php echo get_stylesheet_uri(); ?>" type="text/css" /> 
  <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile.structure-1.3.2.min.css" /> 
  <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
  <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> 
  <script src="<?php echo get_template_directory_uri(); ?>/js/base.js"></script> //外部ファイル
  <script>  
  必要なスクリプトの追加
  $(document).bind("mobileinit", function(){ 
    $.mobile.ajaxEnabled = false;
  });
  $(document).on('click', 'p.show_map a', function(){
         $('div#map_container').slideDown(500);
    var address = $('p.address', $(this).closest('div')).text();
    if($('p.web1').text() !== '') {var url = $('p.web1 a',  $(this).closest('div')).attr('href');}
    showMap(address, $('p.venue').text(), url);  
    return false;
    });  
  ・・・
  $(document).on('swipeleft', "#single_news_content", function(){  
    if($('div.postlink p.fLeft a').attr('href')) {
      window.location =  $('div.postlink p.fLeft a').attr('href');
    }    
    });
  ・・・
  </script> 
  <script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script> 
<?php wp_head(); ?>
</head>

遭遇したいくつかの問題

  • コンテンツに記述してある住所を元に Google Map を表示するスクリプトがリフレッシュをしないと Google Map が表示されない。
    以下を記述してAjaxを使用しない遷移を設定することに。

    $(document).bind("mobileinit", function(){ 
        $.mobile.ajaxEnabled = false;
      });
  • ブログの投稿に挿入した画像(キャプション付き)が縮小されない。
    画像にキャプションをつけた場合は、wp-caption というクラスのついた「キャプション領域(div 要素)」が生成され、それに下記のように style で width が指定されている。

    <div id="attachment_409" class="wp-caption alignleft" style="width: 310px">

    caption ショートコードの出力を img_caption_shortcode フィルタで変更し style の指定を削除。

    function my_img_caption_shortcode($output, $attr, $content){
      extract(shortcode_atts(array(
        'id'    => '',
        'align'    => 'alignnone',
        'width'    => '',
        'caption' => ''
      ), $attr));
    
      if ( 1 > (int) $width || empty($caption) )
        return $content;
    
      if ( $id ) $id = 'id="' . esc_attr($id) . '" ';
    
      return '<div ' . $id . 'class="wp-caption ' . esc_attr($align) . '">' 
      . do_shortcode( $content ) 
      . '<p class="wp-caption-text">' . $caption . '</p>'. '</div>';
    }
    add_filter('img_caption_shortcode', 'my_img_caption_shortcode', 10, 3);
  • PC用では、ブログの投稿に挿入した画像をクリックすると Lightbox 風に画像を表示するため、画像に元の画像のリンクを付けているが、スマートフォン用では元の画像へのリンクは不要。
    以下のスクリプトを追加してスマートフォン用では元の画像へのリンクを無効に。

    $('div.blog_content a').filter(function() {
        if($(this).attr('href').search(/wp-content\/uploads/) != -1) {
          return true;
        }else{
          return false; 
        }
      }).css('cursor', 'default').click(function() {  
        return false;
      });

スワイプ(swipe)イベント

previous_post_link() や pagenavi()などで「次へ」や「前へ」のリンクがあるページでスワイプするとページが遷移するようにするために、以下を記述。

previous_post_link(), next_post_link() の場合、その部分は以下のようにマークアップしてある。

<div class="postlink news">
    <p class="fLeft">
      <?php previous_post_link('%link', __('&laquo; Previous')); ?>
    </p>
    <p class="fRight">
      <?php next_post_link('%link ', __('Next &raquo;')); ?>
    </p>
  </div>

リンク先は「’div.postlink p.fLeft a’」等に入っているのでそれを利用してページ遷移するようにする。

$(document).on('swipeleft', "#single_news_content", function(){  
    if($('div.postlink p.fLeft a').attr('href')) {
      window.location =  $('div.postlink p.fLeft a').attr('href');
    }    
    });
  
  $(document).on('swiperight', "#single_news_content", function(){  
    if($('div.postlink p.fRight a').attr('href')) {
      window.location =  $('div.postlink p.fRight a').attr('href');
    }    
    });

pagenavi() の場合は出力されるマークアップを見ると以下のようになっている。

<div class="pagenavi">
<span class="page-numbers current">1</span>
<a class="page-numbers ui-link" href="http://xxxx/xxxx/page/2/">2</a>
<a class="next page-numbers ui-link" href="http://xxxx/xxxx/page/2/">次へ »</a>
</div>

リンク先は「a class=”next page-numbers ui-link”」等に入っているのでそれを利用してページ遷移するようにする。

$(document).on('swipeleft', "#news_content", function(){    
    if($('div.pagenavi a.prev').attr('href')) {
      window.location = $('div.pagenavi a.prev').attr('href')
    }  
    });
  
  $(document).on('swiperight', "#news_content", function(){  
    if($('div.pagenavi a.next').attr('href')) {
      window.location =  $('div.pagenavi a.next').attr('href');
    }    
    });

テーマを自動で切り替えるプラグインをインストール

ユーザーエージェントによりテーマを自動で切り替えてくれるプラグインは以下のようなものがある。

長い期間アップデートされていないプラグインもあり、今回は「Multi Device Switcher」を使用。