09 | 2008/10 |  11

  1. 無料サーバー

search phpbb-phpbb-FC2BLOG-Info-Edit Template-Post-Edit-Upload-LogOut

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


jQuery Effect を使う(1)

イベント、Ajax通信と辿って来て次は?

エフェクトにチャレンジしようと思います。

Ajax 通信は非同期通信故の困難性───コード進行プロセスと同時並行で Ajax 通信が進行することに拠るスクリプトコントロール、あるいはタイミング取得の───故に、使いこなせる迄に半年を要してしまいました。

初めて Ajax 通信スクリプト作成にチャレンジしてみて、色々学習しましたが、マスターするのにこれ程の時間を要するとは、当初は予想だにしていませんでした。

本職ではない素人の、多忙な中を縫っての片手間の試行錯誤の積み重ねですから、やむを得なかったことですが、それでもなお自分に対して、要した時間長にはちょっと失望気味です。

そんな状況であるにも拘わらず、次に進もうという意欲はまだ残っているようです。

静止画像表示に多用される Effect に挑戦

そして次は...。「 easing 」なる言葉に象徴される Effect 操作のあれこれを学習しようと思います。

動きのあるコンテンツといえば、今日では DHTML でも Javascript でもなく Flash によるコンテンツ作成こそが主流であり、王道でしょうが、碌な Flash 作成ツールを持ってないため、Javascript による動的コンテンツ作成に踏み出してみようという訳です。

画像の様々な動的表示に関するコードは巷に溢れています。

文字の動的表示に至っては、初期ブラウザ(1995-2000年頃)でさえ、既にその一部の方法をHTMLタグ自身で有していました。

ですから、屋上屋を重ねて同じような動的コンテンツ表示手法を追求する意図は全くありません。今考えている動的コンテンツ表示とは、文字であれ画像であれ、それを表示する時の easing 効果をjQuery を活用して体現してみようということです。

つづく

▲ToTop



▲ToTop

・・・・・

FireBug1.2.0b6 使用感

Firefox 3 登場に合わせて登場した firebug 1.2.0

6月18日の Firefox 3( 以下「FF3」)登場段階ではまだ未対応だと思っていた FireBug ( 以下「FB」)ですが、実は既に対応済みだったようです。兎に角早速 FF3 対応版を使い始めました。

さて、スキンが殆ど前のままなので、使い勝手も同様だろう、と踏んでいたのですが、それは誤解でした。

Webサーバーへの負荷を考慮したのか、デバッグ対象とするサイトを登録しなければならないのです。その使い勝手は今一で、最初は非常に戸惑いました。

あちこちの Web サーバーにある外部スクリプトファイルを利用しているので、そのデバッグを FB で行おうとして、これまでのようにスクリプトリストを開いてみたら、どうも違う!───いくつかのサーバーがそのリストに表示されないのです。以前のバージョンの場合にはそんなことは全くなかった訳で、「何がどうなったのか?」最初は戸惑いました。。

特に今行っている Ajax 通信に利用している Google Pages サイトがスクリプトリストに表示されないのには参りました。

また、新しいスクリプトを利用すると一々解析対象とするかどうかを聞いてくるのにも閉口しました。余りに「五月蠅い」のです。

▲ToTop

今は快適に使用している

そんなこんなで試行錯誤を数日重ねた結果、やっと仕組みが分かってきましたので今は何も問題なく使えているのですが、本家の英語サイトの説明を一々読み込むほど英語に強くないので、困惑は今後も継続するかも知れません。

何はともあれ、一つの問題が解決した、という余りにありきたりの話ではありました。

Flash Player 9 へのバージョンアップに伴ういくつかの問題について

そのバージョンアップの影響

