スマホとPCの表示を別ファイルに分けてコーディング

WordPressで作ったサイトを、後付でスマホ対応にしたい。

テンプレートを使うならいいけど、自分でレスポンシブサイトを作るのは嫌だ。
既存サイトに後付なら、もっと嫌だ。
最悪だ。
いっそリニューアルにしてくれ。
なので、テーマファイル内に細工をして、PCとスマホで表示の切り分けをする。

例)テーマ内のsingle.phpでやってみる

まず、templateというフォルダを作成し、その中にpc.phpとsp.phpを設置。
それぞれのファイルにPC用、スマホ用の表示に最適化したコーディングをする。
pcからアクセスがあった場合はpc.phpをスマホの場合はsp.phpを呼び出すようにする。

こんな感じ。

if ( spSwitch() == 'pc' ){
	include  get_template_directory() . '/template/pc.php';
	exit();
}else{
	include  get_template_directory() . '/template/sp.php';
	exit();
}

function spSwitch(){
	$ua = $_SERVER['HTTP_USER_AGENT'];
	$pf = ((strpos($ua,'iPhone')!==false)||(strpos($ua,'iPod')!==false)||(strpos($ua,'Android')!==false)||(strpos($ua,'BlackBerry')!==false)||(strpos($ua,'Windows.Phone')!==false));

	if ($pf){
		return 'sp';
	}else{
		return 'pc';
	}
}

もちろん、別ファイルを呼び出さず、全部single.phpに書いてもいいけど、ソースが見にくくなるのでいや。
categoryやarchiveでも、templateフォルダ内のファイル名を変えて複数用意すれば同じことができる。

IE9でグラデーション

モダンブラウザならそのままCSSで。
IE6~IE8はPIE.htcを利用。
IE9はSVGで処理してきたけど、別ファイルを作成するなど、色々手間がかかる。

調べてみると、フィルターを使う方法がよく検索にヒットしたけど、欠点がある。
例えば、ボタンなどでグラデーションを使いたいとき。
フィルターで処理すると、display:blockを指定していても、aタグ内の文字の部分にしかマウスが反応しなくなってしまう。

ので却下。

こちらが良さそう。

SVG Gradient Background Maker

来年のXPサポート終了でIE6もようやく絶滅してくれるが、IE9でさえこの程度のサポート。
IE10はようやくまとも。
でも、問題は古いブラウザを以下に駆逐するか、なんだけどね。
期待するだけ無駄だけど。

placeholderでレイアウトが崩れる

iphoneで確認(safari、chromeとも)。
inputなどにplaceholderでグレー文字を表示させるのは、HTML5から可能になった。
が。
レスポンシブデザインでフォームを作る仕事にて、placeholderに思わぬ落とし穴。

読み込み・・・OK.
iphoneを横向きに・・・OK.
iphoneを縦に戻す・・・NG.

読み込み時OKだったのに、一度横向きにしてから縦に戻すとレイアウトが崩れる。
placeholderを外すと直るので、これが原因だと思われる。

今のところ、placeholderを諦めるしか対応策なし。

早く直してほしい。

Advanced Custom Fieldsのデータをプレビューしたい

Advanced Custom Fieldsは非常に便利なのだけど、散々作りこんだ挙句にプレビュー出来ないことに気付いた。
今後も使い続けたいので、何とか解決方法を見つけようと四苦八苦・・・。

キレイな方法ではできなかったけど、一応下記のやり方で目的は達せられた。

step1.
SESSIONを使うので、/wp-config.phpの最後に以下を追記

if (!session_id()) session_start();

step2.
プレビューを押されたときのアクションにフックする。
使用しているthemeフォルダ内のfunctions.phpに追記。

function myCfPrev(){
    if ( !empty($_POST)){
        $_SESSION['posts'] = myHtmlSpecialChars($_POST);
    }
}
add_action( 'wp_insert_post', 'myCfPrev' );
// myHtmlSpecialCharsは配列の中もHTML エンティティに変換。不要なら外す。
function myHtmlSpecialChars($string) {
    if (is_array($string)) {
        return array_map("myhtmlspecialchars", $string);
    } else {
        return htmlspecialchars($string, ENT_QUOTES);
    }
}

プレビューボタンを押すと、Advanced Custom Fieldsを使って追加したフィールドは、「field_数字」という名前で$_POSTに格納される。
本来のフィール名との結び付けができなかったので、Wordpressの投稿画面のソース(Firebugなど使うと便利)から、Advanced Custom Fieldsを使って作成したinputフォームなどを調べ、イチイチ取得しなければならなかった。

上記で$_SESSION[‘posts’][‘fields’][‘field_数字’]にそれぞれのデータを格納できる。
また、$_SESSION[‘wp-preview’]に、「dopreview」が入る。
更新ボタンをクリックした場合は、$_SESSION[‘wp-preview’]は空。

