タグ別アーカイブ: HTML5

サイトC:WordPress3.5&Twenty Twelveに変更

去る2012年の12月、WordPressのヴァージョン3.5が正式リリースになりました。

このブログでは、WordPressをヴァージョン2.9から使用しており、大きなアップデートとしては3.0へのアップデートを一回経験しています。以降は小数点以下のアップデート経験しか無いのですが、ヴァージョン3.4へのアップデートあたりから、3.0リリースの補完的アップデートとは異なった新たなWordPressへの脱却を感じさせるアップデートになってきたという印象があります。今まではWordPress以外のWEBアプリケーションの機能をなぞるような意気だったのが、最近ではWEBアプリケーションのトップをひた走るという自負すら見えてくるといいますか。たとえば、3.4でMovableTypeやBlogger由来のAPIを使わなくても、自前のAPIだけでxml-rpc投稿ができるようになったことなどが例として挙げられましょう。

とは言え、あまりWordPressの機能を使い込んでいない人間からすれば、そうした目に見えないアップデートはさして重要ではありません。
今回のアップデートの目玉の一つは、デフォルトテーマのTwenty Elevenのグレードが一つあがり、Twenty Twelveに生まれ変わったことです。このブログでも早速(いや、単体では8月あたりにリリースになっていたことは知ってますよ)導入してみました。

Twentyシリーズはヴァージョンアップのたびに目玉仕様を乗っけてくるのですが、Twenty ElevenがHTML5への対応だったのに対し、今回のTwenty TwelveはRetina対応とレスポンシブデザインとなっています。確かにTwenty ElevenをiphoneやiPadで見たときの間延び感は気になっていたので、アップデート後真っ先にその点をチェックしてみましたが、そつのないスッキリとしたデザインに統一されています。

iPadでのTwenty Twelveテーマ

iPadでのTwenty Twelveテーマ

ちなみに、余談ではありますがこのスクリーンショットを撮影するのに使ったchrome機能拡張は、Rippple Emulatorといい、各種スマートフォン、タブレットの縦横表示チェックの他、本体の振動やGPSもテストできる便利ツールです。

メニューがデフォルトで展開されず、ユーザアクションで開く形になったのがスマートフォンサイトっぽいですね。サイドバーは投稿下部に付き、Twenty Elevenのような面倒くさい設定も要りません。
今後はこれをたたき台にしたデザインのページが増えそうですね。


overflow:hiddenとページ内リンク同時使用による不具合

以前、floatを使った要素の回り込みを実現する際のおまじないとして、overflow:hiddenを紹介しました。clearfixテクニックを使う方法と比べると手軽で、表示上の不具合に対し応急処置となるケースが多いものですから、私のような横着者はとりあえずどの要素にもoverflow:hiddenを適用しておくよう習慣づいてしまっています。

ただ、この手軽な方法にも落とし穴があります。overflow:hiddenを使った要素内で、URLの末尾に#idという形でパラメータを付与し辿るページ内リンクが行われた場合、当の要素が他の要素の下に潜り込んでしまうといった表示不具合が起こる場合があるのです。この不具合は、overflow:hiddenとページ内リンクの組み合わせで必ず発生する不具合というわけでもないため、長くWEB制作に携わりながら、一度もこうした現象に見舞われたことがない、したがって急にそうした不具合に当たって足下を掬われるといったケースがあり得るかもしれません。

対処法はとりあえず、ページ内リンクをあきらめるかoverflow:hiddenをあきらめるかといった、敗北主義的なものしかありません。幸いfloatの回り込み指定の実現方法はoverflow:hiddenだけではありませんし、ページ内リンクについてはJavaScriptを使ったページ内スクロールに変更して衝突を避けることもできます。ページ内スクロールの実現には、こちらのサイトsmoothScroll.jsなどが便利です。

この不具合はほとんどのブラウザで共通して発生してくれる優れた不具合なのが幸いですね。仕様的なものなので、あるバージョンから突然修正が入り対処を行った部分の労力が無駄になることもありません。


clearfixのささやかな覚え書き