Flash Player 9 は調べて驚いたが何と 2 年以上前にリリースされている。「日本語版ダウンロード可となった」との記事が Gigazine に掲載されたのは 2006/6/28 だった。( 「Flash Player 9」日本語版がダウンロード可能に

しかしこの 2 年間ずっと 9 へのバージョンアップはしないまま職場及び自宅のパソコンを使い続けてきた。

今回バージョンアップしたのも積極的なものではなく、FireFox を使っていたある時、バージョンアップの知らせが表示されたので受け身にそれを受諾したのだ。

しかし、問題は直ぐに発生した。早速次の 2 つの障害が発生したのだ。

第一に、フラッシュファイルに埋め込んだクリックイベントが作動しない。

第二に、IE7 において容易にバージョンアップできない。

▲ToTop

問題解決のための格闘で今日一日を費やす羽目に...

最近は描画速度の遅い IE7 に嫌気が指しているので、専らサイト表示は FireFox で行っている。だからより深刻な問題となったのはクリックイベント無効状態であり、このブログでそれを活用しているだけに、それは早急に解決しなければならない課題となった。

さて普段 Flash ファイルを作ることはまずないし、活用できるアプリケーションがないからでもあるが、Action Script には全く手を出していない。

そんな状況下だったので、ハタと困ってしまった。何をどの様に解決すればよいのか、その方向性すら見えない状態になってしまったのである。

あれこれ検索を掛けてみても、なかなか適当なサイトが見つからず、時間ばかりが空しく過ぎ去っていく中で、やっとそれらしいサイトが見つかるまでに多大な時間を要してしまった。

しかも、Adobe 社のサイトを見てみたら、Flash Player 9 では swf ファイルに埋め込む「 href="Javascript:function()" 」が 恰も使えなくなったかのような表現が散見されたので混沌としてしまったりもした。( Adobe - デベロッパーセンター : 2008年4月のFlash Player 9のセキュリティアップデートについて

使えないならばどうしようか?、Action Script に踏み込まなければならないのだろうか?、Javascript と HTML で何とか対応出来ないのだろうか?───等々とあちこちに解決の方向性を漫然と模索してしまったのである。その全ては空しい結果に終わるとは予想もせずに・・・。

結論を言えば、「 [229684]HTML ページに埋め込まれた SWF からのリンクが機能しない場合がある 」を見て問題は解決したし、その内容たるやあっさりしたことであったものの、その解決迄に要したカオス状態に疲労感が一気に増してしまった。

こんな簡単なことをどうしてもっと分かりやすく説明したサイトがないのだろうか?、そもそもAdobe 社のサイトでなかなか目的の頁に到達できないこと自体おかしい。サポートデータベースに目的の情報はあったのだが、決してそれは検索しやすいものではないのである。

関連して付言すると、swf ファイルからのリンク切れに関するあるサイトのスレッドがありました。

それにしても約 2 年間、ページ上部に設置してあるFlash ファイルである ( このFlash Fileにもクリックイベントは埋め込んであるが、ここではそれは作動しないようにしてある。) は Flash Player 9 がインストールされている PC においては動かなかった訳で、閲覧してくださった方々には多大なご迷惑を掛けてしまいました。

▲ToTop

AllowScriptAccess パラメータについて

Adobe 社 サポートデータベース「 [229684]HTML ページに埋め込まれた SWF からのリンクが機能しない場合がある 」によれば、Flash Player 9 から導入された AllowScriptAccess パラメータは、デフォルト値が sameDomain となっているそうだ。「これがセキュリティ上、望ましい設定です。」ということらしい。

しかるに 一般に Blog サイトの場合、Domain 名はエントリイ表示モード、カテゴリイ表示モード、ファイルダウンロード先等々、決して同一ではない。このため、デフォルト値のままでは swf ファイルに埋め込んだリンクは無効になってしまう。

Blog はアメリカで始まり、当然アメリカでも普及しているはずなのに、この「無配慮」は何だろう?!「機能しない場合がある」どころではなく、「一般に機能しない」と言うべき設定値だ。

IE7 でなかなかバージョンアップが出来ない問題

こちらについては最初躓いたものの、直ぐに多くのサイトが見つかったし、Adobe 社サイトからアンインストーラを入手し、その後に普段全く使わない IE7 を起動してインストールしたので、あっさりインストール出来てしまった。

しかし、こちらについても一言言いたい。

ActiveX の面妖さ、である。何かに付け悪意のあるサイト攻撃手段として使われるため、ガードが堅くなるのは仕方ないとはいえ、いかにも使いにくい!

特に Adobe 社サイトからのダウンロードの場合、ActiveX に関する注意事項が余りにすくないため、Flash Player のダウンロード一つとってもなかなか巧くいかない場合が多かったりする訳である。───実際それ故であろう、Flash Player のアップデートが巧くいかない、Flash が動かない等々の障害情報が、Web空間に溢れているのだ。

その意味で、Flash Playerダウンロードサイトは、決してユーザーフレンドリイな仕様ではない、と言わざるを得ない。

jQuery を活用したオリジナルの Ajax 通信コードを全面的に改訂しました

何はともあれ結果を見て戴くのが最善でしょう

任意の Fc2 ブログを個別エントリイモードで開き、そこで Ajax 通信を行って、最新/以前/以後エントリイのタイトル情報などを取得する Ajax 通信プロジェクト(以下「 Fc2タイトル情報プロジェクト 」)を半年を要してやっと実現しました。その結果サンプルは以下の通りです。

サンプル 1【 Fc2総合インフォメーションブログ 】

下の画像は、Fc2総合インフォメーションブログ上で Fc2 タイトル情報プロジェクト を実行した際の表示結果抜粋です。

Ajax 通信によって最新/以前/以後エントリイのタイトル情報などを取得した結果を示すサンプル画像 1
サンプル 2【 関西ZIGZAG 】

下の画像は、人気ブログ「 関西 ZIGAZAG 」ブログ上で Fc2 タイトル情報プロジェクト を実行した際の表示結果の抜粋です。

Ajax 通信によって最新/以前/以後エントリイのタイトル情報などを取得した結果を示すサンプル画像 2
サンプル 3【 FCafe 】

下の画像は、自ブログ開設時からお世話になってきたサイト上で Fc2 タイトル情報プロジェクト を実行した際の表示結果の抜粋を示すものです。

Ajax 通信によって最新/以前/以後エントリイのタイトル情報などを取得した結果を示すサンプル画像 3

以上に例示した Fc2 タイトル情報プロジェクト の詳細については、こちらのエントリイ( ファイル置き場と Ajax 通信を活用して、任意のFc2ブログから情報を得る )をご覧いただければ幸いです。

「その光明」はなかなか見えなかった

jQuery.js を活用した Ajax 通信に、今年の 2 月からチャレンジしています。

しかし、目的とする連続的な Ajax 通信の結果取得(後に分かったことではあるが、結果取得ではなく取得結果の即刻表示)が巧くいかず、半ば諦め、4分の1ほどやけっぱちになり、4分の1ほど食らいついて解明したい、との思いが錯綜する中で、昼間の仕事の多忙さに追われて、なかなか「食らいつく」時間が取れませんでした。

しかしこの程、幸いにもその時間が取れたので、改めて jQuery.js( ver1.2.6 )コードと格闘し、最近刊行された書籍( Amazon.co.jp:『jQueryで作るAjaxアプリケーション』: 沖林 正紀著 2008年6月19日発売) )も購入し、 jQuery.js を利用した Ajax 通信に再チャレンジしてみました。

余談ですが、上記の書籍は日本語で書かれた jQuery.js 入門書としては初めてのものではないでしょうか?

その点での価値は大いに評価できると思います。

しかし、内容は、といえばまさしく「羊頭狗肉」と言わざるを得ません。

書籍名から推測すると、 jQuery.js を活用した Ajax アプリケーションのあれこれについて書かれているのではないか、と思っても決して無理はないと思います。しかし、内容は決してそのようなものではありません。

jQuery.js 入門書としては結構詳述されていますが、 Ajax アプリケーションのあれこれについてはたいした記述がありません。しかも Global イベントを利用した Ajax 通信のことしか書かれていないのです。jQuery 本家サイトを見れば分かるとおり、global イベントを利用した Ajax 通信は「それも出来る」行為であって、決して推奨されるべきものではないはずです。

何故ならば、Ajax 通信はその結果を取得するのに時間を要する行為であり、一方イベント処理も jQuery.js コード内を縦横に縦断する時間を要する行為です。二重に時間を要することを推奨すべきではないでしょう。

故に書籍名はまさに「看板倒れ」と言わざるを得ないのです。書名を「jQuery 入門」とした方が遙かに「体を表す名」だと思います。

▲ToTop

連続的な Ajax 通信による結果取得の困難性

以前のエントリイタイトル、最新のエントリイタイトル、そして以後のエントリイタイトル───Ajax 通信によるこれらの 3 つのフェースの情報取得をずっと試みる中で、特に躓いた点は過去/未来のエントリイタイトル取得、それもそれぞれに 10 個の、合計 20 個のエントリイタイトルを一発で取得する Ajax 通信でした。

もっと具体的に言えば、1回のコード進行で過去/未来の 20 個のエントリイタイトルを取得することは出来たのですが、それらの取得後可及的速やかにそれらを表示することがどうしても巧くいかなかったのです。

例えば、20個の取得を指示しても、過去エントリイは 3 つしか表示できないのに、未来エントリイは 10 個表示できたり、その逆だったり、二度目に実行すると必ず 20 個全てのタイトルを表示取得できたり、結果取得が非常に不安定だったのです。

どうしてそうなるのか、どうすれば問題を解消できるのか、その解決策を求めて上記書籍を購入したのですが、そこからは解決策は得られませんでした。

あれこれのサイトも探索しましたが、1回だけの Ajax 通信に jQuery.js を利用した例はいくつか見つかりましたが、連続してAjax通信を行って、その結果取得を試みたサイトは見つからないのです。

勿論 FireFox + Firebug を利用して進行過程をチェックしてみましたが、Ajax 通信の進行過程は流石の Firebug でもブラックボックス化してしまい、その過程を覗くことが出来ませんし、Firebug でコードのステップ進行している間にも Ajax 通信は進行するので、通信過程を垣間見ることは出来ませんでした。

更に、Firebug でコードをステップ進行するということは、その間に Ajax 通信の進行を許す訳ですから、いわば待機時間を作ることになり、通常では巧く取得できない結果も Firebug を使って進行をチェックすると取得に成功してしまうのです。

つまり、Firebug を使っても Ajax 通信のコードチェックにはならないのです。

▲ToTop

連続した Ajax 通信においてその全ての通信結果が取得できたことをどのようにして知るのか?

連続する Ajax 通信結果を可及的速やかに表示するためには、最後の通信結果が取得できたそのタイミングを Javascript に知らせなければなりません。スクリプトがそのことを知って初めて表示させる事が出来る訳ですから、通信結果が全て取得できたことをコード自体に分からせなければなりません。

その方法を色々と暗中模索した経緯の一端を以下に記しておきます。

最後の通信結果が存在すれば..

例えば「最後の通信結果が存在すれば..」という条件では不完全です。何故ならば最後の通信結果が取得できたからと言って、それ以前の通信結果が取得できている保証は何もないからです。

実際色々試してみましたが、Ajax 通信の所要時間は、それぞれの Ajax 通信の通信量と回線速度によって変化しますが、回線速度が同一であれば Ajax 通信量で決まります。つまり通信されるコンテンツの容量によって通信時間は決まります。今回の例においては、取得する HTML ファイルの容量、つまり各エントリイの本文の長短に応じて通信所要時間が変化します。大きなサイズのエントリイの場合には通信時間が長くなり、小さなサイズの場合には短くなります。

故に最後の通信が終わってもそれ以前の通信が終わった保証はどこにもありません。

通信毎に flag を立てたら..

flag を立てることも検討しましたが、Ajax 通信のどの段階で flag を記述すればよいのか、それが問題です。結果を取得できたその時に立つ flag でなくては意味がありません。ではどこに?

jQuery を活用する前提で考えてみると、なかなか適切な回答が見いだせないまま、空しく月日が流れました。

1 つの光明は jQuery.active プロパティの活用だった

flag をどの様にして立てようか思案する中で、改めて jQuery.js の Ajax 通信部分を眺め回し、また上記で紹介した書籍の Ajax 通信部分を見てみて、jQuery.js の Ajax 通信コード部分に既に flag が立てられていることを知りました。

それはクラス jQuery の 1 つのプロパティであり、コード実行時に Ajax 通信数を数えるカウンターとして利用される jQuery.active です。

そのカウンターは jQuery.ajax() メソッド内で活用されますが、その値は Ajax 通信を行おうとする度に、send コマンド実行直前に 1 だけ増加し(ver1.2.6 の 2650 行)、結果を取得し終えると 1 だけ減じられ(ver1.2.6 の 2835 行)ます。つまり、連続して Ajax 通信を指示すると、その値は順に増加し、それが終わる度に順不同で減じられる仕組みとなってます。(但し、jQuery Ajax 諸定数の1つである global 値を初期値の true ままにしておかなければ、何回 Ajax 通信を行っても、jQuery.active 値は 0 から変化しません。───jQuery.js ver1.2.6: 2650 行と 2835 行)

これを活用すれば、連続通信を開始した後にその値が 0 になるタイミングを捉えて取得結果をまとめて表示することが出来るはずだ、と推測し、実際にその推測は当たっていました。

jQuery.active プロパティを利用することにより、連続した Ajax 通信が完了したことを Javascript に知らせることの出来る flag を獲得することが出来たのです。

というよりも、正確に言えば、そもそも jQuery.active プロパティはそのような目的で作成されたもの、と言えるでしょう。

jQuery.active 利用と Ajax globalイベントの関係に係る若干のコメント

jQuery.active 利用しようとする時に、必ずしも Ajax global イベントを利用する必要はありません。global 値を true としておかなければ、jQuery.active は利用できませんが、それを利用するために Ajax global イベントを使う必要はありません。

jQuery.js の初期値のままで global 値は true となっているので、何も操作することなく「local callback」関数の中で jQuery.active を活用できます。

timerを使った jQuery.active 活用の実際

1回の Ajax 通信の場合には jQuery.active を活用するまでもなく、容易に結果を取得/表示出来ますし、複数回の通信の場合でも「概ね」問題なく結果を取得/表示できました。

これまでに試みてきた全ての自作 Ajax local コード(頁トップに掲載した関連エントリイ参照)において、jQuery.active が全てで目的通りに作動すること、つまり、第一に jQuery.active ==0 が全ての Ajax 通信が終了したことを意味し、第二に、その値になれば全ての Ajax 通信結果が取得出来ていることを確認しました。

jQuery.active 活用の要点

Ajax 通信コード部分より下に、以下のように同一関数の間欠起動を設定し jQuery.active 値がゼロになる迄 Ajax 通信完了を待機し続け、ゼロになってから(つまり全ての Ajax 通信が終わってから)結果をまとめて表示すれば良い訳です。

 function display(){
  if (jQuery.active==0) {
   if (timer) {clearInterval(timer);timer=null;}
   ・・・ここに全ての通信結果を表示するためのコードを記述する。・・・
  }
 }
 var timer = setInterval(display,milsec);
しかし、1 回の jQuery.active 活用だけではまだ不十分だった

ところが、1 回の jQuery.active の活用だけではどうしても全ての Ajax 通信結果を一括表示出来ないケースが発生しました。つまり、一括取得は出来ているのに、一括表示が出来ない場合が生じたのです。

そのケースとは、4 つめのチャレンジとして試みた、任意の Fc2 ブログの任意のエントリイの以前/以後/最新エントリイタイトルを取得するコードの場合でした。当然、そのような現象が発生する理由について、一人悶々とと分析しました。分析し続けました。数ヶ月に亘って・・・。

そしてやっと到達した要点は次のような、今更ながらの基本的なことでした。

  • 第一に、( 分かってみれば余りに当然のことですが )連続する Ajax 通信中において、先行する通信コードの中で設定した変数を、後続する他の通信中で活用しようとする時、先行する通信の中で変数が取得できていない時点で、後続する通信コードの中でそれを利用しようとすれば、当然エラー( 値は undefined となる)となること
  • 第二に、最も確実な連続 Ajax 通信コードの書き方は、先行する通信が終わったことを確認する何らかの flag を設定し、それを確認してから次の Ajax 通信が進行するようにコードを記述すればよいこと
  • 第三に、しなしながらその方法を採用すると、全体の通信完了までに相当の長時間を要してしまい、実用的ではないこと
  • 第四に、従って jQuery.active を複数回活用して各 Ajax 通信完了 を待機させれば、確実に各通信完了を javascript に認識させられること

───などでした。

そこで原点に返って可能な限り Ajax メソッド内で行ってみた

上記の再確認した基本的事項を踏まえて、Ajax 通信コードの外であれこれ操作して Ajax 通信結果を取得する試みがどうしても巧くいかないことから、原点に返って全てを Ajax 通信メソッドの内で行ってしまった方がよいのではないか、と考え直しそれを実行してみました。

すると驚いたことに、あるいは当然の結果なのかも知れませんが、これまでの悩みが嘘のようにあっさり解決してしまったのです。

詳細は以下のエントリイに記述しました。

jQuery が Ver1.2.6 へUP

1.2.3 から一気に 1.2.6 へ

1.2.6 のリリースは 5月 24 日、本家サイトに拠れば「Releases 1.2.4 and 1.2.5 were skipped 」。1.2.4 と 1.2.5 はそれぞれ問題があったためだそうです(1.2.4 was built incorrectly, rendering it effectively identical to 1.2.3, and 1.2.5 was missing a patch.)

1.2.3 からの改良は高速化と新機能にあり、以下のように紹介されています。

  • Performance Improvements(速度改善)
    • Event Handling is 103% Faster
    • CSS Selectors are 13% faster
    • .offset() is 21% faster
    • .css() is 25% faster
    • .css() is 25% faster
  • New Features and Major Changes(新機能と大きな変更)
    • Dimensions Plugin is Now Part of Core
    • .attr() overhaul
    • .toggle() can now accept more functions
    • .index() supports jQuery collections
    • beforeSend can cancel Ajax calls
    • Exposed Speeds

それなりに魅力的なマイナーバージョンアップだ

高速化は歓迎すべき改良点であり、言わずもがなの前進でしょう。

それぞれの高速化がどの様なコードの変更によってもたらされたのか、その解明に興味をそそられます。

また、Dimensions Plugin の扱いやtoggleメソッドの機能拡張も興味深い点です。ユーザーフレンドリーなコード作成に活用出来るのではないか、と期待させられます。

▲ToTop

いずれにしても・・・jQuery の解読を先に進めたい

1.2.2における解読が暫く中断してますが、更なる発展を遂げつつあるjQueryの解読を今回のバージョンアップを契機として、更に先に進めたいと改めて感じ入った次第です。

イベントコードの解読を終えたのは既に約半年前になってしまいましたが、次は jQuery.js のAjax 関連コードの解読に踏み込みたいと考えている今日この頃です。

FireBugLite における mousemove/mouseup イベントについて

FireBugLite のブックマークレットによる組み込み

firebug Liteを組み込みたいサイトに対して、一々その html を加工して firebug Liteをインクルードするのは面倒ですから、誰しもそのインクルードをブックマークレット等によって容易に行えるようにしたい、と考えるでしょう。

そして過去に、それを実現しているサイトを見つけたのですが、最近そのブックマークレットが利用しているファイル置き場が消失してしまい、当該ブックマークレットが使えなくなってしまいました。(WebOS Goodies:Firebug Lite をブックマークレット化しました - WebOS Goodies

そこで WebOS Goodies に倣って、 GooglePages に Firebug Lite 関連ファイルを置き、自作ブックマークレットを活用しようと思い立ったのです。

ところが、Firebug Lite サイトからダウンロードしたファイルを単純に解凍し、解凍後のファイルをファイル置き場として使用する Google Pages にアップロードし、それを利用したブックマークレットを作ってみても、それだけでは Firebug Lite は使えませんでした。

その原因を探るべく WebOS Goodies の「Firebug Lite をブックマークレット化しました」頁をよく見てみると、firebug.js を多少加工して upload している、等のブックマークレット作成上の留意点(※)が書いてありましたので、それを真似て firebug.js に必要な加工を施して upload してみたのです。すると、確かに Firebug Lite の起動には成功したのですが、新たに次の課題が出現しました。

Firebug Lite をブックマークレット化しました - WebOS Goodies からの引用
  • firebug.html の内容を文字列として firebug.js に埋め込み、IFRAME に document.write で流し込むように変更。
  • CSS の URL を変更。
  • ファイルを Google Page に保存する都合で、見分けやすくするためにアイコンのファイル名を変更。
  • Opera できちんと動くように、 z-index の値を小さめ(65536)に変更。
  • こちらの記事のアイディアを参考にして、改行が反映されるように writeRow 関数で生成するタグを pre に変更。ただし、 IE では効果がないようです(謎)。

Opera では問題なし。しかし IE では・・・

Opera では狙い通りに FirebugLite が組み込まれ作動しました。jQuery.js とのダブルインクルードも成功し、FirebugLite 上で jQuery.js を利用することも出来ました。

しかし IE においてはマウスカーソルを動かすだけで、Firebug Lite によって用意されるインラインフレームの高さが上下してしまうため、思うように使えないのです。

その原因を探るためFirebugLite.jsを紐解いてみたところ、原因は 202 行の「toolbar.onmousedown = onSplitterMouseDown;」にあることが判明しましたので、この行をコメントアウトしました。つまり、toolbar 上のマウスダウンイベントを無効にしてしまった訳です。

これにより、202 行によって登録されることになる onSplitterMouseMove 及び onSplitterMouseUp イベントも同様に無効になるわけですが、不如意なフレームサイズ変更は操作上大きな支障を来すためやむを得ない処置であると思います。

また、frame内に表示させるために用意されている firebug.html も不要なので、217行もコメントアウトしました。

▲ToTop

改訂した FirebugLiteを Google-Page 上に置く

こうした改訂を施した firebug.js を Google-Page 上に置いて活用するようにしたのです。

Fc2ブログの場合、ファイル置き場を認めていませんから、 Google-Page 上に置いて活用するようにしたことにより、任意の Web サイト上において FirebugLite を活用できるようになった訳です。

後はこれをインクルードする問題が残るだけですが、それについては別項( Query と FirebugLite を一括登録するブックマークレット: )でまとめました。

Ajax通信による最新/以前/以後の合計30個のエントリイタイトル情報の取得について

このエントリイの改訂履歴
  • 初稿:2008/3/23
  • 大幅な追記(連続するAjax通信の結果をどのようにして過不足なく取得するのかについて):2008/7/13
3/23 の記事

jQuery を活用した Ajax 通信にここ半年ほどのめり込んできました。

しかしアクセスログを見てみると、Ajaxに関するエントリイは余りアクセスが有りません。つまり関心を呼んでいないのです。

jQuery + Ajax の組み合わせは決して一般的ではないし、Javascripter にとってさえもメジャーな話題ではないのかもしれません。つまり、jQuery の Ajax ユーティリティを利用する行為自体が極めてマニアックなのかも知れません。だからアクセスも少ないのでしょう。

決して見られるために書いている訳ではないので、アクセス数に一喜一憂している訳ではありません。それはある意味では二の次であって、書きたいことを書き綴ることに意味があります。一般的な話題ではなく寧ろ deep な話題と言えますから、その意味では閲覧される確率は決して高い筈はないと思います。

それでも尚、読まれているかどうかは気になります。

反応は皆無に近く(あるのは迷惑千万なエロイ書き込みばかりです。(;_;)ウルウル)

最近は、無言の黒い壁に向かって全く自己満足で書き続けている気がしています。

それもこの国の Blog の1つの有り様ですから、致し方ないことなのですが...

▲ToTop

jQuery や Ajax を話題とするサイトや SNS を見つけたい

どうせ書くならば、共通の話題に関心のある方々に読んで貰いたい、あるいは情報交換をしたい、と願っています。

こう書いたからと言ってアクセスが増えたり、また情報交換が可能となるなんて思っていませんが、それでも尚書き綴りたい今日この頃なのです。


以後は 7/13 の記事

連続するAjax通信結果を過不足なく取得する具体的な方法

以下の関連エントリイに共通する「 連続する Ajax 通信からの結果取得方法 」について、ここでまとめておきます。

つづく

Google Code を利用した感想

Google Code は簡単に利用できるファイル置き場としてGood!

Google Code は1プロジェクト当たり 100MB のディスクスペースが提供され、1ユーザー当たりのプロジェクト件数制限は見あたりませんので、実質無制限なファイル置き場として活用できます。

与えられる URI はプロジェクト名から始まるので分かりやすく、upload、download 操作も簡単にできます。

英語の説明書きしかありませんが、特に難しいことが書いてある訳でもないので、何度か使えば操作も難しくありません。

多くのディスクスペースが id やパスワード入力を求め、ファイル置き場としての利用に大きな制限を掛けている中で、Google Code の存在は貴重なものです。

ファイル上書き操作に難点が...

以前次のように書きました。

Google Code では登録済みファイルの上書き更新が出来ません。間違って登録してもそれを取り消せないのです。説明を読むと削除に同一名による新規ファイル登録が可能なように書いてあるのですが、何度試しても駄目でした。

この上書き禁止ルールは、際限なく登録されるファイル置き場として悪用されないための、1つの防護策なのかも知れません。

上に書いたことは正確ではありませんでした。

上書きは基本的に可能で、そのことは説明通りでした。注意すべきことは上書き変更が即座に反映されないことです。

上書きしてもその変更結果を直ぐに確認できないのです。しかし一定の時間(それが何時間なのか、何日なのかは不明)が経過すると、確かに変更が反映されます。

つまり、頻繁にファイル更新を行う行為は認めないが、ファイルの上書きは認める。頻繁な更新を抑制するために、更新にタイムラグを設け、出来るだけ更新を行わないようにさせる───という設計思想だと考えられます。

以上の特性を踏まえて利用すれば、大変貴重で有益な無料サービスだと思われます。

また、Systems engineer の間では Google Code Search が注目されているようで、Google Code でネット検索しても search のことばかりが表示されます。

▲ToTop

Javascript コードおよびCSSファイル説明

ファイル構成

ファイル置き場と Ajax 通信を活用して、任意のFc2ブログから情報を得る

  • 2008/3/12 : 初稿
  • 2008/7/9 : コードの抜本改訂とファイル置き場利用版up
  • 2008/7/12 : Ajax 通信関連部分を更に抜本改正
  • 2008/7/20 : Ajax 通信関連部分で確実性を更に向上(ここで Ajax 関連コードは完成し、これ以降はあれこれのユーザビリティの向上対策を施した。)
  • 2008/7/21 : id 及び class 名称を他の Fc2 ブログで使われていないと推定される固有のものに変更
  • 2008/8/12 : 各 Ajax 通信所要時間を記録し閲覧できるように変更。このプロジェクトの削除(関連cssファイルやjsファイルの登録削除)と隠蔽(単にpopup小窓を隠すだけ)を分け、各ボタンを配置。
  • 2008/8/14 : responseText の 文字化け対策として、或る <meta/> タグを追加するように変更

他ブログ上での Ajax 通信をついに実現( 2008/7/9 記 )

上の関連エントリイでつらつらと述べてきた課題──すなわち他の任意のFc2ブログサイト上において、ブックマークレットによって必要なスクリプトをインクルードし、当該スクリプトによる Ajax 通信によって当該ブログの情報を取得し、それを当該ブログ上に表示する──が、やっと解決しました。( 8/12 完結 )

上記 「 Related Entries in this Blog 」 の No1エントリイで計画したことが、No.2 エントリイで述べた、過去/未来/最新エントリイタイトル取得/表示を行う Ajax 通信の成功と、No.3 とNo.4 エントリイで述べたファイル置き場問題の解決によって実現したのです。

何はさておき、結果を画像で紹介することが最も分かりやすいでしょう。( 2008/8/14 追記 )

サンプル 1【 Fc2総合インフォメーションブログ 】

下の画像は、Fc2総合インフォメーションブログ上でこのプロジェクトを実行した際の表示結果抜粋です。

Fc2 総合インフォメーションブログ上で Ajax 通信によって最新/以前/以後エントリイのタイトル情報などを取得した結果を示すサンプル画像 1
サンプル 2【 関西ZIGZAG 】

下の画像は、人気ブログ「 関西 ZIGAZAG 」ブログ上でこのプロジェクトを実行した際の表示結果の抜粋です。

関西 ZIGAZAG ブログ上で Ajax 通信によって最新/以前/以後エントリイのタイトル情報などを取得した結果を示すサンプル画像 2
サンプル 3【 FCafe 】

下の画像は、自ブログ開設時からお世話になってきたサイト上でこのプロジェクトを実行した際の表示結果の抜粋を示すものです。

FCafe ブログ上で Ajax 通信によって最新/以前/以後エントリイのタイトル情報などを取得した結果を示すサンプル画像 3

今回のプロジェクト「Fc2ブログ エントリイ情報取得」の概要

今回作成したコード群は、任意の Fc2 ブログ上で jQuery を活用してエントリイタイトル等を取得するツールです。また併せて jQuery.js と ( Firefox 以外の browser の場合には )firebugLite もインクルードするようにしたので、IE や Opera などにおいても jQuery と firebugLite を使用し、スクリプトテストや DOM 操作を行うことも可能としました。

つまり、或る Fc2 ブログサイトの、或る個別エントリイ頁を開いた状態でブックマークを起動すれば、以前、最新及び以後の各 10 個のエントリイに係る諸情報(具体的にはタイトル、Entry番号、投稿日など)が閲覧できると共に、そのページ上で jQuery.js と firebugLite.js を使って Javascript コードの実行が出来るわけです。

プロジェクトのファイル構成( 2008/7/9 記 )

コード群はブックマークレットを含めて以下の6つから構成されます。

  1. ブックマークレット……次の setjQnFbug_getFc2EnTts.js を登録するため
  2. スクリプト登録用JSファイル( setjQnFbug_getFc2EnTts.js )……今回のプロジェクト実行に必要な以下の 4 つの全てのファイルを、今閲覧中の任意の Fc2 サイトのHTML文のヘッダー部に登録するための、短い Javascript コードファイル
  3. 上の 2. のファイルで登録するファイルは以下の 4 つです。
    1. jQuery.js、
    2. firebug.js、
    3. getFc2EntryTitles-gp.js( Ajax 通信用オリジナルJSファイル)
    4. getFc2EntryTitles-gp.css(通信結果表示用オリジナルスタイルシート……Ajax通信結果を固有に用意した絶対配置要素内で表示させるために、各ブログに依存しない固有のスタイルシートを用意)

ここに、このプロジェクトでは Ajax 通信処理をはじめとして、随所に jQuery.js を多用したコードを記述し実行しているため、jQuery.js が組み込まれていないブログの場合も想定し(大多数は組み込まれていないと思われる)、なければそれをインクルードするようにしました。

また firebugLite も組み込むようにしたので、IE や Opera 上でも Javascript のテストが容易に出来るようにしました。

以上により、Fc2のブログであれば何であれ、個別エントリイ表示モードの場合において、jQuery を活用して Ajax 通信を行い、エントリイタイトル情報を取得すると共に、firebugLite を使った Javascript の走行テストが出来るようにしました。

▲ToTop

ファイル置き場は Google Page を活用( 2008/7/9 記 )

ファイル置き場に出来るかも知れない、と考えた Just Sysytem 社のインターネットディスクは、同社への問い合わせの結果、使えないことが判明しました。また SONY の WebPocket にも問い合わせましたが、こちらも駄目でした。

有料なのに、それでもなお、ファイル置き場を認めない理由は全く理解できません。

確かに「 アクセスが集中する、ウィルスファイルを置かれる可能性も否定できないから踏み台とされる、つまりサービスの利用よりも悪用に手を貸すことになる 」等の否定的な側面が懸念されます。そしてこの懸念から解放されるためには、ファイル置き場を認めないことが安易な方法なのでしょう。

───と、いくら批判し、嘆いていても仕方ないので、調べた中で、無料で容易にファイル置き場として利用できる Google Page ウェブサイトを活用することにしました。Google page 上にマイページを立ち上げ、そこに上記 6 つのファイルの内ブックマークレットを除く 5 つのファイルを GooglePage サイトに upload し、自作ブックマークレットを作動させてその稼働を半年以上に渡って確認しています。

※ この少し下に成功したブックマークレットを置きました。

このプロジェクトの利用方法( 2008/3/12 記 )

ブックマークレット

以下のブックマークレットを(ブックマーク又はお気に入りに登録し)クリックすれば、関連する JS ファイルや CSS ファイルが head タグ内に追加され、固有の絶対配置要素が画面上部に表示されます。FireFox 、 Opera 及び IE7 で動作確認済みです。

後は Before・・・、Recent・・・、After・・・ などのボタンをクリックすれば、所定の情報が絶対配置要素内に表示されます。

Ajax 通信をやり直すボタン( ReLoad Data ボタン )や、Ajax 通信に要した時間を知ることが出来るような Log 閲覧ボタンも設置しました。また、結果を表示する小窓が邪魔になったら、隠蔽することも出来るし、ブックマークレットによってインクルードした関連スクリプト・cssファイルを削除するボタンも設置しました(但し jQuery.js と firebug.js は残すようにしました)。

こうして、Ajax通信結果を示す小窓が邪魔になったら隠蔽し、ブックマークレットを再起動すれば、隠蔽直前の状態で小窓が復帰するようにすると共に(Ajax 通信結果は閲覧中の頁がリロードされない限りメモリ上に残る仕様としたのです)、インクルードファイルが邪魔になったら簡単に剥離・削除出来る仕様にしました。

次のブックマークレットをお気に入りに登録すれば、今回のプロジェクトを任意の Fc2 ブログサイトで共通して使うことが出来ます。また、単に以下のブックマークレットをクリックするだけでも、今ご覧戴いているこのエントリイを対象としてブックマークレットを利用できます。

このプロジェクトの起点となるブックマークレット

※ 2008/8/11迄上記ブックマークレットのコードに一部ミスがあり機能しませんでした。利用しようとしてくださった方々には大変ご迷惑をお掛けいたしました。

Ajax 通信結果の表示

ブックマークレットをクリックすると、次のような小窓がブラウザの上部に表示されます。

Ajax 通信結果を表示する絶対配置要素の図

上の図は既に Ajax 通信が終わった状態の画像ですが、7つのボタンは左から順に「(1)今見ているエントリイの前の10個のエントリイタイトル表示、(2)最新の10エントリイ表示、(3)今見ているエントリイの後に投稿された10エントリイのタイトル表示、(4)Ajax通信再実施、(5)所要時間表示閲覧、(6)小窓の隠蔽、(7)関連スクリプトやcssファイルの削除」を行うためのものです。

例えば 「 Recent Entries 」 ボタンをクリックすると下図のようにタイトル名とエントリイナンバーが表示されます。Ajax 通信をやり直すことができるように設けた 「 Relaod Data 」 ボタンは、何らかの事情で取得結果がおかしかった場合などに Ajax 通信をやり直すことが出来るように配置したものです。このボタンをクリックすれば Ajax 通信に要した時間を比較して知ることも出来ます。

Ajax 通信結果である過去エントリイ10タイトルを見ている図
表示エントリイ上で jQuery と Firebug Liteを活用!

単に、エントリイタイトルを閲覧するだけでなく、このプロジェクトでは jQuery.js と FirebugLite もインクルードしますので、IE や Opera において、ちょっとした Javascript 利用が(デバッグ環境とまではいかないが、テストや学習に活用出来る)、エントリイ頁上でリアルタイムに行えるようになります。F12 キー又は CTRL+Shift+Lキーを押せば firebug Lite を起動することが出来ます。

▲ToTop

Javascript コードおよびCSSファイル説明( 2008/3/12 初稿:その後漸次改訂。確定は2008/8/14 )

1. スクリプトをインクルードするためのブックマークレット

ブックマークレットは各種のスクリプトや CSS ファイルをインクルードするための、いわば初期化スクリプトです。たった1つのスクリプトの存在をチェックし、存在していなければインクルードします。

そもそも全てのコードをブックマークレットに記述できればそれが最も合理的なのですが、ブックマークレットにはブラウザ毎に文字数制限があり、ここで行ったことはとてもその制限値内には収まらないので、複雑な手続きを経なければなりませんでした。

<a href="javascript:
(function(){
  // 文字数を減らすために変数を纏めて指定
  var%20x=0,i=0,
  h=document.getElementsByTagName('head')[0],
  t=document.getElementsByTagName('script'),
  s=document.createElement('script');
  // headタグ内を検索して
  if(t) for(;i<t.length;i++) 
    // setjQnFbug 文字の有無を走査し、有れば x に 1 を代入
    if(/setjQnFbug/.test(t[i].src)) x+=1;
    // setjQnFbug 文字が見つからなければ所定のjsファイルをインクルードする
    if(x==0){
      s.src='http://hkom007.googlepages.com/setjQnFbug_getFc2EnTts.js';
      s.type='text/javascript';
      // headタグ内にスクリプトタグを追加
      h.appendChild(s);
    // 既に所定のjsファイルがインクルード済みならば所定の関数(chkScript)を起動する。
    // この関数は3つのjsファイルと1つのCSSファイルのインクルードを行うためのもの
    }else%20chkScript();
})()">set jQuery & FirebugLite & getFc2EntryTitles.js</a>

▲ToTop

2. Javascript 及び css ファイルの一括インクルードを行う

setjQnFbug_getFc2EnTts.js は 4 つのファイルを一括してインクルードするコードだけを記述した 小さな JS ファイルです。といってもブックマークレットにするには文字数が多すぎてIEで読み込めないため、ブックマークレットとは別に設置した訳です。このファイル作成の当初段階では、インクルードするだけではなく、その後の処理も1つのファイルに纏めようとしましたが、それは無理でした。

何故ならば、インクルードのためのコードに続けて、インクルードされたファイルを使用して様々な処理を行うコードを書いて実行すると、インクルードが中断されてしまうからです。

ブラウザがファイルをインクルードする処理を行っている間に、JS インタープリタが次の処理を行おうとすると、インクルードそのものが中断されてしまうのです。

そのためインクルード専用のファイルと、インクルードされたファイルを利用して諸処理を実行するコードを記述したファイルとを別々に分けました。

// このスクリプトがインクルード済みの場合に関数が起動できるよう
// 名前付き関数とし、最後の行でこの関数を起動する。
var chkScript = function(){
  var v=0,w=0,x=0,y=0,z=0,i=0,
    h=document.getElementsByTagName('head')[0],
  m=document.getElementsByTagName('meta'),
    t=document.getElementsByTagName('script'),
    l=document.getElementsByTagName('link'),
    s=document.createElement('script');
  // 文字化け対策 
  // http-equiv="content-type" かつ content="application\/x-javascript charset=euc-jp"であるmetameguがあるかどうか走査
  // 存在すれば v 値を加算する。 
 if(m) for(;i<m.length; i++){
  if(/content-type/.test(m[i].getAttribute("http-equiv"))
   && /application\/x-javascript charset=euc-jp/.test(m[i].content)) v+=1;
 }
  // v 値がゼロならば meta タグを追加する。 
 if (!v){ 
  var k=document.createElement('meta');
  k.setAttribute("http-equiv","content-type");
  k.content = "application/x-javascript charset=euc-jp";
  h.appendChild(k);
 }
  // 所定のスタイルシートがインクルード済みかどうか link タグ走査し、あれば記録。
 if(l) for(i=0 ;i<l.length; i++) {if(/getFc2EntryTitles/.test(l[i].href)) w+=1}
  // CSSファイルのインクルード
 if(!w) {
  var k = document.createElement('link');
  k.rel = "stylesheet";
  k.type = "text/css";
  k.media = "screen, print";
  k.href='http://hkom007.googlepages.com/getFc2EntryTitles-gp.css';
  h.appendChild(k);
 }
  // jquery、firebug 及び getFc2EntryTitles の文字を含むスクリプトタグを走査し、
  // 存在していればそのことを記録する。
 if(t) for(i=0;i<t.length;i++){
  if(/jquery[^u][^i]+/.test(t[i].src)) x+=1;
  if(/firebug/.test(t[i].src)) y+=1;
  if(/getFc2EntryTitles/.test(t[i].src)) {
      // ブックマークレットが複数回起動された場合の処理
      // インクルード済みで結果表示小窓が非表示ならば表示する
      var tmp = document.getElementById("ajaxPopup");
      if (tmp && tmp.style.display == "none") tmp.style.display="block";
    } // 結果表示小窓が表示済みならば、何もしないでif文を終える。
 }
  // 以降で反復利用する文字列を定義
 s.type='text/javascript';
  // jQuery.js のインクルード
  // jQuery.js は単に firebug Lite から利用するだけではなく、Ajax通信や
  // その取得結果を表示するコードで多用します。
  // なお、min 版を利用することにしました。
 if (!x){
  s.src='http://hkom007.googlepages.com/jquery126min-gp.js';
  h.appendChild(s);
 }
  // firebugLite のインクルード
 if(!/firefox/.test(navigator.userAgent.toLowerCase()) && y==0){
  var c=document.createElement('script');
  c.src='http://hkom007.googlepages.com/firebug-gp.js';
  c.type=s.type;
  h.appendChild(c)
 }
  // Ajax 通信を行う本体コードの getFc2EntryTitles.js のインクルード
 if (!z){
  var r=document.createElement('script');
  r.type=s.type;
  r.src='http://hkom007.googlepages.com/getFc2EntryTitles-gp.js';
  h.appendChild(r);
 }
  // 無名関数としなかったのは再呼び出しがあり得るからです。
};chkScript(); //関数実行

▲ToTop

3. 結果を表示する小窓用 CSS ファイル

取得結果を絶対配置要素内に表示させるために、CSS ファイルを作成しました。これによりどんな Fc2 ブログであっても Ajax 通信結果を同様に表示するようにしました。

なお、任意のFc2ブログで活用できるようにするには、id や class の名称に工夫が必要であることを、いくつかのサイトで試してみて納得しました。このプロジェクトで利用する名称が、閲覧しているブログサイト内で利用されてる名称と重複してしまってはいけない、ということです。

このことは振り返れば余りに当たり前のことですが、実行して初めて分かった次第です(^_^;)。

経緯はこうでした。( 2008/7/21 追記 )

FC2総合インフォメーション 【ブログ】画像ファイル挿入の仕様変更のお知らせ でこのプロジェクトを試してみたのですが、その際に当該サイトで使用されている id 名称( #menuBlock )が、このプロジェクトで利用していた id 名称と重複していたため、当該サイトでは予想外の挙動が起きてしまいました。

そこで初めて、任意の Fc2 サイトと id や class 名称が干渉しないよう、このプロジェクトでは他には絶対に存在しないであろう、固有の名称を使用しなければならない、と気がついた訳です。

こうして id 及び class 名称は以下にあるように長たらしいものとなりました。全ての id 及び class 名称に、「 getEntryTitles_ 」なる接頭語を付けたのです。これで「おそらく」世界で唯一の名称になったのではないか、と一人合点しています。

更に CSS ファイルでは重要なことがあります。( 2008/8/17 追記 )

それは自分のブログで様々な CSS コードを書いている限り全く問題とはならなかったことであり、他のサイト上で自分が書いた CSS ファイルを適用する際には、必ず注意しなければならない問題です。

その問題とは CSS ファイルの優先順位です。

ブラウザにはそれぞれ固有のスタイル値があり、また当然のことですがそれぞれのブログには、作者固有の、またはテンプレート固有のスタイル値があります。そして私が考え、CSSファイルで表現したスタイル値があります。これらの優先順位についてこれまで全く考慮する必要がなかったのですが、他の方のブログ上で MyCSS ファイルを適用することになった時点で、即座にこの CSS ファイルの優先順位が切実な課題となってきたのです。

そこで数年ぶりに改めて CSS の学習を思い起こし、また一部再学習して !important 属性を使うことに到達しました。

@charset "euc-jp";
	#getEntryTitles_pasteData ul { /* important によって任意の Fc2ブログにおいて同一の */
		margin:0 0 0.5em 1.5em !important; /* 結果を得るようにした。*/
		padding:0 !important; /* ここに到達するまでに結構悩んでしまった。*/
		clear:both !important;
	}
	#getEntryTitles_pasteData ul li{
		margin:0 !important;
		padding:0 !important;
	}
	#getEntryTitles_ajaxPopup{
		position:absolute; z-index:100000; top:150px;left:50%;
		width:0; height:0; margin:0px;
		font-size:small;
		text-align:left;
		color:black;
		display:none;
	}
	#getEntryTitles_menuBlock {
		padding:10px;
		width:0px; height:0px;	/*not auto*/
		background-color:#def;
		border:2px #777 solid;
		display:none;
	}
	#getEntryTitles_loading {
		clear:both;
		padding:5px 10px;
	}
	#getEntryTitles_pasteData {
		clear:both;
		margin-top:-28px;
		display:none;
	}
	#getEntryTitles_pasteData a:link{color:blue; text-decoration: none;}
	#getEntryTitles_pasteData a:visited { color: purple; text-decoration: none;}
	#getEntryTitles_pasteData a:hover {
		color:darkgreen;
		background:#dd0; 
		text-decoration: none; 
	}
	#getEntryTitles_pasteData a:active { color: lightblue; text-decoration: none;}

	#getEntryTitles_finish, #getEntryTitles_resultbefore, #getEntryTitles_resultrecent,#getEntryTitles_resultafter {
		padding:0 10px 10px 10px;
		background:#def;
		border-left:2px #777 solid;
		border-right:2px #777 solid;
		border-bottom:2px #777 solid;
		display:none;
	}
	.getEntryTitles_btn {
		width:120px;
		float:left;
		margin:0 2px;
		padding:2px;
		border:1px black solid;
		font-weight:bold;
		color:white;
		background-color:#89A;
		text-align:center;
	}
	#getEntryTitles_viewLog {
		float:left;
		width:50px;
		margin:0 2px;
		padding:2px;
		border:1px black solid;
		font-weight:bold;
		color:white;
		background-color:#89A;
		text-align:center;
	}
	#getEntryTitles_hideThis, #getEntryTitles_removeThis {
		float:right;
		width:20px;
		margin:0px 2px;
		padding:2px;
		border:1px black solid;
		font-weight:bold;
		color:white;
		background-color:#89A;
		text-align:center;
	}
	#cmtbtn1{
		text-align:center;
		margin-top:-2em;
		display:block; width:16em; float:right;
	}
	#cmtbtn2{
		text-align:center;
		border:1px solid darkgray;
		padding:2px;
		margin-top:-2em;
		width:12em; float:right;
	}