$_SESSION[‘wp-preview’]の値を調べて条件分岐し、プレビューの場合はプレビューデータを表示するようにする。

画像の場合は、もう少し手間をかける。
画像のURLを格納したwp-postのpost_idが格納されているので、その値を使えばいい。
例えばこんな感じで。

$img_url = wp_get_attachment_image( $_SESSION['posts']['fields']['field_数字],'full', false );

もっとスマートなやり方があればいいのだけど、今の自分ではこれがやっと。
面倒なやり方だけど、手も足も出ない状況からは脱却できたので、メモ。

WordPress高速化への取り組み2

高速化への取り組み1では主にキャッシュ系のプラグインをメモ。
今回は画像系。

WP Smush.it
画像を劣化させずにファイルサイズを縮小してくれるオンラインサービス、Smush.itを利用できる。
管理画面のメディアからWordpressにアップ済みのファイルを個別/一括で利用可能。
Smush.itはよく失敗があるらしいので注意。
結果はメディア画面に表示されるので、失敗しても不安はない。
画像アップロード時にもSmush.itが利用できる設定も選べるが、アップロードが激遅になるので注意。

PNGGauntlet
プラグインではなく、ツール。
PNG限定だけど一括して画像を劣化させずにファイルサイズを縮小してくれる。
英語。
設定はデフォルトのままでも問題なし。
http://pnggauntlet.com/

ファイルの書き出しはファイルサイズ縮小の面でもFireworksが優秀だけど、職場にしかない。
個人作業のときは上記が有用なのでメモ。

ちなみにこのブログでは全く高速化の取り組みをしていない・・・。

WordPress高速化への取り組み1

今更だけど、Wordpressは遅い。
高速化に取り組んだメモ。

高速化が期待できるプラグイン。

WP Hyper Response
WordPressのレスポンスを向上させるプラグイン。
詳細はこちら

W3 Total Cache
ページなどをキャッシュできる。
データベース、オブジェクトキャッシュを有効にするとサーバーへの負担が増すらしいので、注意。
不安な場合はページキャッシュのみで。

MO Cache
日本語などマルチバイト環境の翻訳ファイルである.moファイルを読み込んだオブジェクトをキャッシュする。
W3 Total Cacheと併用し、オブジェクトキャッシュを有効化する必要あり。
もしくは、別のキャシュプラグインWP File Cacheなどと併用。

WP-DBManager
データベースの最適化。
その他、バックアップなども取れるので非常に有用。

毎回既存サイトの管理画面からチェックしてたので、メモ。

IE7,8で半透明画像(png)のopacityをいじる場合

IE7,8で半透明画像(png)のopacityをいじる場合。

普通にやると、半透明の部分が真黒になる。

解決法
AlphaImageLoaderを使う

ただし、色々とクセがあるので注意。

AlphaImageLoaderを使うと、背景に画像を一枚作ってしまう。
そのため、まんま導入すると画像が二枚重なる→半透明の部分が濃くなる

回避方法
AlphaImageLoaderを適用した画像を、透過PNG(1*1px)で置き換える。

その他注意点
aタグでimgを囲んで処理する事が多いが、aタグをdisplay:blockにしておき、widthとheightをimgと同じサイズにしておかないと上手く動かない(要検証)。
さらに、img自体にもcssでwidthとheightを指定した方が無難(要検証)。
過程でアレコレやったのでどれが必須かわからなくなってしまった。

以上をふまえてから、実際にはこんな風に書く。

$(function(){
	fixIeOpacity();
});

function fixIeOpacity(){
	var ua = window.navigator.appVersion.toLowerCase();
	if(ua.indexOf("msie 7.") != -1 || ua.indexOf("msie 8.") != -1){
		$("a img[src *= '.png']").each(function(){
			var src = $(this).attr('src');
			$(this).css({
				'filter': 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+src+'", sizingMethod="scale");'
			}).attr("src","../img/cmn/spacer.png");
		});
	}
}

上記、”../img/cmn/spacer.png”が透過PNGなので、それぞれの環境で置き換え。
a img となっているのは、hover時に半透明にしていたため。

もう少しキチンと書かないと汎用性には乏しいけど、同じ症状でハマッた時のヒントにメモっておく。

Ajax使った後のjQueryでのDOM操作

例えばAjaxで読み込んだ部分でclickイベントを拾いたいときは、liveを使えばいいのだけど。
今日はこんな風に書いたら、IE7で動かなかった。

$(function(){
	$(".hoge").live('click',function(){
		var target = $(this).attr('href');
		...略
	
	});
});

IE7だと、’herf’からうまく値を取得できない。(6は無視。)
なんでだー、と考えてたけど、メンドクサイので良く考えずに取得したい値を’herf’ではなく’rel’に設定してみた。
動いた。

一応、メモっておこう。