複数カラムのブログテンプレートなどを作成するとき、一般的にはCSSのfloatプロパティを使ってレイアウトを行います。たとえば2カラムで左にサイドメニュー、右に記事本文というレイアウトは、以下のようなhtml&CSSになるでしょう。

HTML部
<div class="wrapper">
<div class="sidebar">
//サイドメニューエリア本文
</div>
<div class="articlearea">
//記事本文
</div>
</div>
 
CSS
.sidebar{
float : left;
}
.articlearea{
float : right;
}

カラムを包括する親ボックスの大きさが指定されており、各カラムが親ボックスの高さの値を超えないときには、特にレイアウト上の問題は起こりません。しかしながら、ブログのようにカラムの本文が可変長で親ボックスの高さを超えるケースが考えられるときには、カラムが親ボックスをはみ出て表示されてしまい、レイアウトが崩壊してしまいます。

はみ出たカラム

これは、ボックス内でfloat指定されている要素の大きさが親ボックスの大きさを決める際に参照されないという特性によるものです。したがって最も仕様に適った解決は、floatさせた要素の後にclearプロパティでfloat解除した要素を設けることです。空のdiv要素やvisibilityプロパティをhiddenにしたhr要素、br要素がよく使われます。

HTML部
<div class="wrapper">
<div class="sidebar">
//サイドメニューエリア本文
</div>
<div class="articlearea">
//記事本文
</div>
 
//空divの場合
<div style="clear : both"></div>
 
//非表示にしたhrまたはbr
<hr class="clearfix" />
<br class="clearfix" />
</div>
 
CSS
.sidebar{
float : left;
}
.articlearea{
float : right;
}
.clearfix{
visibility : hidden;
clear : both;
}

この方法はシンプルですが、ページのセマンティック(意味)としてはデザイン修正の為だけの無意味な要素をhtmlに加える事になるので好ましくありません。
そこで、無駄な要素を加えることなくレイアウト修正を行う、名前もそのまま”clearfix”というテクニックが開発されました。

HTML部
<div class="wrapper">
<div class="sidebar">
//サイドメニューエリア本文
</div>
<div class="articlearea">
//記事本文
</div>
</div>
 
CSS
//clearfixの追加部分
.wrapper:after{
content : "";
display : block;
clear : both;
}
//IE6,7用
.wrapper{
zoom : 1;
}
 
.sidebar{
float : left;
}
.articlearea{
float : right;
}

CSSのafter疑似要素を使って、floatを解除する要素を無理矢理埋め込むという形です。この方法ならば、検索エンジンやアプリケーションがページのhtmlのみを取得する場合に、解釈の混乱をひきおこす無駄な要素が発生しません。IE用の追加部分については、独自仕様のhasLayoutというプロパティがtrueであれば子要素のfloatを親ボックスのサイズ計算に含めるという特性を利用しています。無害なレイアウト指定(zoom:1;やwidth:100%;など)であれば何でも良いのですが、ソースの意図を明確にする為にzoom:1;の指定をしている場合が多いようです。

ここまでがclearfixの説明です。先に述べた通り、floatを解除する要素を最後に加えるという解決方法ですね。

それに対して、親ボックスのoverflowプロパティを明示的にhiddenと指定することで、親ボックスのサイズ計算方法を変えるというテクニックもあります。overflowプロパティとは、ボックス内の要素がボックスのサイズを超えてしまった際の表示方法についての指定で、何も指定しない状態はvisible、つまりはみ出た部分も表示する指定になります。これをhiddenと指定した場合、はみ出す部分のみ非表示となると同時に、ボックスの高さの計算式にfloatさせた要素も含まれるようになります。

HTML部
<div class="wrapper">
<div class="sidebar">
//サイドメニューエリア本文
</div>
<div class="articlearea">
//記事本文
</div>
</div>
 
CSS
.wrapper{
overflow : hidden;
//IE6,7用
zoom : 1;
}
.sidebar{
float : left;
}
.articlearea{
float : right;
}

