SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

PerlでデスクトップCGI

デスクトップCGIにinnerHTMLを使ったAjaxを導入する

デスクトップCGIでWebとデスクトップを融合する 第7回


Atomフィードリーダー(atom2msrdb_read_ajax3.cgi)

動作の概要

 データベースから読み出されたカテゴリとタイトルと更新日付がtext型の入力フォームで表示されるのは「atom2msrdb_read_js3.cgi」と同じですが、text型の入力フォームと一緒に記事本体を、データベースのcontentカラムあるいはsummaryカラムの内容をHTMLに変換し、「atom2entry.cgi」のAjax出力(次項で説明)をinnerHTMLを使って、<div name="r1" id="r1"></div>の位置に表示しています。また、[PREV]ボタン、[NEXT]ボタンで時系列で記事の表示を切り替えることができる機能も同じです。

スクリプト

設定項目

CGIパラメータ

 「atom2msrdb_read_js3.cgi」と同様に、AtomフィードのURLがパラメータです。

環境変数

 環境変数CGIDIRが設定されている必要があります。

JavaScript

 linksという配列に、「atom2entry.cgi」に渡すCGIパラメータ文字列を設定して出力します。AtomフィードのURLとentry主要素を特定する要素としてupdated要素、それがない場合はmodified要素、それもない場合はtitle要素を渡します。

Ajax

 「atom2msrdb_read_ajax3.cgi」がHTML出力する「atom2entry.cgi」へのリンクはJavaScriptの次のAjax関数の部分になります。Ajaxの記述の内容の構成は概略次のようになります。

  1. XMLHttpRequestのオブジェクトを生成します。これはブラウザに依存する関数を使います。XMLHttpRequest()はMozilla系のブラウザ、Msxml2.XMLHTTPは新しいインターネットエクスプローラ、Microsoft.XMLHTTPは古いインターネットエクスプローラ用です。その他のブラウザを使う場合には調べてください。
  2. XMLHttpRequestオブジェクトが変化するとどのように動作させるのかを関数に記述します。ここではXMLHttpRequestオブジェクトを引数とするdisplayContentという関数が実体となります。
  3. XMLHttpRequestオブジェクトにopenメソッドを適用します。GETメソッドで、「atom2entry.cgi」にパラメータを渡します。openメソッドの第3引数にtrueあるいは1を渡すか、全く渡さなかったときに動作します。falseあるいは0とするとまったく動作しなくなります。
  4. sendメソッドで送信します。
  5. displayContent関数にあるXMLHttpRequestオブジェクトのreadyStateというプロパティはドキュメントの読み込みが完了したときは、4になります。atom2entry.cgiの出力の読み込みが完了しない間は、「Loading...」という文字がボールド体のイタリック体で表示されていますが、完了すると、CGI出力に置き換わります。
atom2msrdb_read_ajax3.cgiのJavaScript出力に含まれるAjax関数
# atom2entry.cgiを呼び出すAjax関数
function msg(i) {
  var xmlhttpobj = null;
  try{
    xmlhttpobj = new XMLHttpRequest();
  }catch(e){
    try{
      xmlhttpobj = new ActiveXObject("Msxml2.XMLHTTP");
    }catch(e){
      try{
        xmlhttpobj = new ActiveXObject('Microsoft.XMLHTTP');
      }catch(e){
        return null;
      }
    }
  }
  xmlhttpobj.onreadystatechange = function(){
    displayContent(xmlhttpobj);
  }
  xmlhttpobj.open('GET', '$cgidir/atom2entry.cgi?' + links[i]);
  xmlhttpobj.send(null);
  function displayContent(xmlhttpobj){
    if(xmlhttpobj.readyState == 4){
      document.getElementById('r1').innerHTML
       = xmlhttpobj.responseText;
    }else{
      document.getElementById('r1').innerHTML
       = "<i><b>Loading...</b></i>";
    }
  }
}

 Ajaxについては下記のサイトを参考にすればよいでしょう。

スクリプト全体
atom2msrdb_read_ajax3.cgi
#!/Perl5.8/bin/perl.exe
use strict;
use warnings;
use DBI;
use CGI qw(:cgi);
use URI::Escape;

my $cgidir = $ENV{'CGIDIR'};
my $atomurl = "";
# Atom URL データの取得
if(param('atom')){
  # CGI で URL を取得する
  $atomurl = param('atom');
}elsif($ARGV[0]){
  # コマンドラインから URL を取得する
  $atomurl = $ARGV[0];
}else{
  $atomurl = "http://homepage1.nifty.com/kazuf/renewal_atom.xml";
#    print "Atom URL データが存在しない。\n";exit;# 終了する
}
# CGI 最初の部分の出力
print <<HEADER;
Content-type: text/html; charset=UTF-8

<html>
<head>
  <title>ATOM DB Browser</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <link rel="stylesheet" type="text/css" href="/mystyle.css" />
