« うな丼 | メイン | NONDRINKING »

2006年07月09日

[技術] Ajax prototype.jsを利用して、広告自動更新サンプル

prototype.jsを極力利用して、非同期でサーバと通信をして、画面の広告スペースの広告を自動更新するプログラムを作成した。作成する中で、いくつか問題点があったので、問題点とその解決方法を備忘録として記録。

■↓今回のサンプル(インフレーム) 全画面表示

■サンプルプログラムの構成
fireworks.html
+prototype.js
+ adview.js <------------ 非同期通信 -----------------> get_addata.cgi

firework.html 広告表示画面
prototype.js 1.4 Ajaxのフレームワーク
adview.js サーバサイドのget_addata.cgiにリクエストを送り、結果をfireworks.html画面に表示する

■fireworks.html概要
画面ロード時に、onloadで、adview.jsのadListener()を起動する

<body onload="adListener()">

広告データのHTML

<div class="adOne adStyle02" id="adId02">
  <div class="catchcopy">
    <a href="http://www.youtube.com" target="_blank" >YouTube</a>
  </div>
  <div class="line_a">見てみる?</div>
  <div class="line_b">投稿してみる?</div>
  <div class="url">
    <a href="http://www.youtube.com" target="_blank" >www.youtube.com</a>
  </div>
</div>

広告データを挿入する所

  <div id="adContents"></div>

adview.js概要
制御用のグローバル変数


// 自動更新インスタンス
var periodicalExecuter;
// 更新間隔時間(秒)
var intervalTime = 2;
// 最大掲載広告数
var adMax = 5;
// テストモードフラグ
var testMode = false;
// サーバサイドのURL
var adUrl = 'http://www.ishihara.ne.jp/sample/get_addata.cgi

adListener() prototye.jsのPeriodicalExecuterクラスを使い、intervalTime秒間隔でreqAddata()を実行する


function adListener() {
periodicalExecuter = new PeriodicalExecuter(reqAddata, intervalTime);
updateShowParams();
}

reqAddata() prototype.jsのAjax.Requestを使い、サーバサイドにリクエストする関数。返ってきた結果を加工したいので、そのための関数setAddata()をonCompleteに指定する。


function reqAddata() {
var pars = createReqParams();
var myAjax = new Ajax.Request(adUrl,
{
method: 'get',
parameters: pars,
onComplete: setAddata
});
}

setAddata() サーバからのデータを画面に挿入し、最大掲載数(adMax)を超えた分を削除


function setAddata(httpRes) {
// 新規広告の挿入
var html = filterResponse(httpRes.responseText);
new Insertion.Top('adContents', html);
// 最大掲載数を超えた広告の削除
var adContents = $('adContents');
var nodes = document.getElementsByClassName('adOne', 'adContents');
while (nodes.length > adMax) {
var node = nodes[nodes.length - 1];
adContents.removeChild(node);
nodes = document.getElementsByClassName('adOne', 'adContents');
}
}

get_addata.cgiの概要
ブラウザからリクエストがあった場合に、広告データ(HTML)をランダムに選択して、送信する。また、パラメータにtestmodeフラグが立っていたら、最大掲載広告数や掲載広告更新間隔を変更するための指示を適当に生成して、送信する。それらのフォーマットは以下の通り。

<config>
<admax>3</admax>
<interval>5</interval>
</config>

■問題点、その他
1.MacのSafari,FireFoxはJavaScriptの正規表現でRegExp.multiline=tureでも複数行モードが正しく動作しない。
仕方ないので、改行コードを取り除いてから、処理した。(他のブラウザでは未確認)

2.SafariはRegExp.rightContext(マッチした部分から右側部分が格納されるプロパティ)に値が入らない。
RegExp.rightContextは使わないことにした

3.prototype.jsのAjax.PeriodicalUpdaterは、 optionのinsertに自前関数を指定すれば、更新部分のカスタマイズができるが、サーバにリクエストを送る際のURLパラメータをリクエスト送信毎に動的に変更する方法がわからなかった。そのため、今回のサンプルで利用しなかった。

4.prototype.jsのPeriodicalExecuterは一度セットしたタイマージョブを停止するインターフェースが用意されていない。今回、更新間隔の変更を行うためには、タイマーをクリアする機構が必要だったので、以下のようにprototye.jsのPeriodicalExecuterに手を入れた。

prototype.jsの104行目から


registerCallback: function() {
this.timer = // add 2006.7.7 ISHIHARA Yoshinori
setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
// add 2006.7.7 ISHIHARA Yoshinori
clearTimerEvent: function() {
clearInterval(this.timer);
},

setInterval()の返り値をthis.timerに保持するようにして、clearTimerEvent() 関数を追加した。

5. 非同期通信で表示する広告がSafariでは文字化けしてしまう
こちらのサイトで で、紹介されている方法を採用する。get_addata.cgiから返すデータの先頭に以下の宣言を追加して、明示的にSafariに文字コードを教えてあげる方法で解決。

<?xml verion="1.0" encodeing="utf-8"?>

■ソースコード他
fireworks.html
prototype.js
adview.js
get_addata.cgi

投稿者 nekobara : 2006年07月09日 09:48


コメント