03 | 2017/04 |  05

  1. 無料サーバー

User forum-FC2BLOG-Info-Edit Template-Post-Edit-Upload-LogOut

CSSやJavascript自習の苦闘史を綴っていきたい。恐縮ですがJavascriptを有効にしてご覧ください。
2005年12月から社会問題も掲載!

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

 

jQueryのAJaxUtilityを利用して、他のエントリイのタイトルを表示する(ResponseText版)

改 訂 履 歴
  • 初稿:2008/2/10 on ver1.2.2
  • 追記:2008/2/16
  • コードの抜本改定:2008/6/30 on ver1.2.6
  • コード微調整:2008/7/1~4
  • コードの更なる調整:2008/7/13

初めて jQuery AJax Utilities を使ってみる

直接そのページを開くのではなく、(今開いている頁はそのままで)当該ブログの過去のエントリイ情報を得るにはどうすれば良いのか、とふと思いました。直前の複数のタイトルが随時見られれば、色々便利かなと思ったのが事の発端です。

言うまでもなく、この Fc2 ブログの場合には、直前/直後の各々 1 つずつのエントリイに関する所定の情報は、所定の単変数によって取得することが出来ます。例えば <%nextentry_url> で直前エントリイの URLを、<%preventry_title> で直後エントリイのタイトルを取得することが出来ます。

しかしそれは直前直後の僅か 1 つずつのエントリイ情報しか得られません。

また、最新エントリイのタイトル一覧もブロック変数 <!--recent--> ~ <!--/recent--> で取得することが出来ます。

しかし、それはあくまでも最新のエントリイに関する情報であって、直前/直後ではない、もっと離れた過去と未来のエントリイ情報を取得する変数は用意されていません。

任意の1のエントリイの直前/直後のエントリイタイトル一覧を見る変数は用意されていません。

そこでそれらを取得するには AJax を利用するしかないだろうと判断し、初めて jQuery's Ajax メソッドを利用して試してみました。

ここでは、このエントリイの前の 10 個のエントリイのタイトルをまとめて取得し、このエントリイ内に表示してみました。

jQuery.get クラスメソッドを使って別エントリイのタイトル(リンク付き)を取得

※ 個別エントリイ表示以外のモードの場合には、ここに何も表示されません。

  •   Now Loading...

▲ToTop

成功したコードを確認する。

まず最初に、過去の任意の1つのエントリイタイトル情報の取得を試みたところ、これはあっさりと出来てしまいました。その時には、その余りの「容易さ」が、後にアダになるとは思いもしませんでした。(×_×;)シュン

余りの容易さに意気込んで、次に複数のエントリイ情報を得ようとチャレンジを開始したわけですが、何と現在の表示状態に達するのに5日を要してしまいました。

何故それ程の時間を要したのか───それを明らかにすることは jQuery を利用する上での注意点を体験を通じて示すことであり、意味のある行為であると思われるので、躓いたことを以下にまとめます。

jQuery.get(url,data,callback,type) メソッドの callback 関数

callback 関数は、url で指示したサイトの DOM ツリー全体を引数「 data 」に 取得し、次にその data 値から目的とする情報を取得して当該関数内で様々に処理する仕様となっています。なお、data はユーザーからサーバーへの送信データであり今回は記述しませんでした。

さて、この callback 関数内で取得した値を、その外の別の関数や Javascript 文の中で直ぐに使用しようとしたのですが、ここで躓きました。

callback 関数内で処理され取得した値を、その外では「直ぐには」「微妙に」利用出来ない場合があるのです。Ajax 通信故のタイムラグ、つまり Javascript コード進行と並行で行われる Ajax 通信がもたらす指示出しと結果取得とのタイムラグが、「微妙な問題」を引き起こします。

その具体的な内容を以下に記します。

過去 Entries のタイトル及びリンク先アドレスの取得に成功したコード