場当たり的な対応ではありますが、セマンティックを汚染せずさらに簡単なので、こちらをバカの一つ覚えのように使ってしまって良いかもしれません。


Conceptual:Ajax対応CSV表示プログラムOnlyCSViewを計画する

以前、PHPの便利なfgetcsv関数を使ったCSV表示プログラムを書きました。このプログラムはソースコードを読んで判るように、フォームで受け取ったパスのファイルを一時ファイルとしてコピーし、関数に与え処理した結果をページの再読み込み時に表示という手順を踏んでいます。もちろんPHPはサーバサイドで呼ばれるので、結果の表示に最低一回の画面遷移を必要とするnon-Ajaxなプログラムです。今回はこのプログラムを新しくAjax対応させて、OnlyCSViewという名前のWEBサービスにする計画を立てました。

完成までには色々と仕様的な壁にぶち当たりました。その過程をここに順を追って記しておくことで、これからPHPプログラムをAjax対応させようとする方、ならびに自分自身が同じ轍と格闘しないようにしようと思います。

Ajax対応のキモ 〜jQuery.post命令でPHPerにも直感的に

まずは今回のajax対応に関しては、jQueryを使うということに決めました。理由としてライブラリを使わない素のJavaScriptでの開発は、非同期処理実装のためブラウザ毎に異なった命令を使わなければならないということがあり、面倒臭くスマートでないからです。面倒臭いことは時にプログラミングの醍醐味でもあったりしますが、できればメイン部分の処理か、あるいは誰もやらないような事の方に労力をかけたいと思いますよね。
Ajax部分はPHPプログラムで慣れたPOSTを使いたかったので、jQuery.post命令を使います。

jQuery.post(引数1,引数2,引数3,引数4)
引数1 呼び出すurl 今回の例ではcsvtojson.phpという処理部分のファイル
引数2 呼び出し先に与えるデータ。複数の場合はラベルをつける {"label1" : data1,"label2" : data2}
PHP側では$_POST["label1"]のように取り出せる。省略可
引数3 エラーも含め値が帰ってきたら行う処理。省略可
引数4 データの種類。省略可

csvtojson.phpには何を書けば良いでしょうか。PHPのみで作ったCSV表示プログラムの中から、ユーザが指定したCSVファイルが何かを知る機能、と、配列に格納したデータを表に整形する機能、を取り除いて、この2つの機能はJavaScript側で実装するようにします。そうすることで、csvtojson.phpは入力がファイルパス(文字列)、出力が配列という単機能のプログラムにまとまります。
PHPとJavaScriptで配列の受け渡しをするには、JSONというフォーマットを使います。上に書いたjQuery.postの説明の引数2のところで既に出してしまいましたが、何の事はなくJavaScriptのオブジェクトの書式と同じです。ただしラベルは必ず文字列でなければなりません。PHPの配列をJSONにエンコード/デコードする際には、配列をjson_encode関数もしくはjson_decode関数に与えてやるだけで済みます。最後にエンコード済みのJSONフォーマットをechoして、csvtojson.phpの仕事は終わりです。

