無精で短気で傲慢なプログラマ

UNIX や web やプログラムの技術的なことを中心に。

Perl の web アプリ作成手法 その2

Perl の web アプリ作成手法 のつづき。

時間をみつけて調べてみたが、HTML::Template も Template Toolkit
も気に入らない。

HTML::Template は低機能すぎる。ある意味、その割り切りっぷりは
評価できるが、それを踏まえたとしても細かな仕様に不満がある。
たとえば、TMPL_LOOP 中から上位の TMPL_VAR にアクセスできない、とか。
die_on_bad_params=0 にすればアクセスできるが、チェック機能がすべて
OFF になってしまうので、そんなことはしたくない。

Template Toolkit はもっと気に入らない。なぜテンプレートごときで
独自の文法を覚えなければならないのか。

web 開発環境で一番好きなのは「Java Servlet + JSP で MVC」なのだが、
同類のテンプレートエンジンが Perl にもないものか。

…と思って調べてみたら、やっぱりあった。HTML::Mason
でも、Apache にモジュールを組み込まなきゃいけないのは嫌だなぁ。
PageTop

Perl の web アプリ作成手法

Perl による web アプリケーション生成のための手法・モジュールを、
わたしはよく知らない。

ずっと print 文でゴリゴリ書いていたが、最近は HTML::Template を
お試し中。モジュール作成者の手のひらで踊らされている感が嫌いなのと、
デファクトスタンダードが固まるのをずっと待っていたが、最近は開発効率の
あまりの悪さに耐えがたくなってきた。

まずは候補をリストアップ。

●print 文
 print 文をなめてはいけない。いろいろできる。
  print ""
  print ''
  print qq()
  print "@{[ $var ]}";
  print <<END; (ヒアドキュメント。変数展開あり)
  print <<'END'; (ヒアドキュメント。変数展開なし)
●HTML::Template
 変数置換 (TMPL_VAR)・ループ (TMPL_LOOP)・真偽判定 (TMPL_IF) が可能。
 TMPL_IF
  値が 1 か 2 か、などの判定はできない。真か偽かのみ。
  AND や OR はできない。TMPL_IF を複数個書いてネストさせよう。
   ●COND1 AND COND2
   <TMPL_IF NAME="COND1">
    <TMPL_IF NAME="COND2">
     COND1 かつ COND2 なら
    </TMPL_IF>
   </TMPL_IF>
   ●COND1 AND NOT COND2
   <TMPL_IF NAME="COND1">
    <TMPL_UNLESS NAME="COND2">
     COND1 かつ、COND2 でないなら
    </TMPL_IF>
   </TMPL_IF>
   ●COND1 OR COND2
   <TMPL_IF NAME="COND1">
    ほげ
   <TMPL_ELSE>
    <TMPL_IF NAME="COND2">
     ほげ
    </TMPL_IF>
   </TMPL_IF>
    → 同じことを 2回書かねばならないのがウザい。
 TMPL_VAR
  値が設定されていない場合に使用するデフォルト値を設定可能 (DEFAULT="HOGE")。
  テンプレート側で HTML エスケープ・URL エンコード可能 (ESCAPE="HTML" など。
  エスケープの種類は HTML, URL, JS)。HTML::Template-2.8 以降なら、
   HTML::Template->new(default_escape=>'HTML');
  で変数の一括エスケープが可能。例えば default_escape=>'HTML' とした場合、
   <TMPL_VAR NAME="FUGA">
    → default_escape により自動的に ESCAPE="HTML" 相当の処理が行われる
   <TMPL_VAR NAME="HOGE" ESCAPE="JS">
    → default_escape よりも個別に記述した ESCAPE="JS" が優先
  となる。アンエスケープはできないので、default_escape を使う場合は
   $tmpl->param(LINK => '<a href="hoge.html">fuga</a>');
  という、HTML の一部をパラメータとして渡す書き方がしづらくなる。
 TMPL_LOOP
  ループの初回・奇数回・偶数回・末尾などの判定が可能 (loop_context_vars=>1)。
  これを使うと perl の join 的なこともできる。
   <TMPL_LOOP NAME="ARRAY">
    <TMPL_VAR NAME="HOGE">
    <TMPL_UNLESS NAME="__last"__>,</TMPL_UNLESS>
   </TMPL_LOOP>
    → join(',', @ARRAY) のようなもの
  配列について TMPL_IF や TMPL_UNLESS を使うと、空かどうかを判定できる。
   <TMPL_IF NAME="ARRAY">
    <TMPL_LOOP NAME="ARRAY">
     <TMPL_VAR NAME="HOGE">
    </TMPL_LOOP>
   <TMPL_ELSE>
    データがありません
   </TMPL_IF>
 配列的なものを渡したくても、いちいちハッシュ化が必要なのは面倒。
 そういうときはこれ。
  $tmpl->param(HOGE_LIST => [ map { my %h=(FOO=>$_); \%h } @array ]);

 ◎HTML::Template::Ex
  <TMPL_EX>perlコード</TMPL_EX> という書き方ができる。
  <TMPL_SET NAME='...' value='...'> で値のセットが可能 (TMPL_VAR で参照できる)。
  TMPL_LOOP で参照可能な TMPL_SET も可能。
  <TMPL_VAR NAME="env_http_referer"> などと環境変数の参照が可能。
 ◎HTML::Template::Pro
  HTML::Template と HTML::Template::Expr の Perl/XS 版
 ◎HTML::Template::Extension
  ▼HTML::Template::Extension::DOC
   <TMPL_DOC>コメント</TMPL_DOC>。
   コメント内は最終的に出力されない。
  ▼HTML::Template::Extension::SLASH_VAR
   <TMPL_VAR NAME="parameter_name">プレースホルダー</TMPL_VAR>
   という書き方ができる。普通の HTML::Template なら、
   <TMPL_VAR NAME="parameter_name"> という書き方。
  ▼HTML::Template::Extension::CSTART
  ▼HTML::Template::Extension::HEAD_BODY
  ▼HTML::Template::Extension::IF_TERN
   3項演算子が使える。%cond?OK:NG%
  ▼HTML::Template::Extension::TAG_ATTRIBUTE_NORMALIZED
  ▼HTML::Template::Extension::DO_NOTHING
   何もしない。Extension 開発の際のサンプル
 ◎HTML::Template::Pro::Extension
  HTML::Template::Extension の Perl/XS 版
 ◎HTML::Template::Set
  <TMPL_SET NAME='...'>値</TMPL_SET> で値のセットが可能 (TMPL_VAR で参照できる)。
  HTML::Template::Ex の TMPL_SET と異なり(?)、
   <TMPL_SET NAME='...'>hoge<TMPL_VAR NAME="aaa">fuga</TMPL_SET>
  などと TMPL_SET 中に TMPL_VAR が使用可能。
 ◎HTML::Template::Expr
  TMPL_IF で真偽以上の判定が可能。
   <TMPL_IF EXPR="banana_count > 10">ほげ</TMPL_IF>
  TMPL_VAR で値の加工が可能。
   <TMPL_VAR EXPR="sprintf('%d', foo)">
  関数が使用可能
   <TMPL_IF EXPR="myfunc('hoge')">
   myfunc の中で TMPL_VAR は使えるのか?
 ◎HTML::Template::HTX
 ◎HTML::Template::HashWrapper
  param で指定するのではなく、new で全パラメータを
  指定できるようにする。