何はともあれ、成功したコードは以下の通りで、コードに触れながら「微妙な問題」に言及しようと思います。なお以下のコードはこのエントリイの末尾に記述してあるので、基本的に DOM 読み込み完了を待機させる必要はありません。

   // 個別エントリイモード以外の時には、
  1: if (location.href.indexOf("entry")==-1) {
    // Ajax通信開始ボタンを隠蔽し
  2:  $("#pastTitle623").parent().css("display","none");
    // 何もしないでコード進行を終える。
  3:  (function(){return;})();
  4: }
   // ボタンから起動される Ajax 通信実行関数を定義する
  5: var getTitleText = function(limit){
    // この関数を起動するボタンを隠蔽する。
  6:  $("#btn623").css("display","none");
    // 結果表示領域を表示する。この中には Ajax 通信中を知らせる文字列を埋め込んである。
  7:  $("#pastTitle623").css("display","block");
    // 諸変数定義
  8:  var thisEntryNo, getEntryNos=[], thisURL=[],
  9:   regExpr = /entry-([0-9]+)/, html=[], realcnt=0;
    // 今開いているエントリイのエントリイ番号を取得する
 10:  thisEntryNo = regExpr.exec(location.href)[1];
    // タイトル文字列を抽出するための正規表現を定義する
 11:  regExpr = /<title>(.*)<\/title>/;
    // 対象とするエントリイ番号を巡回処理で作成する
 12:  for (var i=1; i<limit+1 && i<thisEntryNo ; i++){
     // エントリイ番号を配列
 13:   getEntryNos.push( thisEntryNo -i);
 14:  }
 15:  // 複数のエントリイを対象として Ajax 通信を実行する
 16:  $.each(getEntryNos,function(i,item){
     // タイトル名などを取得するエントリイの URI アドレスを構成する
 17:   thisURL[i] = "http://hkom.blog1.fc2.com/blog-entry-" + item +".html";
     // 各々の個別エントリイ URI に対して Ajax 通信を行い
     // ResponseText 文を取得する。
 18:   $.get(thisURL[i],function(data){
      // Ajax通信結果であるエントリイHTML文全文からタイトル名を取得
 19:    var titleStr = regExpr.exec(data)[1].substring(19);
      // エントリイタイトル名があれば
 20:    if (!!titleStr){
       // 取得タイトル名などを表示用 HTML 文として整序する
 21:     html[i] = "<li><a href='" + thisURL[i] + "' target='_blank'>" + titleStr +" (EntryNo.:" + item + ")</a></li>";
       // 取得タイトル数をカウンター値に入力する
 22:     ++realcnt;
 23:    }
      // 巡回処理が最後の配列要素に到達したならば
 24:    if (item == getEntryNos[getEntryNos.length-1]){
       // realcnt、つまりタイトル取得数がゼロならば
 25:     var tmp = realcnt==0 ?
        // デコードして「ありません」を代入する
 26:      decodeURI('%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82')
        // タイトル取得数があれば取得結果である配列要素を併合する
 27:      : html.join("");
       // 結果表示タグ内に結果を表示する
 28:     $("#pastTitle623").html(tmp);
 29:    }
 30:   }); // End of $.get()メソッド
 31:  }); // End of $.each()メソッド
 32: } // End of function
 33: 

dataType(text や json 等)を特に指定していませんので、data は テキスト形式となります(ver1.2.6 の 2881 行から)。このテキスト文は指定した「url」の html 文ですから、正規表現文字列(上のコードリストの 13 行)とその exec メソッド(同上 21 行)を使って、title タグ内の文字列を取得し、かつその中のエントリイタイトル名文字列を抽出しました(つまりブログタイトルを除外しました)。

上のコード作成上で最も苦労したのは、$.get(url,fn(data){}) で取得した data 値の処理です。

追記(2008/2/16)

その後色々調べた結果、そもそもサーバー側が xml ファイルを提供しなければ当然それを取得できない───そんな簡単なことがやっと分かりました。(※ 詳しい方からは「そんなこと当たり前!何を今更言っているのか?!」と叱咤されそうです。)FC2ブログサイトでは通常のアドレスのままでは XMLHttpRequest.ResponseText は取得できても、 XMLHttpRequest.ResponseXML は取得できないことを理解しました。

具体的には jQuery.js を使っている限り Ajax の動きがブラックボックス化されているので、『 Javascript 第5版』で紹介されているコードを使って、つまりjQuery.js ではなくもっと原始的な Ajax コードを使って確認しました。

なお、今回行った Text ファイルにたいする正規表現による検索以外の方法でも、例えば XML ファイルを取得する Ajax 通信によってもブログタイトルやそのエントリイタイトルは取得出来ますが、それは一群の最新のエントリイに関するものだけに限定されます。

追記2(2008/2/16)

Fc2 ブログは RSS を発行できるのだから、xml が使えないはずはない、と食い下がった結果、次のことに気がつきました。

uri アドレスの後に「 /?xml 」をオプション的に付加することによって xml ファイルが取得できると言うことを!!

しかし、ここで取得できる xml ファイルにはある「固定された」制限があります。それは xml ファイルに含まれるエントリイ数です。ブログ環境設定で登録したエントリイ数の、しかも直近の情報しか xml ファイルには含まれません。そのためでしょうか、ブログ環境設定には RSS 固有用のエントリイ数登録が可能となる項目が新設されていました。