jQuery.postの方では、引数4に”json”と指定してやる事で、帰ってきたデータをJSONと解釈してくれます。その他にとりうるオプションとして、”xml”,”html”,”script”,”jsonp”,”text”があります。もしCSVの整形表示部までcsvtojson.phpに担当させる設計にするならば、整形後のhtmlを”html”で受けるといった具合です。引数3はfunction(){…と結果が帰ってきた際の処理を匿名関数でそのまま書いてしまえば良く、さらにこの関数の引数として宣言された変数で、帰ってきたデータを受けられます。
実際にjQuery.postでcsvtojson.phpを呼んだ部分はこのようになりました。

jQuery.post("csvtojson.php", {"filepath" : filepath,"charset" : charset},function(data,status){
//処理。変数dataはcsvtojson.phpが返してきた値(JSON)。
//data[i][j]のようにアクセスして値を取り出せる。省略可。
//変数statusには成功、失敗などのステータスが入る。省略可。
},"json");

Ajax対応落とし穴 〜JavaScriptはファイルのローカルパスを知ることができない

メイン処理部分は後回しにして、csvtojson.phpに与えるローカルファイルパス取得の処理を考えます。JavaScriptではWEBページ内のフォームに入力された値を、フォームのname属性で特定して操作する事ができます。したがって、ユーザーに<input type=”file”>でローカルファイルをセットさせて、その値を取り出す。理論的にはそれで大丈夫なはずです。

//HTML部分
<input type="file" name="csvfile" accept="application/excel" />
.
.
.
//JavaScriptでセットされたパスを取得
var filepath = document.controlls.csvfile.value;

ところが、実際にはこの書き方ではパスを取得できません。試しに上のコードに続いてalert(filepath);というコードを実行すると、結果は以下のようになります。

fakepath

fakepathという単語で、実際のファイルパスがマスキングされています。良く言われる、JavaScriptではセキュリティ対策のためローカルファイルにアクセスできないという表現ですが、ファイルへのアクセスにエラーが出るという実装ではなく、そもそもローカルファイルパスを知る事ができないという仕様によるもののようです。したがって、PHPに受け渡してしまえば処理できるというものでもありません。

Ajax対応のキモ 〜HTML5のFile APIを使ってみる

そこで、ローカルファイルアクセスの問題を克服したとこちらも良く言われる、HTML5を使います。HTML4以前で作られたページでHTML5の機能を有効にするには、DOCTYPE宣言をこれまでの複雑なものから、<!DOCTYPE html>というシンプルなものに変えるだけです。詳しい説明はまた別のエントリで行いますね。
HTML5は2014年の正式勧告を目指して仕様策定中という段階であり、API導入の状況は各ブラウザによってまちまちです。今回使用するFile APIは、現時点でFirefoxとChromeが対応、Safariは部分的対応といった状況です。今回のプログラムがFirefoxおよびChromeのみ対応となってしまうのは、このSafari未対応部分の機能を使うからです。
File API対応ブラウザであれば、<input type=”file”>でユーザが選択したファイルに、name属性でなくid属性でアクセスできます。

//HTML部分
<input type="file" id="csvfile" accept="application/excel" />
.
.
.
//JavaScriptでセットされたファイルを変数に代入
var userfile = document.getElementById("csvfile").files[0];
//ファイル名取得
var name = userfile.name;
//サイズ取得
var size = userfile.size;
//タイプ取得
var type = userfile.type;
//urn取得
var urn = userfile.urn;

File APIは複数ファイルの選択にも対応しているため、セットされたファイルはインデクスで指定して取り出します。一つしかセットされていない場合はfiles[0]で指定します。
このurnというプロパティが、いかにもファイルパスだろうという安易な予想をしたのですが、実際ローカルファイルをセットして値を取得してみると空でした。大抵のFile APIの解説でも省略されているのですが、URNというのは、URLと同じくICANNによって唯一性が保証されたファイル名のことで、パスのようにユーザが主体的に値を設定せずとも存在しているものではないようです。いずれは活用するようになるかもしれない名前空間といったところでしょうか。

Ajax対応落とし穴 〜objectURLはセッションを越えられない

File APIにはローカルファイルのパスを知る2通りの方法が用意されています。どちらの方法も発想の逆転で、指定されたローカルファイルに新しくパスを与えるということでセキュリティ上の問題をクリアしています。方法の1つ、objectURLはファイルへの参照を示し、2つ目のDataURLはurl文字列にファイルの内容をそのまま展開してしまいます。もちろんobjectURLの方が圧倒的にバイト数が少ないので、Ajax通信で使うフォーマットとしてはこちらを採用したくなります。

//HTML部分
<input type="file" id="csvfile" accept="application/excel" />
.
.
.
//objectURLを作成
 
//Firefoxの場合
var filepath = window.URL.createObjectURL(document.getElementById("csvfile").files[0]);
//Chromeの場合
var filepath = window.webkitURL.createObjectURL(document.getElementById("csvfile").files[0]);
 
//jQuery.postに与える
jQuery.post("csvtojson.php", {"filepath" : filepath},function(){
//処理
},"json");

しかしながら、こうして作成したObjectURLはセッションを越えられないため、csvtojson.phpはこれを無効なパスと解釈します。残念ではあるのですが、ObjectURLにはまた別のところで活躍してもらうとしましょう。

Ajax対応のキモ 〜filereaderでData URLを作成しパス渡しを実現

Data URLというのは、先程も述べましたがファイル内容をそのまま展開してしまったURLのことで、このURLの解釈自体は大抵のブラウザが対応しています。具体的な採用例としては、Google画像検索で表示される画像がData URLです。File APIのfilereaderではアクセスしたローカルファイルをいくつかのフォーマットに展開することができるのですが、その内の一つのフォーマットがData URLなのです。filereaderの使い方を見てみましょう。

//HTML部分
<input type="file" id="csvfile" accept="application/excel" />
.
.
.
//filereaderインスタンスを作成し、メソッドでファイル読み込み
var reader = new FileReader();
//バイナリ文字列へ
reader.readAsBinaryString(document.getElementById("csvfile").files[0]);
//テキストへ(第二引数は文字コード)
reader.readAsText(document.getElementById("csvfile").files[0],"UTF-8");
//Data URLへ
reader.readAsDataURL(document.getElementById("csvfile").files[0]);
 
//読み込み終了時の処理(非同期なので他のステータスにもメソッドあり)
reader.onload = function(e){
//変数filepathに結果を代入
var filepath = e.target.result;
};

filereaderを使う場合には、FirefoxとChromeの分岐処理は必要ありません。作成されたData URLを、jQuery.postでcsvtojson.phpに送ると正常に処理されました。トラフィックには優しくない方法ですが、とりあえず既存PHPプログラムのAjax対応への糸口が見えました。

$.post("csvtojson.php", {"filepath" : filepath},function(data, textStatus){
var $table = $('<table id="ct"></table>');
for(var i in data){
var $onerow = $("<tr></tr>");
for(var j in data[i]){
$("<td></td>").text(data[i][j]).appendTo($onerow);
}
$onerow.appendTo($table);
}
$("#tablearea").append($table);
},"json");

csvtojson.phpが返してきたJSONをテーブルに整形しています。こちらもjQueryを使って幾分楽をしていますね。

ということで、とりあえず最低限のAjax対応が果たせました。デモはこちらから。
段々肉付けをして便利なサービスにしていきたいと思います。


プログラム・設定ファイルのコメント書式一覧

個人的によく使うプログラミング言語・設定ファイルのコメント書式を、まとめてメモしておこうと思います。

コメント書式一覧
言語・設定名 コメントの書式 備考
XHTML(HTML)・HTML5 <!‐‐ ここにコメントを書く ‐‐> 複数行も可能です。コメント中の連続したハイフン(‐‐)の使用は禁止されています。
CSS /* ここにコメントを書く */ 複数行も可能です。
PHP // ここにコメントを書く 一行のコメント。複数行はダメ。C++形式。
#ここにコメントを書く 一行のコメント。複数行はダメ。ShellやPerl形式。
/* ここにコメントを書く */ 複数行も可能です。
JavaScript・ActionScript // ここにコメントを書く 一行のコメント。複数行はダメ。C++形式。
/* ここにコメントを書く */ 複数行も可能です。
Objective-C・Swift // ここにコメントを書く 一行のコメント。複数行はダメ。C++形式。
/* ここにコメントを書く */ 複数行も可能です。
SQL ‐‐ ここにコメントを書く 一行のコメント。複数行はダメ。
/* ここにコメントを書く */ 複数行も可能です。
php.ini(PHPの設定ファイル) ; ここにコメントを書く 一行のコメント。複数行はダメ。
.htaccess(サーバアプリケーションの設定ファイル) # ここにコメントを書く 一行のコメント。複数行はダメ。

これからもうちょっと複雑なWEB制作を始めたら、表の項目が増えていく可能性もあります。そして、間違っている箇所を発見したら指摘していただけると非常に助かります。