AJAXでWebフォームの使い勝手を向上させる

問題

HTMLで書かれたデータを取り込むおよびHTMLを動的に作成するで作成したプログラムを活用して、抽選番号を1桁入力するごとに動的に当選番号候補を表示するプログラムを作成したい。

解答

AJAXの仕組みを利用する。AJAXといっても基本的な仕組みはCGIだ。Open usp TukubaiではCGI向けのコマンドとしてcgi-nameコマンドを提供している。cgi-nameを使ってブラウザから渡される引数を取得し、照合処理を済ませ、結果をブラウザに返す。JJAXの場合はHTMLを最初から作り直すのではなく、ブラウザ側で一部を書き換えてもらうための情報を渡すわけだが、ユニケージ開発手法流にこなすなら部分的なHTMLテキストを作って返す。

#!/bin/sh
#
################################################################
# LOTTERY.AJAX 当せん番号チェックエンジン+AJAXインターフェース
#
# Written by N.Tounaka(tounaka@usp-lab.com) / Date : 7 Sep.2012
# Arrenged by USP MAGAZINE(mag@uap-lab.com) / Date : 8 Sep.2012
################################################################

# 環境変数のセット
export LANG=ja_JP.UTF-8

# シェル変数のセット
homedir=$(pwd); homedir=${homedir%/*}
htmd=$homedir/HTML
pomd=$homedir/POMPA
kind_list=$pomd/KIND_LIST
lottery_dat=$pomd/LOTTERY_DAT
tmp=/tmp/$$

# POSTメソッドでのデータの受け取り
dd bs=$CONTENT_LENGTH   |
cgi-name -d_ -i_        > $tmp-name

# 番号、組、宝くじ種類、名称の取得
number=$(nameread NUMBER $tmp-name)
group=$(nameread GROUP $tmp-name)
kind=$(nameread KIND $tmp-name)

# HTTPヘッダーの出力
cat << HTTP_HEADER
Content-type: text/html

HTTP_HEADER

# (a)何も選んでなければ何も出力しない
if [ $number = "_" -a $group = "00"  -a $kind = "00" ]; then

  sed -n '/OUTPUT/,/OUTPUT/p' $htmd/LOTTERY.HTML |
  sed 's/###AMOUNT###//g'                        |
  filehame -lFILEHAME - /dev/null

# (b)何か選んでいるとき
else

  [ $number = "_" ] && number=""
  [ $group = "00" ] && group=""
  lottery_name=$(nameread $kind $kind_list)

  #===== 番号チェック ==========================================
  # 入力先頭番号と当せん下X桁番号のマッチングを行う。(番号は6桁)
  #-----
  # 1:抽せん日 2:宝くじ名 3:等 4:賞金 5:組 6:番号
  cat $lottery_dat                                             |
  # 入力先頭番号と当せん番号を6桁にパディングする
  awk '{print $0,"XXXXXX"int($6),'$number'"XXXXXX"}'           |
  awk '{$7=substr($7,length($7)-5,6);$8=substr($8,1,6);print}' |
  # 先頭桁から数字をcheck,片方がXあるいは両方が同じ文字だとOK
  awk '{for(i=1;i<=6;i++){ch2=substr($7,i,1);ch2=substr($8,i,1);
      if(!(ch2=="X"||ch2=="X"||ch2==ch2)){next}};print}'       |
  delf 7 8                                                     |
  #===== 組チェック ===========================================#
  # 下Xケタ だとOK
  #-----
  # 1.XX組 / 2.組下1ケタX組 / 3.各組共通 / 4.下Xケタ
  LANG=C awk '{if($5~/^下[0-9]ケタ$/){print; next}             \
  # 入力組と当せん組を2桁にパディングする
      else if($5~/各組共通/){str="XX"}                         \
      else if($5~/組下1ケタ/){str="X"substr($5,14,1)}          \
      else if($5~/[0-9][0-9]組/){str=substr($5,1,2)};          \
      grp='$group'"XX";                                        \
  # 先頭桁から数字をcheck,片方がXあるいは両方が同じ文字だとOK
      for(i=1;i<=2;i++){ch2=substr(str,i,1);ch2=substr(grp,i,1);
      if(!(ch2=="X"||ch2=="X"||ch2==ch2)){next}};print}'       |
  #===== 宝くじ名チェック =====================================#
  awk '$2~/'$lottery_name'/{print}'                > $tmp-result

  # ===== 当せん最高金額レコードを求める =======================
  grep -E "[0-9.]*億円" $tmp-result |
  sort -nr -k4,4                    > $tmp-work
  grep -E "[0-9]*万円"  $tmp-result |
  sort -nr -k4,4                   >> $tmp-work
  grep -E "[0-9]*円"    $tmp-result |
  grep -vE "*万円"                  |
  sort -nr -k4,4                   >> $tmp-work

  #===== ファイルハメ ==========================================
  sed -n '/OUTPUT/,/OUTPUT/p' $htmd/LOTTERY.HTML               |
  sed 's/###AMOUNT###/'$(head -1 $tmp-work | self 4)'/g'       |
  filehame -lFILEHAME - $tmp-result

fi

rm -f $tmp-*
exit 0

上記プログラムを使ってみることができるようにサンプルアプリケーションをデプロイしておいたので、操作してみてほしい。

シェルスクリプトでの引数の取得

GETメソッドを使った場合、環境変数QUERY_STRINGに引数が格納されている。POSTメソッドでは標準入力に詰められて送られてくる。シェルスクリプトではこれらから値を取得する。Open usp TukubaiでPOSTメソッドから受け取るなら、dd(1)コマンドを使って環境変数CONTENT_LENGTHの分だけデータを受け取り、cgi-nameコマンドに流す。これで、URLデコードと受け取った変数を名前と値から成るテキスト表ができあがる。

Tukubai流のAJAXデータ生成

AJAXというとブラウザにはXMLで結果を返すことが多い。だがユニケージ開発手法でやるならそうではなく、部分的なテキストを作り、これを返す。これならブラウザは、innerHTMLメソッドを使って返された文字列を流し込むだけで済む。なるべくシェルスクリプトを使い、JavaScriptのコード量は抑えるという方針だ。

上記のプログラムではテンプレートHTMLから部分的に必要な部分を抜き出し、そこに結果をハメ込んでいる。こうして、部分的なHTMLテキストを生成している。

参考: CGIのデプロイ手順

  1. Open usp Tukubaiをインストール
  2. ファイルを次のようにデプロイ。POMPA以下のファイルはLOTTERY.DBを実行することで生成。ファイルのパーミッションを適切なものに設定
LOTTERY
├── CGI
│   ├── LOTTERY.AJAX
│   └── LOTTERY.CGI
├── HTML
│   └── LOTTERY.HTML
├── POMPA
│   ├── GROUP_LIST
│   ├── KIND_LIST
│   └── LOTTERY_DAT
└── SHELL
    └── LOTTERY.DB
  1. 環境変数、ファイルパスなどの環境に合わせて編集
  2. LOTTERY.DBをcron(8)を使うなどして定期的に実行、または手動で定期的に実行
  3. Webサーバの設定を編集

環境によってはHTML/LOTTERY.HTMLファイルに記載されているLOTTERY.AJAX呼び出し部分のパスを変更する必要がある点に留意しておきたい。

ユニケージユニバーサル・シェル・プログラミング研究所の登録商標。

usp Tukubaiユニバーサル・シェル・プログラミング研究所の登録商標。

※1 Open usp Tukubaiは最新バージョンを採用のこと。古いバージョンでは適切に動作しない可能性がある。

※2 USP MAGAZINE 2012 autumnより加筆修正後転載。

※3 本ページで公開されているプログラムとそれに付随するデータの著作権およびライセンスは、特に断りがない限りOpen usp Tukubai本体と同じMITライセンスに準拠するものとする。

Last modified: 2014-01-13 00:00:00