●CGI.pm
●CGI.pm + HTML::Template
●Template Toolkit
●HTML::Mason
●HTML::Mason::CGIHandler (MVC)
●Embperl
●HTML::FillInForm
●HTML::Seamstress
●CGI::Application
●Sledge
●Catalyst

※上記リストは新しいものを見つけるたびに更新します。

関連

PageTop

GD::Graph グラフ作成マシーン

GD::Graph グラフ作成マシーン って、perl + GD::Graph の機能検証するときに結構便利では?

と自画自賛してみたりする (誰も言ってくれないので)。
PageTop

label 要素のススメ

「あらゆるラジオボタン・チェックボックスに label 要素をつけよう運動」を
今日から推進します。

たいていのブラウザにおいて、ラジオボタンやチェックボックスのサイズは非常に
小さいです。わずか数ドットしかない狭い領域をクリックしなきゃならないような
インタフェースは腐っています。このようなインタフェースを放置するのは利用者を
馬鹿にした行為といっても過言ではありません。

というわけで、label 要素をつければ入力が飛躍的に楽になります。


○ label 要素使用 (ラジオボタンx・チェックボックスx をクリックすると、対応するボタンにチェックが入る)






× label 要素未使用 (ラジオボタンx・チェックボックスx をクリックしても無反応)

ラジオボタン1
ラジオボタン2
ラジオボタン3
チェックボックス1
チェックボックス2

具体的には、以下のように input 要素に id を振ります。そして label for="対応するid" と
記述すれば OK です。なお、HTML 内で id の値は重複してはいけません (label 云々ではなく、
HTML の仕様)。

<input id="radio1" type="radio" name="hoge" value="1">
<label for="radio1">ラジオボタン1</label>
<input id="radio2" type="radio" name="hoge" value="2">
<label for="radio2">ラジオボタン2</label>
<input id="checkbox1" type="checkbox" name="hoge" value="1">
<label for="checkbox1">チェックボックス1</label>
<input id="checkbox2" type="checkbox" name="hoge" value="2">
<label for="checkbox2">チェックボックス2</label>

ちなみに google は、ほとんどのサービスにおいて label 要素を使用しており、
とても使いやすいです。Gmail を使っていると、ユーザインタフェースにここまで
こだわるか、と驚かされます。

Yahoo! Japan は、label 要素を使用しているサービスもあれば、
使用していないサービスもあります。がんばりましょう。


参考: フォームとアクセシビリティ
PageTop

長すぎる部分が勝手に隠れるテーブル

Gmail の吐いた HTML と 2時間も格闘して得た技。

http://x68000.q-e-d.net/~68user/bugnote/bugindex.php?projectid=1

ウィンドウサイズを小さくすると、「要約」の列のみが勝手に隠れる。
その他の列は隠れない。Firefox・IE6 で確認。
PageTop