<script language="Javascript">
<!--
if(navigator.appCodeName.indexOf("Mozilla") != -1){
  document.write(
    "<link rel='stylesheet' type='text/css' href='/firefox.css' />");
}
//-->
</script>
<script language="Javascript">
<!--
HEADER

my $dbh
   = DBI->connect(
       "DBI:mysql:database=atomfeeds;host=localhost;port=3306",
       "root", "password",
       {'RaiseError' => 1});

my $sth = $dbh->prepare(qq{
  SELECT  atom,link,ver,title,tagline,modified,info,logo,
          icon,subtitle,updated
  FROM feeds WHERE atom = \"$atomurl\"
});
$sth->execute();

my $feed;
while(my $row = $sth->fetchrow_hashref()){
  $feed .= "<p><a href=\"$row->{link}\">$row->{title}</a></p><p>";
  if($row->{logo}){
    $feed .= "<img src=\"$row->{logo}\">";
  }elsif($row->{icon}){
    $feed .= "<img src=\"$row->{icon}\">";
  }
  $feed .= "$row->{subtitle}</p><p>$row->{updated}</p>";
}
$sth = $dbh->prepare(qq{
  SELECT atom, issued, published, link, title, content, name, 
         modified, created, id, updated, summary, category
  FROM entries WHERE atom = \"$atomurl\" ORDER BY updated DESC
});
$sth->execute();
my $link = "var links = new Array(";
my $count = 0;
my $esc_id;
my $linkstr;
my $firstlink;
my $year;my $cyear = (localtime(time))[5] + 1900;
my $mon;(my $cmon = (localtime(time))[4] + 1) =~ s/^(\d)$/0$1/;
while(my $row = $sth->fetchrow_hashref()){
  my $esc_atomurl = uri_escape($atomurl);
  if($row->{updated}){
    $esc_id = uri_escape($row->{updated});
  }elsif($row->{modified}){
    $esc_id = uri_escape($row->{modified});
  }else{
    $esc_id = uri_escape($row->{title});
  }
  $linkstr = "atom=$esc_atomurl\&id=$esc_id";
  $count++;
  if($count == 1){ $firstlink = $linkstr; }
  $link .= "\"$linkstr\",";
}
chop $link;print $link . ");\n";

$sth->finish();
$dbh->disconnect();

# CGI 最後の部分の出力
print <<FOOTER;
var i = 0;
function nextLink () {
  i++; if(i >= links.length) i = 0;
  msg(i);
}
function prevLink () {
  i--; if(i < 0) i = links.length - 1;
  msg(i);
}
function msg(i) {
  var xmlhttpobj = null;
  try{
    xmlhttpobj = new XMLHttpRequest();
  }catch(e){
    try{
      xmlhttpobj = new ActiveXObject("Msxml2.XMLHTTP");
    }catch(e){
      try{
        xmlhttpobj = new ActiveXObject('Microsoft.XMLHTTP');
      }catch(e){
        return null;
      }
    }
  }
  xmlhttpobj.onreadystatechange = function(){
    displayContent(xmlhttpobj);
  }
  xmlhttpobj.open('GET', '$cgidir/atom2entry.cgi?' + links[i], true);
  xmlhttpobj.send(null);
  function displayContent(xmlhttpobj){
    if(xmlhttpobj.readyState == 4){
      document.getElementById('r1').innerHTML
       = xmlhttpobj.responseText;
    }else{
      document.getElementById('r1').innerHTML
       = "<i><b>Loading...</b></i>";
    }
  }
}
//-->
</script>
</head>
<body onLoad="msg(0);">
<div class="emph">Atom DB Browser</div>
$feed
<hr>
<form name="form">
<p>
  <input type="button" value="PREV" onclick="prevLink ();"> 
  &lt;-----&gt; 
  <input type="button" value="NEXT" onclick="nextLink ();">
</p>
<div name="r1" id="r1"></div>
</form>
<hr>
</body>
</html>
FOOTER

exit(0);
# マークアップ記号の実体参照デコード
# 文字実体参照と数値文字参照の両方に対応
sub entities_decode{
  my($str) = @_;
  $str =~ s/(&lt;|&#60;|&#x3C;)/</g;
  $str =~ s/(&gt;|&#62;|&#x3E;)/>/g;
  $str =~ s/(&apos;|&#39;|&#x27;)/'/g;
  $str =~ s/(&quot;|&#34;|&#x22;)/"/g;
  $str =~ s/(&amp;|&#38;|&#x26;)/&/g;
  return $str;
}

次のページ
atom2msrdb_read_ajax3.cgiのentry要素出力用CGI(atom2entry.cgi)

この記事は参考になりましたか?

PerlでデスクトップCGI連載記事一覧

もっと読む

この記事の著者

jscripter(ジェイスクリプター)

NIFTY SERVEのFGALEL(エントリーラボ)、FGALTS(テキスト&スクリプト)に参画し、FGALTSでシスオペを務める。現在、TSNETメンバー。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/1342 2008/08/19 18:57

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー