06 | 2008/07 |  08

  1. 無料サーバー

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

anything from here

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


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 を一括登録するブックマークレット: )でまとめました。

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 通信コードを全面的に改訂しました

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

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 (timer) {clearTimeout(timer);timer=null;}
  if (jQuery.active==0) {
   ここに全ての通信結果を表示するためのコードを記述する。
  }
  else var timer=setTimeout(display,50);
 }
 display();
しかし、jQuery.active 活用だけではまだ不十分だった

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

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

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

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

───などでした。

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

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

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

詳細はこちらの該当エントリイ( No631:ファイル置き場と jQuery Ajax Utilities を活用して、任意のFc2ブログからタイトル情報を取得する )に記述しました。

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 関連コードの解読に踏み込みたいと考えている今日この頃です。

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
  • コードの抜本改訂とファイル置き場利用版up:2008/7/9
  • (再改訂)Ajax通信関連部分を更に抜本改正:2008/7/12
  • (再々改訂)Ajax 通信関連部分でflagを追加して確実性を向上:2008/7/15

他ブログ上での Ajax 通信をついに実現

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

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

もう少し具体的に述べると、次のことを実現しました。

  1. 4 つの js ファイル(今回は次の4ファイル:1. jQuery.js、2. firebug.js、3. Ajax 通信を履行する自作の js ファイル、4. Ajax 通信結果を表示するための css ファイル)を一括してインクルードするための js ファイル( setjQnFbug_getFc2EntTts.js )を作成し、この js ファイルの実行によって 4 つのファイルの全てまたは一部をインクルードする。
  2. Ajax 通信はもちろんのこと随所に jQuery.js を多用してコードを実行するため、jQuery.js が組み込まれていないブログの場合も想定し、なければそれをインクルードするようにした。
  3. setjQnFbug_getFc2EntTts.js をインクルードするためのブックマークレット(BMsetScriptTag.html)を作成する。
  4. BMsetScriptTag.html をブックマークに登録し、閲覧したい Fc2 ブログを開いてこのブックマークを実行する。

以上により、Fc2のブログであれば何であれ、jQuery を活用して Ajax 通信を行い、エントリイタイトル情報を取得することが出来るようにしました。

▲ToTop

ファイル置き場は Google Page を活用

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

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

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

───と、いくら批判し、嘆いていても仕方ないので、調べた中で、無料で容易にファイル置き場として利用できる Google Page ウェブサイトを活用していきたいと思います。

Google page 上にマイページを立ち上げ、そこに関連ファイルを置いて自作ブックマークレットを作動させその成功を確認し、この頁の少し下にその成功したブックマークレットを置きました。

何をしたのか?───今回のプロジェクト「他ブログエントリイタイトル取得」について

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

あるFc2ブログサイトの或るエントリイ頁を開いた状態で、ブックマークを起動すれば、以前、最新及び以後の各10個のエントリイに係る諸情報(具体的にはタイトル、Entry番号、投稿日など)を表示すると共に、jQuery と firebugLite を使用することが出来ます。

ファイル構成

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

  1. ブックマークレット……次の setjQnFbug_getFc2EntTts.js を登録するため
  2. スクリプト登録用JSファイル( setjQnFbug_getFc2EntTts.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通信結果を固有に用意した絶対配置要素内で表示させるために、各ブログに依存しない固有のスタイルシートを用意)

これらのファイルの内、今回独自に作成した3つのファイル( setjQnFbug_getFc2EntTts.js、getFc2EntryTitles.js 、getFc2EntryTitles.css )と firebug.js を GooglePage サイトに upload した上で、setjQnFbug_getFc2EntTts.js 内から、jQuery.js を含む他の 4 つのファイルにリンクを貼ってインクルードするようにしました。なお、jQuery1.2.6pack.js は、既定のファイル置き場(これは Google Code 上にあります)にあるファイルを利用するよう、setjQnFbug_getFc2EntTts.js 内で記述しました。

▲ToTop

利用

ブックマークレット

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

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

Ajax 通信をやり直すボタン( ReLoad Data ボタン )も設置しましたし、結果を表示する小窓が邪魔になったら、隠蔽することも出来るようにしました。更に、小窓を隠蔽した場合には、ブックマークレットを再起動すれば、隠蔽直前の状態で小窓が復帰するようにしました。Ajax 通信結果は閲覧中の頁がリロードされない限りメモリ上に残る仕様としたのです。

次のリンクをお気に入りに登録しておけば、任意の Fc2 ブログサイトで共通して使えます。また、単にクリックするだけでも、今ご覧戴いているこのエントリイを対象として利用できます。

全ての起点となるブックマークレット :
Ajax 通信結果の表示

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

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

上の図は既に Ajax 通信が終わった状態の画像ですが、5つのボタンは左から順に「今見ているエントリイの前の10個のエントリイタイトル表示、最新の10エントリイ表示、今見ているエントリイの後に投稿された10エントリイのタイトル表示、Ajax通信再実施、小窓の隠蔽」を行うためのものです。

例えば「 Before 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ファイル説明

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_getFc2EntTts.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. jsファイルの一括インクルードを行う

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

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

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

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

// このスクリプトがインクルード済みの場合に関数が起動できるよう
// 名前付き関数とし、最後の行でこの関数を起動する。
var chkScript = function(){
  var x=0,y=0,z=0,w=0,i=0,
    h=document.getElementsByTagName('head')[0],
    t=document.getElementsByTagName('script'),
    l=document.getElementsByTagName('link'),
    s=document.createElement('script');
  s.type='text/javascript';
  // jquery、firebug 及び getFc2EntryTitles の文字を含むスクリプトタグを走査し、
  // 存在していればそのことを記録する。
  if(t) for(;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)) {
      z+=1;
      // ブックマークレットが複数回起動された場合の処理
      // インクルード済みで結果表示小窓が非表示ならば表示する
      var tmp = document.getElementById("ajaxPopup");
      if (tmp && tmp.style.display == "none") tmp.style.display="block";
      // 結果表示小窓が表示済みならば、何もしないでこのjsファイルのコード進行を終える
      if (tmp && tmp.style.display == "block") return;
    }
  }
  // 所定のスタイルシートがインクルード済みかどうか link タグ走査し、あれば記録。
  if(l) for(i=0 ;i<l.length; i++)  {if(/getFc2EntryTitles/.test(l[i].href)) w+=1;}

  // jQuery.js のインクルード
  // jQuery.js は単に firebug Lite から利用するだけではなく、Ajax通信やその取得結果を表示するコードで
  // 多用するためにインクルードします。
  // なお、軽量化のためにpack版を利用するようにしました。
  if (x==0){
    s.src='http://jqueryjs.googlecode.com/files/jquery-1.2.6.pack.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)
  }
  // getFc2EntryTitles.js のインクルード
  if (z==0){
    var r=document.createElement('script');
    r.type=s.type;
    r.src='http://hkom007.googlepages.com/getFc2EntryTitles.js';
    h.appendChild(r);
  }
  // CSSファイルのインクルード
  if (w==0){
    var k = document.createElement('link');
    k.rel = "stylesheet";
    k.type = "text/css";
    k.media = "screen, print";
    k.href='http://hkom007.googlepages.com/getFc2EntryTitles.css';
    h.appendChild(k);
  }
  // 無名関数としなかったのは再呼び出しがあり得るからです。
};chkScript(); //関数実行

▲ToTop

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

取得結果を絶対配置要素内に表示させるために、CSS ファイルを作成しました。

これによりどんな Fc2 ブログであっても同様な結果表示を行うことにしました。

@charset "euc-jp";
#ajaxPopup{
	position:absolute; z-index:100000; top:150px;left:50%;
	width:600px; margin-left:-300px;
	font-size:small; padding:0.5em;
	background-color:#def;
	text-align:left; border:2px #777 solid; color:black;
	display:block;
}
#pasteData {clear:both; color:black;}
#pasteData a:link{color:blue; text-decoration: none;}
#pasteData a:visited { color: purple; text-decoration: none;}
#pasteData a:hover {
	color:black;
	background:#dd0; 
	text-decoration: none; 
}
#pasteData a:active { color: darkgreen; text-decoration: none;}

.btn {
	width:120px;
	float:left;
	margin:2px;
	padding:2px;
	border:1px black solid;
	font-weight:bold;
	color:white;
	background-color:#89A;
	text-align:center;
}
#menuBlock {float:left;}
#closeThis {
	float:right;
	width:20px;
	margin:2px;
	padding:2px;
	border:1px black solid;
	font-weight:bold;
	color:white;
	background-color:#89A;
	text-align:center;
}

▲ToTop

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

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

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

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

  1: /* getFc2EntryTItles-gp.js
  2:  * 2008/7/15 Release
  3:  * Ajax通信結果要素内配置版
  4:  */
  5: 
  6: // fc2ブログでかつ個別Entry表示モードの場合にのみコードを進行する。
  7: if (location.href.indexOf("fc2")!=-1 && location.href.indexOf("blog-entry-")!=-1){
   // 実行コード全体を無名関数で包含する
  8: (function($){
  9:  var aP,ld,fn,r_c,r_b,r_a;
 10:  var html = { before:[], after:[], recent:[] },getStr ={ before:"", after:"", recent:"" }, 
    blogTitle =null, regExpr = "",itval,border={ before:0, after:0},
    realElm={before:0,after:0},thisEntryNo=Number(1), lastNo;
 11: 
 12:  // 取得結果表示用のタグを作り表示する。
 13:  if ( !aP ) { // 存在しなければ
 14:   $(document.body).append( // 以下のタグを document.body 内に追加する
 15:    '<div id="ajaxPopup">'+
 16:     '<div id="menuBlock">'+
 17:      '<div id="before" class="btn">Before Entries</div>'+
 18:      '<div id="recent" class="btn">Recent Entries</div>'+
 19:      '<div id="after" class="btn">After Entries</div>'+
 20:      '<div id="reload" class="btn">ReLoad Data</div>'+
 21:     '</div>'+
 22:     '<div id="closeThis">'+decodeURI("%C3%97")+'</div>'+
       // 通信中、通信終了、以前/最新/以後エントリイタイトル名表示などの各種情報表示用タグ
 23:     '<div id="pasteData">'+
        // 通信中であることを表示するタグ
 24:      '<div id="loading"><img src="http://blog1.fc2.com/h/hkom/file/loading_16.gif" width="16" height="16" border="0" alt="" /> Now Loading...</div>'+
        // 連続する Ajax 通信の全てが終わったことを表示するタグ
 25:      '<div id="finish"><strong>Finish Ajax Communication !</strong></div>'+
        // 以前エントリイタイトル名等を表示するタグ
 26:      '<div id="resultbefore"></div>'+
        // 最新エントリイタイトル名等を表示するタグ
 27:      '<div id="resultrecent"></div>'+
        // 以後エントリイタイトル名等を表示するタグ
 28:      '<div id="resultafter"></div>'+
 29:     '</div>'+
 30:    '</div>'
 31:   );
 32:   // 表示/非表示を操作するために必要な要素をショートカット変数に代入する。
 33:   aP=$("#ajaxPopup"); ld = $("#loading"); fn = $("#finish");
 34:   r_c = $("#resultrecent");r_b = $("#resultbefore"); r_a = $("#resultafter");
 35:  } else {
     // 結果取得済みの時にはそれを表示するだけでコード進行を終える。
     // これはブックマークレットが再度クリックされた場合への対応策
 36:   aP.show();
 37:   return;
 38:  }
 39: 
 40: // 最近のタイトルを取得する関数を定義
 41: var makeRecentEntryList = function (limit){
	  // getStr.recent が存在し、かつ空でない場合
 42:  if (!!getStr.recent && getStr.recent!="") {
     // それを表示してこの関数を終える
 43:   $("#pasteData").html(getStr.recent).show();
 44:   return;
 45:  }
 46:  var No, subject, date, iter=0, ret=[],
 47:   target ={  //xml ファイル内での順番
 48:      link:[],     //0
 49:    title:[],     //1
 50:  // description:[],  //2  :今回は使用しない。
 51:  // content:[],    //3  :今回は使用しない。
 52:     subject:[],    //4
 53:    date:[]      //5
 54:   };
 55: 
 56:  // エントリイタイトルを取得する
    // limit 個数のエントリイタイトル情報を Ajax 通信によって取得する。
    // 閲覧中のFc2ブログの xml ファイルのアドレスを設定する。
 57:  $.ajax({
 58:   url: /http:.+fc2\.com\//.exec(location.href)[0] + "?xml" || null,
 59:   type: "GET",
 60:   dataType: "xml",
     // xmlファイルが成功裏にダウンロード出来た場合の処理関数
 61:   success: function(xml){
      // 「ありません。」の encodeUTI 文字列
 62:    var tmpStr = '<div>'+decodeURI("%E6%9C%80%E6%96%B0%E3%81%AE%E3%82%A8%E3%83%B3%E3%83%88%E3%83%AA%E3%82%A4%E6%83%85%E5%A0%B1%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93")+'</div>';
      // xmlファイルが取得できない場合には「ありません。」を取得結果変数に代入
 63:    if (xml==undefined || xml==null) {getStr.recent = tmpStr; return;}
 64:    // Blogタイトルを取得する
 65:    blogTitle = $(xml).find("title").eq(0).text();
 66:    // 最新エントリイ情報を巡回取得
 67:    $.each(target,function(key){
 68:     $.each($(xml).find("item"), function(i,n){
        // 取得結果を ret 配列の i 番目に代入
 69:      ret[i]= [$(n).children().eq(0), $(n).children().eq(1), $(n).children().eq(4),$(n).children().eq(5)];
        // ret配列内のテキスト文字列を抽出して target 配列に代入する。
 70:      target[key].push( ret[i][iter].text() );
 71:     });
       // 次のエントリイ情報を取得するために(46行で初期値ゼロを定義済み)
 72:     iter++;
 73:    });
 74:    try {
       // エントリイ番号、エントリイタイトル、投稿年月日を取得する。
 75:     for (var i=0 ; (i < limit) && target.link[i] ; i++) {
 76:      No = /entry-([0-9]+)/.exec(target.link[i])[1];
 77:      i==0 && (lastNo = Number(No)); // 最新エントリイ番号を取得
 78:      subject =" , " +target.subject[i];
 79:      date =" , " +target.date[i].substring(0,10); // 年月日のみを抽出
        // limit 個の取得結果を表示用に整序して配列 html.recent に代入する。
 80:      html.recent.push( "<li><a href='" + target.link[i] + "' target='_blank'>" + target.title[i] + "</a> (No." + No + subject + date + ")</li>" );
 81:     }
       // 上行で格納した配列を HTML 文字列に併合して最終表示用に整序する。
 82:     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 文字列を表示用タグに挿入する。
 83:     r_c.html(getStr.recent);
 84:    } catch (err) { // 何らかのエラーが発生した場合にはその旨を表示する。
 85:     r_c.html(tmpStr);
 86:    }
 87:   } // End of success()メソッ
 88:  }); // End of ajax()メソッド
 89: }; //End of makeRecentEntryTitle func
 90: 
 91: // 前後のタイトルを取得するための準備を行う
 92: var makeEntryList = function(b_a,limit){
    // 表示用のデータ配列があり、それが空でなければ
 93:  if (!!getStr[b_a] && getStr[b_a]!="") {
     // 結果を表示してこの関数の実行を終える。
 94:   $("#pasteData").html(getStr[b_a]).show();
 95:   return;
 96:  }
    // ローカル変数定義
 97:  var thisHTTP, getEntryNos=[], thisURL=[];
    // エントリイアドレス文字列を分解するための正規表現文字列定義
 98:  var regExpr = /(http:.+entry-)([0-9]+)/;
    // 今開いているエントリイのエントリイ番号を取得する。
 99:  thisEntryNo = Number(regExpr.exec(location.href)[2]);
    // 今開いているエントリイアドレスのエントリイ番号前までの文字列を取得する。
100:  thisHTTP = regExpr.exec(location.href)[1];
    // 以前エントリイについてアドレス名にエラーが出ないように
    // この段階では最新エントリイタイトル名取得関数内で設定した最新エントリイ番号値
    // はまだ取得できない。(最新エントリイ情報を取得する Ajax 通信が完了していないため)
101:  border[b_a] = Math.min(limit+1, b_a == "before" ? thisEntryNo : limit+1);
102:  if (border[b_a]==1) thisURL=[]; // 求める以前エントリイがない場合の処理
103:  else {
     // 求める以前または以後のエントリイが存在すれば
104:   for (var i=1; i < border[b_a]; i++)
      そのアドレス文字列を作成し配列に格納する。
105:    thisURL.push(thisHTTP + (thisEntryNo - (b_a == "before" ? i : -i)) +".html" );
106:  }
107:  realElm[b_a] = 0; // 初期化
108:  // 準備完了! Ajax 通信開始
109:  getTitlesByAjax.call(this, b_a,thisURL);
110: };
111: 
112: // Ajax 通信によりエントリイタイトル等を取得する関数の定義
   // b_a は以前のエントリイか、以後のエントリイかを示す文字列
113: var getTitlesByAjax = function (b_a,thisURL){
   // ローカル変数定義
114:  var result={before:[],after:[]}, complement, realSize;
    // エントリイタイトル部分を抽出するための正規表現文字列を定義する。
115:  regExpr = /<title>(.*)<\/title>/;
     // エントリイアドレス毎に巡回処理を行う。
116:  $.each(thisURL,function(i,aryitem){
117:   $.get(aryitem,function(data){ //data は thisURL[i] の html テキスト文
      // ブログタイトル文字列があればそれをエントリイタイトル文字列から削除する。
118:    var titleStr = blogTitle != null ? regExpr.exec(data)[1].replace(blogTitle,"") :"" ;
119:    if ( /\S+/.test(titleStr)){ //空白だけのタイトル名は補足しない。
120:     ++realElm[b_a]; // 取得したタイトル数をカウントする。
       // 1つのエントリイのタイトル名、エントリイ番号を取得
121:     html[b_a][i]="<li><a href='" + aryitem + "' target='_blank'>" + titleStr +" (Entry No." + /entry-([0-9]+)/.exec(aryitem)[1] + ")</a></li>";
       // 実証的にこの段階ならば先行するAjax通信が完了していて、 lastNo 値を取得でき
       // ることが分かったので、ここで limit 値よりも 
       // (現在の最終エントリイ番号 - 現在開いているエントリイ番号の値)
       // が小さければ、border[b_a] 値をその値+1の値に変更する。
       // これにより thisURL[i]の番号値が、欠番なのか、存在しない番号なのかを判別する
       // ことが可能となる。
122:     b_a=="after" && (border[b_a]=Math.min(border[b_a],Number(lastNo)-thisEntryNo+1));
       // 欠番があればその旨を表示する文字列を complement 変数に代入する。
123:     complement = (border[b_a]-1 -realElm[b_a]!=0) ? 
124:     " ( " +decodeURI("%E6%AC%A0%E7%95%AA%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82") +" )" : "";
       // result[b_a] 配列の各要素にタイトルが取得できたかどうかを記録する。
       // 取得できたらば true、出来なければ null が要素の代入される。
125:     result[b_a][i]=true;
126:    }
      // each 巡回が最後の thisURL になった場合には、
127:    if (aryitem == thisURL[thisURL.length-1]) {
       // 一つもタイトル名が取得できなかった場合
128:     if (realElm[b_a]==0){
        // 存在しなかった旨の文字列を getStr オブジェクトの b_a プロパティに代入する。
129:      getStr[b_a]="<div>"+ (b_a=='before' ? 'Before ' : 'After ') + "Entry "+ decodeURI('%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82') + "</div>";
130:      display(); // 表示タグ内に最終結果を挿入する関数を起動する。
131:     } else docking(); // 以前又は以後のエントリイタイトル名を表示用に整序する関数を起動する。
132:    }
133:   });
     // タイトル名を表示用に結合する関数の定義
134:   function docking(){
      // timer タイマーの停止
135:    if (timer) {clearTimeout(timer);timer=null;}
      // 取得できたタイトル数を変数に代入
136:    realSize = realElm[b_a];
      // 巡回処理
137:    for (var i=0; i < border[b_a];i++){
       // 結果が取得できていて、その結果が実際に存在しすれば、変数値を 1 減する。
138:     result[b_a][i] && html[b_a][i] && realSize--;
139:    }
      // 巡回処理が終わった時点で変数値 realSize がゼロであれば、
      // すなわち Ajax 通信が以前又は以後エントリイの全ての結果を取得できたこと
      // が確認できたので、
140:    if (realSize==0) {
       // 取得結果を表示用に結合し、HTML文化する。
141:     getStr[b_a] = "<div><strong>"+ (b_a=='before' ? 'Before ' : 'After ') + realElm[b_a] + " Entries" + complement +"</strong></div><ul style='margin-left:1.5em;list-style-type:disc'>" + html[b_a].join('') + "</ul>";
142:     display(); //それを表示用に挿入する関数を起動する。
143:    }
      // realSize != 0 ならばまだ取得できていない通信があるから
      // 15ミリ秒後に docking 関数を再起動する。こうすることによって、全ての結果が
      // 取得できるまで巡回処理を行い続け、これが終わるまではdisplay関数は起動されない。
144:    else var timer=setTimeout(function(){docking()},15);
145:   }
146:   var display = function(){ // 挿入関数定義
      // 表示用にHTML文に加工済みのタイトル名情報を、表示用タグに挿入する。
147:    $("#result"+b_a).html(getStr[b_a]);
      // 以後タイトルを扱っていれば、setEnding関数を起動する。
148:    b_a == "after" && setEnding();
149:   } // End of $.get()メソッド
150:  }); // End of each function
151: } // End of function
152: 
   // 全ての Ajax 通信が終わったことを画面に表示するための関数定義
153: var setEnding = function (){
    // itval タイマーの停止
154:  if (itval) {clearTimeout(itval);itval=null;}
    // 念のために jQuery.active==0 となっているかどうか判別し、
155:  if (jQuery.active==0){ //ゼロならば
     // 通信中表示を隠蔽し、全てのAjax 通信が終わったことを fadeIn/Out メソッドを
     // 活用して「注目させながら」表示する。
156:   ld.hide(); fn.fadeIn("slow").fadeOut("slow").css({color:"darkgreen",background:"pink"}).fadeIn("slow");
    // (jQuery.active != 0) ならば20ミリ秒後にこの関数を再起動させる。
157:  } else itval=setTimeout(function(){setEnding()},20);
158: } // 以前/以後のエントリイ情報取得完了
159: 
   // 一連の Ajax 通信実行関数を呼び出すための関数の定義
160: var makeLists = function(num){
    // 必要なタグを表示し、不要なタグを隠蔽する。
    // $(・・・).each(・・・) メソッドを活用してした。
161:  $([ld,fn,r_c,r_b,r_a]).each(function(i,n){i==0 ? n.show() : n.hide();});
    // 最新情報を取得するための行
162:  getStr.recent=""; html.recent.length=0; makeRecentEntryList.call(this,num);
    // 以前情報を取得するための行
163:  getStr.before=""; html.before.length=0; makeEntryList.call(this,"before",num);
    // 以後情報を取得するための行
164:  getStr.after=""; html.after.length=0; makeEntryList.call(this,"after",num);
165: }
    // 一連の連続した Ajax 通信を実行する関数を起動する。
166:  makeLists(10);
167: 
168: //--------------------------------------------
    // 固定配置的に配置するためのスクロールイベントハンドラー
169:  $(window).scroll(function(){
170:   $("#ajaxPopup").css({
171:    top:10 +( window.pageYOffset || Math.max(document.body.scrollTop, document.documentElement.scrollTop) )+"px",
172:    marginLeft:-300+ ( window.pageXOffset || Math.max(document.body.scrollLeft, document.documentElement.scrollLeft) )+"px"
173:   });
174:  });
175: 
    // 最新/過去/未来エントリ情報を表示させるクリックイベントハンドラー
    // ここでもeach()メソッドを効果的に活用した
176:  $.each([$("#recent"),$("#before"),$("#after")],function(j){
177:   $(this).click(function(){
178:    $([fn,r_c,r_b,r_a]).each(function(i){
179:     i==j+1 ? $(this).show() : $(this).hide();
180:    });
181:   });
182:  });
183: 
184:  $("#closeThis").click(function(){ // 結果表示用の小窓全体を隠蔽するために
185:   $("#ajaxPopup").hide();
186:  });
187: 
188:  $("#reload").click(function(){
189:   makeLists(10);
190:  });
191: 
192:  $(".btn, #closeThis").hover( // ボタンにマウスオーバー/アウトした際のイベントハンドラー
193:   function(){
194:    $(this).css({color:"black",backgroundColor:"#dd0"});
195:   },
196:   function(){
197:    $(this).css({color:"white",backgroundColor:"#89A"});
198:   }
199:  );
200: })(jQuery);
201: } // 1 行目の if を閉じる

ファイル置き場問題(2) 結局有料サイトしかないのか?! 否!Google Codeが!

概ね5時間掛けて色々調べた結果...!!

リンクが貼れるファイルを無料ホスティングサービスでゲットすることは、かなり困難であることが判明しました。

そこで最後のチャレンジで Google Code に登録してみました。すると何と!upload 出来て、かつリンクを貼ってダウンロード出来るではありませんか!

早速、その例を下に掲載してみます。

firebug.js

firebugx.js

既存のファイルなので Google Code Website の主旨に反するでしょうが、テストということで許して貰うとして(苦笑)、上のリンクをクリックすると直ぐにダウンロードを開始するダイアログが表示されます。まさにこれこそ願っていた環境なので、ついに目的を達することが出来ました。

これにより、各種のブックマークレットによって各種のサイト上でスクリプトをインクルードし、Ajax 通信などによる情報取得/表示を実現する道が開けました。

例えば、先のエントリイで掲載したブックマークレット( jQuery と firebugLite を一括してインクルードするもの)において、その中の firebug.js ファイルのリンク先を webos-goodies から、Google Code に変えたものを以下に掲載しました。

これで (1) jQuery1.2.3.jsと (2) firebug.js のインクルードが実現すれば、万々歳です。

そしてそれは実現できました!!

下のリンクをお気に入りに登録すれば、 jQuery と firebugLite を一括してインクルードするブックマークレットとして使えます。
No1簡易版 jQuerify + FirebugLite

▲ToTop

それでも有料サイトを使うべきかも知れない

Google Code サイトは他者に貢献できるようなファイルを置く場所だと思われますので、私のような使い方、あるいは私のようなレベルの素人が使うのは、いかにも僭越な気がします。

よってGoogle Code には遠慮して、有料サイトを使うべきかも知れません。

しかし、暫くの間は自作の ブックマークレットを含む Javascript コード等を Google Code に upload し、このブログ上からダウンロードやインクルード出来るようにしてみようか、と思っています。

JustSystem や Sony が提供するホスティングサービスを利用することは、いつでも可能なことですし、Google Codeでは写真や動画あるいは通常の文書ファイルは保存できません。毎月 300 円程度で確実にファイル置き場として利用できるのであれば、決して高くはありませんから、追って有料サービス利用に踏み切ろうかと、思案中です。

ps:昨日確認したところ、二社とも無料期間を設けて自社サービスへの誘導を行っていました。

ファイル置き場問題に明るい展望が開けた!、かと思いきや・・・駄目だった。

駄目元でも良いから...とグーグったら!

検索用語はずばり「無料 ファイル置き場」。するといくつかの候補がリストアップされるではありませんか!

