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の記述の内容の構成は概略次のようになります。
XMLHttpRequestのオブジェクトを生成します。これはブラウザに依存する関数を使います。XMLHttpRequest()はMozilla系のブラウザ、Msxml2.XMLHTTPは新しいインターネットエクスプローラ、Microsoft.XMLHTTPは古いインターネットエクスプローラ用です。その他のブラウザを使う場合には調べてください。XMLHttpRequestオブジェクトが変化するとどのように動作させるのかを関数に記述します。ここではXMLHttpRequestオブジェクトを引数とするdisplayContentという関数が実体となります。XMLHttpRequestオブジェクトにopenメソッドを適用します。GETメソッドで、「atom2entry.cgi」にパラメータを渡します。openメソッドの第3引数にtrueあるいは1を渡すか、全く渡さなかったときに動作します。falseあるいは0とするとまったく動作しなくなります。sendメソッドで送信します。displayContent関数にあるXMLHttpRequestオブジェクトのreadyStateというプロパティはドキュメントの読み込みが完了したときは、4になります。atom2entry.cgiの出力の読み込みが完了しない間は、「Loading...」という文字がボールド体のイタリック体で表示されていますが、完了すると、CGI出力に置き換わります。
# 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については下記のサイトを参考にすればよいでしょう。
スクリプト全体
#!/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 ();"> <-----> <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/(<|<|<)/</g; $str =~ s/(>|>|>)/>/g; $str =~ s/('|'|')/'/g; $str =~ s/("|"|")/"/g; $str =~ s/(&|&|&)/&/g; return $str; }