つまり /?xml で取得できる xml ファイルは「最新」エントリイ情報であり、そのエントリイ数は環境設定に依存します。従って RSS 情報の場合のエントリイ数を 11 以上に設定しておけば直近直前の10エントリイのタイトル情報を取得することが可能となります。

そもそも、この /?xml オプションを利用した Ajax によるタイトル取得については、ブロック変数 <!--recent--> ~ <!--/recent--> で取得できる情報と全く同一になるので、敢えて Ajax を利用する価値は皆無ですが、一応別のエントリイで述べてみたいと思います。

( 別 Entry 「 jQuery の AJax Utilityを利用して、最新 20 エントリイの諸情報を取得表示(ResponseXML版) 」 でそれを試みました。 )

▲ToTop

何が問題となったのか

1. $.get メソッドの後に続くコードの実行に要注意

非同期通信中で、まだ目的の情報が取得できていないのに、お構いなしにスクリプトのコード進行は先に進む───このことに気がつくのに数日を要しました。これまで自前では全く非同期通信を実行したことがないので、このようなデータ取得時間とコード進行の兼ね合いなどを気に掛ける必要がありませんでした。

この点こそ、非同期通信の特異性あるいは特徴と言えるかも知れません。

従って、$.get メソッド内で取得した結果を利用するコードを、$.getメソッドの外でかつ当該メソッドの直後に記述するとエラーとなるか、意味のない結果が得られてしまいがちです。原因を探るべく jQuery 本家サイトをよ~く眺めてみたら、そのことが小さく書いてある箇所がありましたが、初めてAjax コードを書く上で、必ず留意すべき重要な点だと改めて確信した次第です。

以上の問題、いな特性を踏まえて 18 行以下のコードを書きました。さんざん試行錯誤を重ねた結果、Ajax 通信結果を処理するコードは、全て Ajax 通信メソッドの中に入れるべきであることを改めて学習したのです。

2. 繰り返し $.get メソッドを利用する場合の注意点

次に、複数回の $.get メソッド実行によってサーバーから連続して情報を取得する場合においても、予想しなかった問題が発生しました。今回のケースで言えば過去の 10 個のエントリイのタイトルが新しいものから順に下に表示されるようにコードを作ったのです。否、作った筈でした。

ところが表示結果を見てみると順番が不同になってしまうのです。今開いているエントリイの直前 10 個のエントリイタイトルを確かに取得できているのですが、その順番が大袈裟に言えば表示する度に異なるのです。少なくとも新しいものから順に下に並ばないのです。

どうしてなのか思案した結果、それは 10 回のそれぞれのタイトル値の取得に要する時間が異なるのではないか、との結論に至りました。当該エントリイの情報量が多ければより多くの時間を、少なければより短時間で目的を達してしまうのだろう、と推測しました。

実際 FireFox 版の Firebug で通信状況を調べたところ、Ajax 通信完了は各エントリイのファイルサイズに依存し、下図で分かるように完了順序は必ずしも通信開始順にはならないことを確認しました。

複数の連続する Ajax 通信の進行状況図

そこで順番に並べるために一工夫しました。(取得完了順ではなく番号順に)配列に順番に情報を格納し、それを順に結合すればよいと考え、それを実行したのです。

3. DOM ready メソッドとの兼ね合い

今日(2008/2/10)最終結果に到達するまでずっと、コード全体を DOM ready メソッドでくるんでいました。

しかし非同期通信そのものやその過程で情報を取得する手順においては、DOM 読み込みが完了している必要はありません。その完了を確認してから実行しなければならない処理は、Ajax処理で取得した情報を、今見ているページ内に挿入する行為だけです。

そこで本日(2008/2/16)、全体を無名関数で包含して不必要な待機をやめさせ、その結果、可能な限り速く結果を今見ているページに表示できるようにコードを改変しました。

その後(2008/7/1)更に改変し現在の形にしました。エントリイ表示後に直ぐに無名関数を実行させて自動的に Ajax 通信をスタートするのではなく、ユーザー指示により通信を開始するようにしたのです。Ajax 通信に要する時間を体感できるこの方法がより相応しいとの判断からです。

次に行うべきことは・・・

  • xml ファイルをゲットして、そこから過去エントリイ情報を取得する試みを行ってみたい。
  • 更に過去の10タイトルを、あるいは後続する未来のタイトルを、各々このエントリイ内においてクリック一つで表示できるようにするのも一興か?、と考えています。同時にその時には、それまで表示されていたタイトル一覧の消去と新しいタイトル一覧の表示を、アニメーションを使って入れ替えればより面白いかも知れない、と考えています。

 

■ コメントの投稿 ■