iDrive───これは英語圏のもので無料ではあるものの、利用規約などとても読む気にはならないので、最後の手段かな、と概観してみました。使えそうではありました。( Free Online Backup - IDrive - Encrypted, Secure and Automated! )一度は無料サービス提供をやめたはず(2001年)ですが、その後また再開したものと思われます。何と 2GB の容量が無料で使えるようです。

但し、バックアップ用途としてのディスク容量の提供に限定されているのかも知れませんが、詳細は調べ切れていません。

なお、有料の eXys iDrive(WebDAV対応 大容量 オンラインストレージ - eXys iDrive - 簡単・安全にファイルを保存・共有できます) とは全く別物です。

次に、Google の無料サービスでも使えそうなものがあるようです。プロジェクト ホスティング「独自のオープンソース プロジェクト用に コードとドキュメントのホスティング サービスを無料で提供。」とありますが、jQuery.js ファイルも Google サイトに置いてあったことを思い出しました。( 開発者ホーム - Google Code

しかしこちらは色々とハードルが高そうな気がします。

更に、オンラインストレージに関して、概括的・具体的・網羅的な情報を提供してくれるこんなサイト( オンラインストレージを使ってみよう )もありました。

そしてたどり着いたのは infoseek です。今や楽天傘下に組み込まれているとは知りませんでしたが、こちらの無料ホームページサービスはファイル置き場を認めているらしいのです。

日本語でファイル置き場と言う用語に引っかかるサイトの多くは infoseek の登録 Homepage であることからも象徴されるように、infoseek の Homepage サービスをファイル置き場として活用している方が沢山いるらしいことも判明しました。

▲ToTop

というわけで早速 infoseek に Homepage 開設しようとして...But!

ユーザー登録を終えると「iswebライト新規登録時のご確認」画面が表示されますが、そこには「他サイトからのCGI及びデータの参照を禁止します。 」と書かれているではありませんか!

つまりファイル置き場には出来ない、と言う結論になります。

しかし一方ではいくつかのブログサイトで、ファイル置き場として使っていることを公言しているエントリイもあったりしますので、もしかしたら最近になって「置き場禁止」へと方針を転換したのかも知れません。うむ...。出鼻を挫かれてしまいました!

▲ToTop

そこで更にネット検索を重ねたところ...!!

あった。ありました!

メールアドレスとパスワードを登録するだけで容量制限なしで使えるという、超簡単ストレージが!
「 何の予告もなくファイルを全削除されました(08.1/1)。そして消えていたファイルが全て元通りになってました。何だったんだ?!(08.1/4) 」との記述が象徴しているように( 8倍速対応 | 無料無制限のオンラインストレージ-MediaFire )、何時消えてなくなるかも知れませんが、そのことを覚悟した上で( まさしく駄目元で )利用してみようかと思います。

容量制限なし、登録は超簡単な無料オンラインストレージ

早速アップロードしてみましたが、アップロードが終わるとメルアドとパスワードを入力する画面が表示され、Image Page URL とリンク HTML 文とが直ぐにゲットできてしまいます。

使用例1:例えば写真を登録してみました

Unlimited Free Image and File Hosting at MediaFire
(例)Media Fireに保存した写真

使用例2:jsファイル

firebug.js

しかし...

写真などをダウンロードするのは良いでしょうが、インクルード用 js ファイル置き場としては適さないことが分かりました。

ダウンロードしようとすると MediaFire サイトが開くのです。そしてウィルスチェックが自動的に行われ、その後画面をクリックして初めてダウンロードするようになるのです。これではjsファイルのファイル置き場としては実用的ではありません。

そこでブックマークレットの一部にMediaFireからインクルードするjsファイルを組み込もうと思いましたが、ファイル名が http://www.mediafire.com/?ymw9kjb0jig のように独自ネームに変えられてしまうため、これも駄目だと分かりました。

ということで、明るい展望は開けませんでした。

苦闘5時間の末に!

それでも食い下がった結果、苦闘5時間の末についに「発見し、利用を開始」しました───外部からリンクを貼りそれを参照可能な無料サービスを。このことについては次の Entry( ファイル置き場問題(2) 結局有料サイトしかないのか?! 否!Google Codeが! )で詳述します。