▲ToTop

4. メインの JS コード( Ajax通信実施、結果表示等全ての処理を実行する )

Ajax 通信処理、取得結果表示処理などを行うメインコードを書いたファイルです。

必要なファイル全てのインクルードを行ってから、getFc2EntryTItles-gp.js によって Ajax 通信処理を行い、その取得結果を表示中のブログ内に表示します。

結果を表示する小窓にはスクロールイベントを登録し、スクロール時にも常に画面上部に表示され続けるようにしました。

  1 :/* getFc2EntryTItles-gp.js
  2 : * 2008/7/21 Release
  3 : * 2008/8/12, 2008/8/17 update
  4 : */
  5 :// fc2ブログでかつ個別 Entry 表示モードの場合にのみコードを進行する。
  6 :if (location.href.indexOf("fc2")!=-1 && location.href.indexOf("blog-entry-")!=-1){
  7 :(function($){
  8 : var now=function(){return +new Date;}; // 時刻取得関数
  9 : $.extend({ // 時刻・timer起動回数記録用 jQuery 拡張オブジェクト
 10 :  tr:{
 11 :   start:now(),
 12 :   registerEvent:"",
 13 :   ajax:{ recent:[],before:[],after:[]},
 14 :   end:"",
 15 :   waitRecentAjaxCnt:0,setEndingCnt:0
 16 :  }
 17 : });
 18 : // ローカル変数定義
 19 : var aP,mB,ld,pD,fn,lg,r_c,r_b,r_a, constStr="getEntryTitles_";
 20 : var html = { before:[], after:[], recent:[] },getStr ={ before:"", after:"", recent:"" },
 21 :  blogTitle =null, regExpr = "",border={ before:0, after:0},realElm={before:0,after:0},thisEntryNo, lastNo, itval,complement,cmt=0;
 22 :
 23 : // 取得結果表示用のタグを作り表示する。
 24 : if ( $("#"+constStr+"ajaxPopup").size()==0) {
 25 :  $(document.body).append(
 26 :   '<div id="getEntryTitles_ajaxPopup">'+
 27 :    '<div id="getEntryTitles_menuBlock">'+
 28 :     '<button id="getEntryTitles_before" class="getEntryTitles_btn" title="このエントリイより前のエントリイのタイトル情報を見る">Before Entries</button>'+
 29 :     '<button id="getEntryTitles_recent" class="getEntryTitles_btn" title="最新エントリイのタイトル情報を見る">Recent Entries</button>'+
 30 :     '<button id="getEntryTitles_after" class="getEntryTitles_btn" title="このエントリイより後のエントリイのタイトル情報を見る">After Entries</button>'+
 31 :     '<button id="getEntryTitles_reload" class="getEntryTitles_btn" title="Ajax通信をやり直す">ReLoad Data</button>'+
 32 :     '<button id="getEntryTitles_viewLog" title="Ajax 通信の所要時間を見る">Log</button>'+
 33 :     '<button id="getEntryTitles_removeThis" title="このプロジェクトの関連スクリプトやcssを一気に削除する。">'+decodeURI(encodeURI("×"))+'</button>'+
 34 :     '<button id="getEntryTitles_hideThis" title="この小窓を隠蔽する。再表示はブックマークレットを再度クリックすれば良い。">-</button>'+
        // 通信中であることを表示するタグ
 35 :     '<div id="getEntryTitles_loading"><img src="http://hkom007.googlepages.com/loading_16.gif" width="16" height="16" border="0" alt="" /> Now Loading...</div>'+
 36 :    '</div>'+
 37 :    '<div id="getEntryTitles_pasteData">'+
        // 連続する Ajax 通信の全てが終わったことを表示するタグ
 38 :     '<div id="getEntryTitles_finish"><div><strong>Finish Ajax Communication !</strong></div><div id="getEntryTitles_log"></div></div>'+
        // 以前エントリイタイトル名等を表示するタグ
 39 :     '<div id="getEntryTitles_resultbefore"></div>'+
        // 最新エントリイタイトル名等を表示するタグ
 40 :     '<div id="getEntryTitles_resultrecent"></div>'+
        // 以後エントリイタイトル名等を表示するタグ
 41 :     '<div id="getEntryTitles_resultafter"></div>'+
 42 :    '</div>'+
 43 :   '</div>'
 44 :  );
 45 : } else {
 46 :  $("#"+constStr+"ajaxPopup").show();
 47 :  return;
 48 : };
 49 :
 50 : // 表示/非表示を操作するために必要な要素をショートカット変数に代入する。
 51 : aP=$("#"+constStr+"ajaxPopup");
 52 :  mB=$("#"+constStr+"menuBlock");
 53 :    ld = $("#"+constStr+"loading");
 54 :  pD=$("#"+constStr+"pasteData");
 55 :    fn = $("#"+constStr+"finish");
 56 :       lg =$("#"+constStr+"log");
 57 :    r_c = $("#"+constStr+"resultrecent");
 58 :    r_b = $("#"+constStr+"resultbefore"); r_a = $("#"+constStr+"resultafter");
 59 :
 60 : // 結果表示ポップアップに対するアニメーション関数。真ん中から吹き出すような効果を狙った。
 61 : var doExplodeShrink = function(elem,w,h,padbdr,left,state){
 62 :  elem.show().animate({
 63 :   width: w=="auto" ? "auto" : w+"px", height:h=="auto"?  "auto" : h+"px",
 64 : //  display:state, // IEでは機能しないためやむなく削除
 65 :   marginLeft:left ? (-parseInt(w/2)-padbdr+"px") : 0
 66 :  },400,"swing");
 67 : };
 68 :
 69 : // イベントハンドラー登録
 70 : $.tr.registerEvent=now();
    // 固定配置的に配置するためのスクロールイベントハンドラー
 71 : $(window).scroll(function(){
 72 :  $("#"+constStr+"ajaxPopup").css({
 73 :   top:10 +( window.pageYOffset || Math.max(document.body.scrollTop, document.documentElement.scrollTop) )+"px",
 74 :   marginLeft:-320+ ( window.pageXOffset || Math.max(document.body.scrollLeft, document.documentElement.scrollLeft) )+"px"
 75 :  });
 76 : });
 77 :
    // 最新/過去/未来エントリ情報を表示させるクリックイベントハンドラー
 78 : $.each([$("#"+constStr+"recent"),$("#"+constStr+"before"),$("#"+constStr+"after")],function(j){
 79 :  $(this).click(function(){
 80 :   $([fn,r_c,r_b,r_a]).each(function(i){
 81 :    i==j+1 ? $(this).show() : $(this).hide();
 82 :   });
 83 :   this.blur();
 84 :  });
 85 : });
 86 :
    // Ajax通信をやり直すボタン
 87 : $("#"+constStr+"reload").click(function(){
 88 :  $.tr.start=now();
 89 :  this.blur();
 90 :  pD.hide().children().hide();
 91 :  mB.hide();
 92 :  doExplodeShrink(aP,0,0,0,true,"none");
 93 :  ld.show();
 94 :  makeLists(10);
 95 : });
 96 :
    // Ajax通信に要した時間を見る為のボタン
 97 : $("#"+constStr+"viewLog").click(function(){
 98 :  $([r_c,r_b,r_a]).each(function(){$(this).hide();});
 99 :  fn.show();
100 :  this.blur();
101 : });
102 :
    // 小窓を一時的に隠蔽するボタン
103 : $("#"+constStr+"hideThis").click(function(){
104 :  this.blur();
105 :  aP.hide();
106 : });
107 :
    // プロジェクトに係るjsファイルやcssファイルを削除するボタン
108 : $("#"+constStr+"removeThis").click(function(){
109 :  this.blur();
110 :  aP.remove();
111 :  $("script[src*='getFc2EntryTitles']").remove();
112 :  $("script[src*='setjQnFbug']").remove();
113 :  $("link[src*='getFc2EntryTitles']").remove();
114 : });
115 :
116 : mB.children().hover( // ボタンにマウスオーバー/アウトした際のイベントハンドラー
117 :  function(){
118 :   $(this).css({color:"black",backgroundColor:"#dd0"});
119 :  },
120 :  function(){
121 :   $(this).css({color:"white",backgroundColor:"#89A"});
122 :  }
123 : );
124 :
125 :// 最近のタイトルを取得する関数を定義
   // limit 個数のエントリイタイトル情報を Ajax 通信によって取得する。
126 :var makeRecentEntryList = function (limit){
127 : var No, subject, date, iter=0, ret=[],
128 :  target ={  //xml ファイル内での順番
129 :     link:[],     //0
130 :   title:[],     //1
131 : // description:[],  //2 これは利用しない
132 : // content:[],    //3 同上
133 :    subject:[],    //4
134 :   date:[]      //5
135 :  };
136 :
137 : // エントリイタイトルを取得する
138 : $.ajax({
     // 閲覧中のFc2ブログの xml ファイルのアドレスを設定する。
139 :  url: /(http:.+fc2\.com\/.*)blog-/.exec(location.href)[1] + "?xml" || null,
140 :  type: "GET",
141 :  dataType: "xml",
     // xmlファイルが成功裏にダウンロード出来た場合の処理関数
142 :  success: function(xml){
143 :   var tmpStr = '<div>'+decodeURI(encodeURI("最新のエントリイ情報がありません。"))+'</div>';
144 :   if (xml==null) {getStr.recent = tmpStr; return;}
145 :   // Blogタイトルを取得する
146 :   blogTitle = $(xml).find("title").eq(0).text();
147 :   // 最新エントリイ情報を巡回取得
148 :   $.tr.ajax.recent["start"]=now();
149 :   $.each(target,function(key){
150 :    $.each($(xml).find("item"), function(i,n){
        // 取得結果を ret 配列の i 番目に代入
151 :     ret[i]= [$(n).children().eq(0), $(n).children().eq(1), $(n).children().eq(4),$(n).children().eq(5)];
        // ret配列内のテキスト文字列を抽出して target 配列に代入する。
152 :     target[key].push( ret[i][iter].text() );
153 :    });
       // 次のエントリイ情報を取得するために(46行で初期値ゼロを定義済み)
154 :    iter++;
155 :   });
156 :   try {
       // エントリイ番号、エントリイタイトル、投稿年月日を取得する。
157 :    for (var i=0 ; (i < limit) && target.link[i] ; i++) {
158 :     No = /entry-([0-9]+)/.exec(target.link[i])[1];
159 :     i==0 && (lastNo = Number(No)); // 最新エントリイ番号を取得
160 :     subject =" , " +target.subject[i];
161 :     date =" , " +target.date[i].substring(0,10); // 年月日のみを抽出
        // limit 個の取得結果を表示用に整序して配列 html.recent に代入する。
162 :     html.recent.push( "<li><a href='" + target.link[i] + "' target='_blank'>" + target.title[i] + "</a> (No." + No + subject + date + ")</li>" );
163 :    }
164 :    $.tr.ajax.recent["end"]=now(); // 時刻記録
       // 格納済み配列を HTML 文字列に併合して最終表示用に整序する。
165 :    getStr.recent = "<div><strong>Recent " + Math.min(limit,i) + " Entries</strong></div><ul style='margin-left:1.5em;list-style-type:disc'>" + html.recent.join('') + "</ul>";
       // 最終表示用に整序した HTML 文字列を表示用タグに挿入する。
166 :    r_c.html(getStr.recent);
167 :   } catch (err) { // 何らかのエラーが発生した場合にはその旨を表示する。
168 :    r_c.html(tmpStr);
169 :   }
170 :  } // End of success()メソッ
171 : }); // End of ajax()メソッド
172 :}; //End of makeRecentEntryTitle func
173 :
174 :// 前後のタイトルを取得するための準備を行う
175 :var makeEntryList = function(b_a,limit){
176 : var thisHTTP, getEntryNos=[], thisURL=[]; // ローカル変数定義
    // エントリイアドレス文字列を分解するための正規表現文字列定義
177 : regExpr = /(http:.+entry-)([0-9]+)/;
    // 今開いているエントリイのエントリイ番号を取得する。
178 : thisEntryNo = Number(regExpr.exec(location.href)[2]);
    // 今開いているエントリイアドレスのエントリイ番号前までの文字列を取得する。
179 : thisHTTP = regExpr.exec(location.href)[1];
    // 以前エントリイについてアドレス名にエラーが出ないように
    // この段階では最新エントリイタイトル名取得関数内で設定した。
    // 最新エントリイ番号値は上で取得済みなので、これを活用して
    // 以後番号も存在しない番号を取得しないようにする。
180 : border[b_a] = Math.min(limit+1, b_a == "before" ? thisEntryNo : Number(lastNo)-thisEntryNo+1);
181 : if (border[b_a]==1) thisURL.length=0; // 求める以前エントリイがない場合の処理
182 : else {
     // 求める以前または以後のエントリイが存在すれば
183 :  for (var i=1; i < border[b_a]; i++)
      // そのアドレス文字列を作成し配列に格納する。
184 :   thisURL.push(thisHTTP + (thisEntryNo - (b_a == "before" ? i : -i)) +".html" );
185 : }
186 : realElm[b_a] = 0; // 初期化
187 : // 準備完了! Ajax 通信開始
188 : getTitlesByAjax.call(this, b_a,thisURL);
189 :};
190 :
191 :// Ajax 通信によりエントリイタイトル等を取得する関数の定義
   // b_a は以前のエントリイか、以後のエントリイかを示す文字列
192 :var getTitlesByAjax = function (b_a,thisURL){
193 : if ( thisURL.length != 0 ) {
     // エントリイアドレス毎に巡回処理を行う。
194 :  $.each(thisURL,function(i,aryitem){
195 :   $.tr.ajax[b_a][i]=[];
196 :   $.tr.ajax[b_a][i]["start"]=now();
197 :   $.get(aryitem,function(data){ //data は thisURL[i] の html テキスト文
       // エントリイタイトル部分を抽出するための正規表現文字列を定義する。
198 :    regExpr = /<title>(.*)<\/title>/;
       // ブログタイトル文字列があればそれをエントリイタイトル文字列から削除する。
199 :    var titleStr = blogTitle && regExpr.exec(data)[1].replace(blogTitle,"") || "" ;
200 :    if ( /\S+/.test(titleStr)){ //空白だけのタイトル名は補足しない。
201 :     ++realElm[b_a]; // 取得したタイトル数をカウントする。
        // 1つのエントリイのタイトル名、エントリイ番号を取得

202 :     html[b_a][i]="<li><a href='" + aryitem + "' target='_blank'>" + decodeURI(encodeURI(titleStr)) +" (Entry No." + /entry-([0-9]+)/.exec(aryitem)[1] + ")</a></li>";
203 :    }
204 :    $.tr.ajax[b_a][i]["end"]=now(); // 時間記録
       // 最後の通信処理が終わったらsetEnding()関数をタイマー起動する。
205 :    if (b_a == "after" && aryitem == thisURL[thisURL.length-1]) 
206 :     itval=setInterval(setEnding,20);
207 :   });
208 :  });
209 : } else {if (b_a == "after") itval=setInterval(setEnding,20)}
210 :};
211 :
   // 終了処理関数定義
212 :var setEnding = function (){
213 : $.tr.setEndingCnt++; // 回数記録
214 : if (jQuery.active==0){ // Ajax通信結果が取得出来たならば
215 :   if (itval) {clearInterval(itval);itval=null;} //タイマー変数停止無効化
     // 以前・以後別に処理
216 :   $.each(["before","after"],function(i,b_a){
      // 取得結果がない場合
217 :  if (realElm[b_a]==0)
218 :   getStr[b_a]="<div>"+ (b_a=='before' ? 'Before ' : 'After ') + "Entry "+ decodeURI(encodeURI('はありません。')) + "</div>";
219 :  else {
      // 欠番があった場合の説明文を complement 変数に代入
220 :   complement = (border[b_a]-1 -realElm[b_a]!=0) ? 
221 :    " ( " +decodeURI(encodeURI("欠番があります。")) +" )" : "";
      // 取得結果を HTML 文字列にして変数に代入
222 :   getStr[b_a] = "<div><strong>"+ (b_a=='before' ? 'Before ' : 'After ') + realElm[b_a] + " Entries" + complement +"</strong></div><ul>" + html[b_a].join('') + "</ul>";
223 :  }
     // HTML 文字列化された取得結果文字列を所定のタグに挿入する。
224 :  $("#"+constStr+"result"+b_a).html(getStr[b_a]);
225 :  if (b_a=="after") {
      // Now loading...文字を隠蔽
226 :   ld.hide();
      // 結果表示ボタンの無効化と半透明化を解除
227 :   $(".getEntryTitles_btn").attr("disabled","").animate({opacity:1.0});
      // 以前タイトルの所要時間を設定(ゼロの時にも対応)
228 :   var beforeTime=$.tr.ajax.before.length ? "<li>以前タイトル取得 Ajax 通信所要時間: "+ ($.tr.ajax.before[realElm.before-1].end-$.tr.ajax.before[0].start)/1000 +" 秒</li>" : "";
      // 以後タイトルの所要時間を設定(ゼロの時にも対応)
229 :   var afterTime=$.tr.ajax.after.length ? "<li>以後タイトル取得 Ajax 通信所要時間: "+ ($.tr.ajax.after[realElm.after-1].end-$.tr.ajax.after[0].start)/1000 +" 秒</li>" : "";
      // 所要時間を表示するためのHTML文の作成
230 :   var AjaxLog ="<ul style='margin-bottom:5px'>"+
231 :    "<li>クリック後 Ajax 通信開始迄の所要時間: "+($.tr.ajax.recent.start-$.tr.start)/1000 +" 秒</li>"+
232 :    "<li>最新タイトル取得 Ajax 通信所要時間: "+ ($.tr.ajax.recent.end-$.tr.ajax.recent.start)/1000 +" 秒</li>"+ beforeTime + afterTime +
233 :    "<li>このプロジェクト全体の所要時間: "+ (($.tr.end=now())-$.tr.start)/1000 +" 秒</li></ul>";
      // ログ閲覧回数の記録
234 :   cmt++;
      // 一度目の所要時間表示文字列
235 :   var cmtbtn1="<button id='cmtbtn1' onclick='this.blur();window.open(\"http://hkom.blog1.fc2.com/blog-entry-631.html\",target=\"_blank\")'>この Ajax 通信や所要時間について</button>";
      // 二度目以降の所要時間表示文字列
236 :   var cmtbtn2="<div id='cmtbtn2'>" +(cmt-1)+" 回目の Reload 結果</div>";
237 :   lg.append(AjaxLog+(cmt==1 ? cmtbtn1:cmtbtn2)); // 経過時間ログの挿入
      // 結果表示エレメントの表示
238 :   pD.css({width:"640px",height:"auto"}).show();
      // 通信終了を知らせる文字列の表示(アニメーション)
239 :   fn.show().