管理者にだけ表示を許可する

●トラックバック●

■トラックバックURLはこちら■
http://hkom.blog1.fc2.com/tb.php/623-853a68a0

●参照元一覧●

<provided Fc2>
<provided i2i>

▲ToTop

 90%近いシェアを握っているインターネットエクスプローラの描画エンジンを利用したタブbrowser。沢山のタブbrowserがあるが、多機能、カスタマイズフリー、スクリプト利用等で一日の長がある。Gekkoエンジンへの対応も行われ、IEからの自立独立の方向に向かっている。2005年7月にはIE7が登場する見通しの中で、今後の発展が望まれる。

 多様なCSS作成支援機能を備えた、タグ入力式 HTML&CSS作成支援エディタ。スキンデザインもすっきりしている。テキストエディター上で作成するよりも確実で安全にタグ打ちが出来る。
文字コードを選べないのが欠点。

 StyleNote同様のタグ入力式 HTML&CSS 作成支援エディタ。長年使用してきたが現在StyleNoteに乗り換えつつある。

 クリップボード履歴情報を活用する為のソフト。画像まで履歴を取ってくれるのが嬉しい。このソフトを使わない日は絶対ない程に重宝し、愛用している。

 起動中のウィンドウの「コピーできない」説明文などの文字列を取得し、コピー可能な文字データにするツール。何かと便利。

 ストリーミングデータを保存することが出来るソフト。動画利用には不可欠なソフトだ。

 無料ながらレイヤー機能を有し、スクリプトによる拡張も可能な、sleipnir作者が提供している優れもの画像編集ソフト。

 画面キャプチャソフトと言えばこれに勝るものなし、ではないだろうか? 様々な取得方法を有しており、ブログ作成にもHomepage作成に不可欠だ。Jtrimと並んでWoodyBellsの作品。

 複数ファイルの同時編集は出来ないが、透過pngも作れる画像編集ソフト。
(以下当該サイトから抜粋)初心者にも簡単に操作が出来るフォトレタッチソフトです。多くの加工機能で画像に様々な効果を与えることができます。非常に軽快に動作するため、ストレスなく操作できます。

 Animation Gifファイルを作れる無料ソフト。

 キャプチャソフト。画面内にサイト全体が表示しきれない場合でも、これを使えば全体をキャプチャすることが出来る。

 画像処理。画像のフォーマット変換のみならず、色数やサイズ、圧縮率の変更まで一括処理できてしまう『BatchGOO!』は、大量の画像をまとめて処理したいときに大変便利なソフト。BMP, TIFF, JPEG, PCX, PNG の相互変換をはじめ、色数・サイズ・解像度の統一、JPEG圧縮率の調節など、ホームページ用の画像や携帯電話用の壁紙を揃えるのに抜群の相性を見せる。(Vectorの当該ソフト紹介頁より抜粋引用)

 名前から直ぐに想像が付くように画像のサイズを測るためのソフトだ。Homepage作成には欠かせない。2カラム、3カラムのレイアウトを行う場合に大変重宝する。

 ランチャーソフトは沢山あるが、中でもこれが一押しだ。2年以上使ってきたがその操作性には毎日満足している。これを使い始めてからデスクトップには一切のアイコンを表示することをやめてしまった。

 AdobeReader7によって、起動時間が長すぎるという長年のユーザーの不満はある程度解消した。そのためこの高速化ソフトは存在価値が低下してしまったかもしれない。AdobeReader6迄はこのソフトによる起動高速化で恩恵を受けてきた。

 IE専用が難点だが、様々なサイト内でIDやパスワードを入力するのに重宝するソフト。コンテキストメニューから簡単に起動できるのがGood! sleipnir等のIEの描画エンジンを利用しているブラウザでも使える。

 利用しているパソコンの諸元値を取得するには、このソフトがベストだ。インストール済みソフトの一覧が取得できるのも嬉しい。

 WMPは機能が豊富なだけ重い。RealPlayerも同様だ。そこでMedia Player Classicを使いたい。動作が軽快なだけではなく、対応しているファイル形式もすこぶる多く、これひとつで、wmvもrmも表示できてしまうのだから凄い! 数多あるMedia Playerの王様と言えるだろう。

 自宅でPCを起動しているときには必ず起動しているメディアプレーヤー。何かと過剰なWinampよりも、起動も速くスキンはシンプルだ。

 DivX, Xvid, Mov, Vob, Mpeg, Mpeg4, avi, wmv, dv, などの動画をDVD-Video形式に変換できるフリーソフト。クリックするとDVD関連ソフト紹介サイト=「DVDなToolたち」なるHomepageが開きます。

----------
200802100133
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。