最近ウェブログなどで見掛ける、縮小された画像を選択するとそのページの背景が暗くなって中央に元の画像が表示される機能を解説します。
Ajaxに対応している環境で縮小されている画像を選択すると、背景が暗くなって、リンク先の本文とリンク先にある元の画像が表示されるようになります。
Ajaxに対応している環境の方向けに、比較用に用意したサンプルです。
こちらは、縮小されている画像を選択しても、全く同じリンク先へ遷移するだけです。
今回のサンプルの前提条件として、以下のようになっている事に留意してください。
今回、Ajaxを用いて、画像を選択すると、画面が暗くなって中央にそのHTML文書のメイン部分だけを抜き取って表示するようにします。
.xml が追加されたXML文書版(つまり、.html.xml と言う二重拡張子になっているもの)を別途用意しております。
今回こうした理由は、Ajaxの場合のみXML文書として配信すると言う設定にしようとすると、サーヴァの設定の話しまでする必要が出てくるためです。
実際にHTML文書をAjaxで読み込み、加工して出力させたいのであれば、AjaxでのHTTP通信ではURLの末尾に何らかのクエリを与えておいて、それをサーヴァが認識したらXML文書(MIMEタイプ・text/xml)として配信すると言うやり方がベターかと思われます。
そのような方法が使えない場合は、今回のように別途同じ内容のXHTML文書を用意してそれにアクセスさせるしか無いでしょう。
id="TOP"属性を与えた<h1>要素で始まり、id="TO_TOP"属性を与えた<ul>要素で本文部分が終わると言うテンプレートを使っております。
そこで、この二つの要素の間の部分のみを抽出して表示させる事とします。
但し、<body>要素直下の要素でクラス名に noAjax を含んでいる要素は抽出しないものとします。
勿論、対象となる<a>要素は限定されます。具体的には、クラス名に aj_thumbnail を含んだ<ul>要素の子孫要素のみとします。
実際にサンプルに用いた、ThumbNail.jsのコードは以下のようになっております。
尚、このコードは HTTPRequest.js と併用する必要があります。
をご覧ください。
/*
Ajax(アジャックス)サンプルコード(2) - 画像。
※インターネットエクスプローラはウィンドウズ版の5.0以降を対象とします。
※『サンプルコード(0) - HTTPリクエストを行うコード』が必要です。
*/
/********************************************************************************
元のHTML文書に本処理を起動するための仕掛けをする処理。
********************************************************************************/
var s_onload=window.onload;
window.onload=thumbnail_prepare;
window_width=600; // ウィンドウの幅。
function thumbnail_prepare() {
if (s_onload) s_onload();
var e=document.getElementsByTagName('ul');
var i=e.length;
while (--i>=0) {
var c=' '+(e[i].getAttribute('class') || e[i].getAttribute('className') || '')+' ';
if (c.indexOf('aj_thumbnail')<0) continue;
var e1=e[i].getElementsByTagName('a');
var j=e1.length;
while (--j>=0) {
e1[j].onclick=getHTML;
}
}
}
/********************************************************************************
XHTML文書をHTTP通信で取得するための処理。
********************************************************************************/
var h=null;
function getHTML() {
var f=this.getAttribute('href');
// HTTP通信のセッティングを行う。
h=httpReq();
// HTTP通信をサポートしていないか、通信に失敗した場合、何もなかったように戻る。
if (!h) {
return(true);
}
// 通信状況が変わったとき(通信中⇒通信完了など)に実行すべき処理を指定する。
h.onreadystatechange=getHTML2;
// 実際にHTTP通信で文書を取得する処理。
// ※今回は、本来配信するHTMLと同じもので、ファイル名末尾に「.xml」をつけたものを
// XML文書として配信するようにしております。
h.open('GET',f+'.xml',true);
h.send(null);
return(false);
}
/********************************************************************************
通信状況が変化したときに呼び出される函数。
※実際には、HTTP通信が正常終了した場合のみ処理を行う。
********************************************************************************/
function getHTML2() {
// 通信完了でなければ何もなかったように戻る。
if (h.readyState!=4) return(true);
// 正常に処理されなければ、エラーとして通信を途絶させて戻る。
if (h.status!=200) {
alert('HTTPエラー '+h.status+' が発生しました!');
h.abort();
return(false);
}
// HTML文書をXMLとして取り込む。
var txt=h.responseXML;
h.abort(); //この段階で通信を終了する。
proccessHTML2display(txt); //HTML加工処理に移る。
}
/********************************************************************************
取得したXHTML文書を加工して表示させる処理。
********************************************************************************/
var canvas='';
var bgscreen='';
function proccessHTML2display(txt) {
/**********************************************************
取得したXHTML文書の表示用ノードの確保。
**********************************************************/
// 加工したHTMLを表示させるための<div>要素(bgscreenノード)を作成する。
// 実際の内容を入れる子ノード(canvasノード)を生成する。
var b=(document.getElementsByTagName('body'))[0];
if (!bgscreen) {
bgscreen=document.createElement('div');
b.appendChild(bgscreen);
}
if (canvas) {
b.removeChild(canvas);
}
canvas=document.createElement('div');
b.appendChild(canvas);
/**********************************************************
取得したXHTML文書の加工。
**********************************************************/
/*
※IDとして「TOP」を与えられた要素の次の要素から、
IDとして「TO_TOP」を与えられた要素の直前までを取得。
但し、クラス名に「noAjax」が含まれている要素は除外する。
*/
var t2=(txt.getElementsByTagName('body'))[0];
if (!t2) {
alert('HTMLが壊れております!');
return(true);
}
e=t2.childNodes;
// IDとして「TOP」を与えられた要素までスキャンする。
i=-1;
while (++i<e.length) {
if (e[i].nodeType!=1) continue;
var j=e[i].getAttribute('id') || '';
if (j=='TOP') break;
}
// IDとして「TO_TOP」を与えられた要素の手前までcanvasノードに追加する。
// 但し、クラス名に「noAjax」が含まれている要素は追加しない。
while (++i<e.length) {
if (e[i].nodeType!=1) continue;
var j=e[i].getAttribute('id') || '';
if (j=='TO_TOP') break;
j=' '+(e[i].getAttribute('class') || e[i].getAttribute('className') || '')+' ';
if (j.indexOf(' noAjax ')>-1) continue;
appendOthersNode(canvas, e[i]);
}
// 末尾に<hr>要素とクローズするためのアンカーを付ける。
var e1=document.createElement('hr');
e1.style.margin='2em 0 0';
canvas.appendChild(e1);
e1=document.createElement('ul');
e1.style.margin='1em 0 0';
canvas.appendChild(e1);
var e2=document.createElement('li');
e1.appendChild(e2);
var e3=document.createElement('a');
e2.appendChild(e3);
var e4=document.createTextNode('戻る');
e3.appendChild(e4);
e3.onclick=closeCanvas;
e3.setAttribute('href','#');
/**********************************************************
加工したXHTML文書の表示。
**********************************************************/
e1=(document.getElementsByTagName('body'))[0];
var h=e1.offsetHeight;
var w1=document.documentElement.clientWidth || document.body.clientWidth ||
window.innerWidth;
var h1=document.documentElement.clientHeight || document.body.clientHeight ||
window.innerHeight;
var t=e1.offsetTop;
var l=e1.offsetLeft;
var ie6=document.all && !window.opera &&
navigator.userAgent.indexOf('MSIE 7.')<0 &&
navigator.userAgent.indexOf('Trident/')<0;
// 幅を決める。
window_width=Math.floor(w1*0.7);
// IE 6.0まで(position fixed;が使えない)。
if (ie6) {
bgscreen.style.position='absolute';
bgscreen.style.visiblity='visible';
bgscreen.style.display='block';
bgscreen.style.top=0;
bgscreen.style.left=0;
bgscreen.style.zIndex='1000';
bgscreen.style.width=w1+'px';
bgscreen.style.height=h+'px';
bgscreen.style.background='#000000';
bgscreen.style.overflow='hidden';
bgscreen.style.margin=0;
bgscreen.style.padding=0;
bgscreen.style.filter='alpha(opacity=70)';
bgscreen.style.opacity='0.7';
canvas.style.visiblity='visible';
canvas.style.display='block';
canvas.style.position='absolute';
canvas.style.top=((document.body.scrollTop || document.documentElement.scrollTop)+32)+'px';
canvas.style.left=((w1-window_width-64)/2)+'px';
canvas.style.width=window_width+'px';
canvas.style.height=(h1-128)+'px';
}
// その他(position fixed;が使える)。
else {
bgscreen.style.position='fixed';
bgscreen.style.visiblity='visible';
bgscreen.style.display='block';
bgscreen.style.top=0;
bgscreen.style.left=0;
bgscreen.style.zIndex='1000';
bgscreen.style.width=w1+'px';
bgscreen.style.height=h1+'px';
bgscreen.style.overflow='hidden';
bgscreen.style.margin=0;
bgscreen.style.padding=0;
bgscreen.style.background='#000000';
bgscreen.style.filter='alpha(opacity=70)';
bgscreen.style.opacity='0.7';
canvas.style.visiblity='visible';
canvas.style.display='block';
canvas.style.position='fixed';
canvas.style.top='32px';
canvas.style.left=((w1-window_width-64)/2)+'px';
canvas.style.width=window_width+'px';
canvas.style.height=(h1-128)+'px';
}
canvas.style.zIndex='1001';
canvas.style.overflow='auto';
canvas.style.margin='0';
canvas.style.padding='32px';
canvas.style.background='#ffffff';
return(false);
}
/********************************************************************************
閉じる処理。
********************************************************************************/
function closeCanvas() {
bgscreen.style.display='none';
bgscreen.style.visiblity='hidden';
canvas.style.display='none';
canvas.style.visiblity='hidden';
return(false);
}
Ajaxを利用したサムネール処理のサンプルのコードはちょっと長いので、どれがどのように動作するか簡単に説明させていただきます。
Ajaxを利用したサムネール処理のサンプルのコードの簡単な処理の流れは以下のようになります。
それでは、もう少し詳しく解説しましょう。
先ず、読み込み完了後にthumbnail_prepare() 函数を呼ぶように読み込み時に設定します。
thumbnail_prepare() 函数では、指定されたサムネール(ここではクラス名に aj_thumbnail を含んだ<ul>要素)内にある<a>要素に対し、クリックでXHTML文書をHTTP通信で取得するための処理である getHTML() 函数をコールするようにDOM操作を行います。
getHTML() 函数では、クリック元のアンカーが参照しているURLに対応するXML文書をHTTP通信で取得するようにしております。
また、通信完了時(実際には通信状況が変わった際)に通信で取得したXML文書の受け取り処理を担当するgetHTML2() 函数を割り込むようにします。
これらの処理はAjaxでの文書類リクエスト処理内のデータを送信する必要がない場合のリクエスト方法でのコードと殆ど同じですが、今回は取得する文書のURLとして、クリック元の<a>要素のhref属性の値を加工したものを用いております。
getHTML2() 函数はサムネールクリック時に起動するAjax起動処理で、通信状況が変わった際に割り込む処理です。
実際には通信完了時以外には処理出来る事はないので、通信が完了した場合のみ処理を続けます。
正常にHTTPが実行された事を確認したうえで、取得したXHTML文書をXML文書のDOMとして受け取ります。
ここでの処理はAjaxでのデータ取得処理内のAjaxでXML文書としてデータを受け取る場合でのコードと殆ど同じですが、今回はDOMのエラーチェックは後で行う事としております。
また、DOMを受け取ったら、それをproccessHTML2display() 函数に引渡します。
proccessHTML2display() 函数はリクエストしたXHTML文書の受け取り処理であるgetHTML2() 函数から呼び出されます。
引数として、取得したXML文書のDOMデータを受け取ります。
今回は、取得したXHTML文書から欲しい要素のみを抽出して表示させるため、その表示場所となる要素ノードが必要となります。
また、表示時には背景を暗くしたいため、半透明の黒い要素ノードを画面全体に被さるようにします。
これらのノードは取得したHTML文書の表示用ノードの確保の処理で行います。
具体的には、
となります。
表示用の準備が整ったら、いよいよ取得したXHTML文書の加工に入ります。
注釈にあるように、取得したXHTML文書の<body>要素の子要素のうち、id="TOP"属性を与えられた要素の次の要素から、id="TO_TOP"属性を与えられた要素の直前までを取得します。
noAjax が含まれている要素は取得しません。先ず、取得したXHTML文書のDOMから、一番目の<body>要素(XHTML文書なので<body>要素は一つしか存在しませんが)を抽出しますが、これに失敗した場合にはエラーダイアログを出して終了させます。
<body>要素を抽出したら、続いてその子要素を先頭から順に見ていきます。
id="TOP"属性を持つ要素までスキップします。id="TO_TOP"属性を持つ要素までをcanvas ノードに追加します(但し、class属性に noAjax が含まれている要素はスキップします)。
このとき、取得したXHTML文書は、コードを埋め込んでいるHTML文書とは別文書である事を忘れてはいけません。従って、canvas.appendChild(e[i]) でcanvasノードにXHTML文書のノードを追加する事は出来ません。
このため、併用している HTTPRequest.js 内にある appendOthersNode() 函数を用いてcanvasノードに追加して行きます。
position: fixed;プロパティに対応していないので、スクロールに合わせて表示位置を決める事になります。さて、指定されたサムネールのアンカーをクリックすると、リンク先のHTML文書に対応するXHTML文書が取得され、それから重要な要素のみが抜き取られて画面に表示されるようになりましたが、何時までも表示しっ放しと言う訳にも行きません。
そのため、表示処理では閲覧者が見終わったら元の状態に戻せるようにアンカーを仕掛けておりますが、そのアンカーをクリックされたときに実行されるcloseCanvas() 函数では、表示用の要素ノードと画面を暗くするための要素ノードをスタイル操作で非表示にしております。
Copyright ©平成21年-平成24年 さいたま・しらぎくさいと 版権所有
marguerite.site@gmail.com