search phpbb-phpbb-FC2BLOG-Info-Edit Template-Post-Edit-Upload-LogOut
それはjQuery.jsの GET メソッドを使って ResponseText と ResponseXML を取得し、このブログサイトの過去/未来/最新のエントリイタイトル名称等を取得することでした。
それらは以下のエントリイで説明したように「一応」実現しました。
そして、これらの情報取得が可能になったことによって、そもそもやりたかったことを実現する手段が獲得出来ました。すなわち、ナビゲーションバーの直前のエントリイや直後のエントリイ文字列にマウスオーバーすると、直前/最新/直後の任意の数のエントリイタイトル等の情報をポップアップ表示させることです。
そのためにこそ、任意のエントリイの直前エントリイタイトル取得を試みてきた訳ですし、両方に挟まれた「ホームへ」文字列にマウスオーバーした時にも同様にポップアップさせるべきだと考え、それは最新10エントリイタイトルにしようと思い、それを実現するための前段の措置として最新エントリイ情報の取得について模索したのでした。
さて、何はともあれ実現したこれらのポップアップ表示をまずは画像で紹介させていただきます。
これらの3つの情報を簡単に取得することは Ajax 通信を使ってこそ可能になります。直前/直後のエントリイ情報は、閲覧しているエントリイ毎に異なる訳ですから、ここにこそ Ajax 利用のメリットがあります。
まず実現した3つのポップアップ画像を示します。
直前10エントリイタイトル情報
最新10エントリイタイトル情報
直後10エントリイタイトル情報
この下の節で詳細な説明を付けた Javascript コードを掲載しましたので、以下の説明はそちらを見ていただければより分かりやすくなるかと思います。
結果を popup させるための HTML テンプレートと popup 要素のための CSS テンプレートに必要な加工行った上で Javascript コードを作成しました。そのコードそのものの説明は後述するとして、まずその概要やポイントを纏めておきます。
取得したエントリイタイトルリストを表示させる方法としてポップアップを選びました。閲覧上固定的に表示する必要はありませんし、邪魔にならずに目的とする情報を随時閲覧できる方法としてポップアップが最適です。
Ajax通信に関する記述を読むと必ず次のことが強調されています。─── Ajax 通信は背景で処理されるので、そのことを知らせないと閲覧者はパソコンが固まったのではないか、と誤解する。閲覧者を戸惑わせないためにも、Ajax通信中は今通信中であることなどを示すべきである。
しかし、その表示は恒常的に出ている必要はなく(常に見えていてはむしろ邪魔)、popupさせようとしたその時にまだ通信中であればその時に限って表示すればよい訳です。
さてここで述べているコードは頁が開かれると同時に起動して背景で動いています。そして頁オープン後数秒で結果を取得し、マウスオーバーを待つ状態になります。
ですから、敢えてAjax通信中であることを表示する必要はないと判断し何も策を講じませんでした。
正確に言えば表示するような文言を用意したのです( 20 行 )が、取得までの時間が短すぎて表示する暇がないようです。(苦笑)
IEの場合 xml 文書の名前空間処理(DOM の getElementsByTagNameNS メソッド)に対応していません。最初は xml 文書の名前空間や DOM の getElementsByTagNameNS メソッドのこと自体を知らなかったので、どうして IE では結果を取得できないのか皆目見当が付きませんでした。
仕方なく、使いにくいデバックツールしかないので面倒だったのですが、IE上で自作コードをデバッグしてみて、やっと IE が名前空間を使用したタグを認識できないと言うことを知ったのでした。
そこでコードに改良を加えるために xml 文書を詳しく眺めてみると item 要素にエントリイ情報が内包されていることが確認できましたので、item 要素を配列内に全て取得してから、その中から必要な要素だけを抽出する方法を採用して、IE でもその他のブラウザと同様の結果が取得できるようにしました。(98-101行。この target オブジェクトは item タグ内から目的とする要素だけを抽出したその結果を受け取るためのもの。)
XML文書の名前空間に関する参考サイト:XML 名前空間の簡単な説明
まず、今見ている頁の直前/直後のエントリイアドレスを取得する方法を考えました。直ぐに今見ている頁の URI アドレスを取得して、それを活用すればよいと判断し、URIアドレスからエントリイ番号とそれ以外とを分離するために、正規表現の exec メソッドを活用しました。(121-123行)
次に HTML 文書からタイトルをゲットするタグはどれがよいのか選択しました。当然それは title タグです。しかし title タグ内にはブログタイトルも含まれているので、substring メソッドを使ってこれを除去しました。(142行)
なお、この関数で最後まで頭を悩ました問題は境界問題(前後のエントリイ数が10に満たない場合)でした。これについては後述します。
このプロジェクトでは Ajax 通信を都合 21 回行っています。
まず最初に、最新エントリイ情報を取得するために xml ファイルを取得しています。( 89-115 行 )
次に、前/後のそれぞれ 10 個のエントリイ情報を取得するために、10 回ずつ合計 20 回の Ajax 通信を履行しています。( 141-150 行 )
これらの 21 回の通信で特に難しかったのは、10 個ずつ合計 20 個のエントリイタイトル情報を取得する通信において、その起動を適切なタイミングで行うためのコードの作成でした。
最新エントリイ情報を取得する Ajax 通信は、たった 1 回だけで最新 10 個のエントリイ情報を取得できてしまいますので、1 回の Ajax 通信結果から 10 個の情報を拾い出すだけで事足ります。
しかし、20 回の非同期で連続進行している最中に結果を取得するのは非常に難しかったのです。
その困難性の打開策については次項で述べます。
Ajax 通信メソッドを実行する上でのポイントはそのタイミングです。
HTML 文内の要素にアクセスするコード( popup 要素に通信結果を格納する等 )は、その対象が存在しなければ機能しません。つまり Ajax 通信結果を格納する popup 要素が存在していなければ通信結果は表示出来ません。しかし、だからといって、通信開始を DOM 読み込み完了後にしたのでは、背景で静かに駆動してくれる Ajax 通信を折角利用するメリットが半減してしまいます。そこで HTML 内のタグにアクセスするコードやイベントハンドラー部分だけに、DOM Ready メソッドを適用することにして、DOM 読み込み完了前に Ajax 通信を開始することとしました。
次に、連続する Ajax 通信から結果を正確に取得するコードにおいて最大のポイントとなったことが 2 つあります。
第一のポイントは timer を使うことです。( この方式に到達するまでに数ヶ月の時を要してしまいました。 )
これにより先行通信と後続通信との間に必要最小限のタイムラグを置くことが出来、先行通信結果の一部を後続通信で利用することを可能としました。。
第二に、複数の Ajax 通信を行う場合で先行する通信結果の一部の値を後続の通信で使用する場合には、先行通信が終わったことを確実に Javascript に知らせなければなりません。そして確実に先行通信が終わってから後続通信を開始しなければなりません。
そのためには、先行通信が終わったことを知らせるフラグが必要となり、そのフラグとして jQuery.active プロパティを活用したのです。
こうして jQuery.active フラグの値に応じて、setInterval timer を停止し、あるいは継続させるようにしました。
ナビゲーションバーに mouseover した時に出現させるポップアップの位置は、当該ナビゲーションバーの近傍が相応しいと誰しも考えるでしょう。
今回はナビゲーションバーの直下に表示するようにさせたかったので、最初は my コードで長年使用してきた位置表示用のコードを利用してみました。
しかし折角 jQuery を活用するのですから、改めてそのコードを十分に利用した方が得策であると判断し、CSS に係る jQuery.js コードをざっと見渡し、本家頁のドキュメントを概観して、十分にその機能が果たせることが分かったので、フルに活用してみました。
利用したメソッドは以下の通りです。
$(〜).width()、$(〜).css()、$(〜).position().left、$(〜).position().top
よく使われる popup は或る要素(= popup 発生元となる)上で mouseover イベントが発生した場合に、その近傍に小窓を popup させると共に、当該発生元要素で mouseout イベントが発生した場合に当該 popup を非表示にするものです。
しかし、今回はそれだけでは駄目です。ナビゲーション要素( A 要素)に mouseover した時に popup 要素( B 要素)を表示させる点は同様ですが、その後 popup の中に mouseover した時、つまりA 要素から mouseout して B 要素に mouseover した時に、当該 popup を消してしまっては意味がありません。
B 要素(popup)は、A 又は B 要素から mouseover した時に消えるようにしなければなりません。併せて B 要素から mouseout した時には、その行き先が A 要素でない場合にだけ B 要素を消さなければなりません。
つまり2つの要素間を mouseover/out/move する複雑なイベントを処理する必要があります。そこで今回は relatedTarget(IE以外)プロパティ又は toElement(IE専用)プロパティを活用することにしました。
2つの要素間を mouseover/out するイベントを処理する場合によく使われる方法は setTimeout メソッドの利用です。
A要素(それには mouseout イベントがバインドされており、そのイベントハンドラー関数は B 要素を隠蔽するもの)から mouseout した時に、B 要素を隠蔽する関数の駆動に timer をセットしておき、 B 要素に mouseover した場合には、このタイマーを停止させて B 要素が隠蔽されることを防ぐものです。この方法では同時に B 要素からの mouseout イベントハンドラー関数にも、同じタイマーをセットすることになります。
この方法はちらつきを防止する上でも有効であり、実はこのサイトのメニュー表示に、タイマー付きの mouseout イベントハンドラー関数を使用しています。
しかしながら、この方法には1つ欠点があります。それは popup が消えるのに所定の時間を要すると言う点です。必要がない時に直ぐに popup が消えてくれないのです。この欠点をなくすために今回は relatedTarget(又はtoElement)プロパティを利用することにしました。
ところで、これらの mouse カーソルの「行き先」情報を有するプロパティは、mouseover/out イベントだけでしか使えないプロパティです。さて ver 1.2.2 以降の jQuery.js の hover メソッドにおいては IE の場合 mouseenter/leave メソッドを起動するように改変されました。つまり IE で toElementプロパティを使おうと思えば、 jQuery の hover メソッドは利用出来ないのです。
こうして popup を引き起こすナビゲーションバー上での mouseover/out イベント処理に関しては、敢えて DOM 0 レベルの「メソッドによるイベントハンドラー」を使うことにしました。( 58-72 行 )
ナビゲーションバーに mouseover した時に popup 表示が引き起こされますが、この popup 内に mousemove する時に relatedTarget 又はtoelement プロパティを活用します。
そして簡潔に済ますために3つの異なる popup 要素には class 名「 popup 」が振ってあります。(22-25行参照)これは、
1: var itsClassName = e ? e.relatedTarget.class : window.event.toElement.class;
2: if (itsClassName!="popup") $(".popup").css("visibility","hidden");
と書いて3つの popup 要素に mouseover した場合にはそれを消さないようにしたかったのです。そして FireFox ではそれに成功したのですが、IE では全く駄目でした。1行目が有効に働かないのです。仕方なく.id の場合には巧くいくので、やむなくこちら(29-38行)にあるように idName を頼りにして relatedTarget 等を利用することにしました。
月別、カテゴリイ別等の表示の場合には今回の Ajax 通信は一切関係がないので、コードの冒頭に表示モードチェックを行うようにして、無駄を排除しました。
これが必要となったのは、背景で静かに進行する Ajax 通信の進行過程を何とか把握し明示させたいと思ったためです。
そのための固有の変数を jQuery グローバル変数のプロパティとして設定し( 11-19 行 )、コードの随所に現在時刻を取得する関数を埋め込んで、通信開始/終了、コード進行開始/終了等の経過時間を計測するようにしました。
当然その取得値をpopup枠内に表示するようにしたことは言うまでもありません。( 168-175 行 )
なお、popup内に表示される所要時間について一言触れておくべきでしょう。
この所要時間は各値を合計しても全体の所要時間と一致しません。以前エントリイと以後エントリイの情報を取得するための Ajax 通信は、20 回の連続する通信であり、これらの全ては殆ど同時に開始されるからです。
最新エントリイを開いている時には直後エントリイは存在しませんし、(10個のエントリイを対象とした場合。以下同様)最新10以下のエントリイを開いている時には直後エントリイ数は10に満ちません。またエントリイ番号 10 以内のエントリイを見ている時には直前エントリイは 10 に満ちません。この、いわば境界領域における挙動の制御にかなり時間を要しました。
ここで行った Ajax 通信で取得する情報は、各エントリイの HTML 文と RSS 配信にも利用されている最新情報に係る xml 文です。これらからエントリイの各種情報(タイトル、リンク、カテゴリイ及び投稿日時)を取得することが目的ですが、各エントリイの情報を獲得するのに不可欠な第一義的情報は、その URI アドレスであり、各エントリ毎に異なるのはそのエントリイ番号です。
具体的には、Fc2 ブログ URI 個別エントリイ表示の場合 http://username.blogN.fc2.com/blog-entry-NNN.html となりますが、このNNNを取得することが最初に行うべきことです。
こうしてエントリイ番号を頼りに複数のエントリイ情報にアクセスするのですが、最新エントリイより大きな数の NNN をもった URI アドレスにアクセスした場合、Ajax 通信はエラーを返しません。Fc2 Web サーバーは空のエントリイ部分を持つ頁をブラウザに提供するからです。
http://username.blogN.fc2.com/ までは実在するアドレス( protocol: "http:"と hostname: "username.blogN.fc2.com" の組み合わせ)なので 404 Not Found にはならず、かつその後に続く「blog-entry-NNN.html」も「論理的には」有効な文字列なのでエラーとならないのでしょう。
一方、NNN が負の値の場合には Fc2 Web サーバーはエラー頁 http://error.fc2.com/blog/ を返します。http://・・・entryの後に「--」とマイナスが2つ以上続くと論理的に不正なアドレスとみなすのでしょう。
ここに Ajax 通信は同一ホスト内でしか有効ではありませんから、今見ているブログ頁と異なるホストアドレスがサーバーから送られた時点で Ajax 通信用 Javascript コードが通信エラーを投げます。
従って、負のエントリイナンバーにアクセスしないようにするか、あるいはエラーが返された時の対応をコードに記述しなければなりません。
解決策としては、より一般化できるエラー処理を使うべきかとも思いましたが、とりあえずより簡単な方法であって同時に無駄なアクセスやエラー処理をしなくて済む方法、つまり負の値を持ったアドレスをサーバーに投げないようにしました。( 124 行)
コードはかなり巨大なもの(簡単な解説を含めて 191 行)となりました。そのため独自のファイルに纏めこれをインクルードして利用するようにしました。
いずれ完璧になればタブや不要なスペース、コメントを全て削除して圧縮版を作成するつもりですが、しばらくは非圧縮版を試験走行させるつもりです。( 2008/8/9 圧縮版を upload して使用しています。)
いずれにせよ、直前直後の10エントリイのタイトルなどが簡単に閲覧できることは、サイト情報の総覧性を高めることになりますので、私は非常に重要な情報提供であると考えています。
ということで、臥薪嘗胆したコードの全貌を以下に明らかにします。
HTML 文においては、公式テンプレートの場合にコメントエリア( <!--comment_area--> 〜 <!--/comment_area--> )内にあるナビゲーションバーを加工する必要があります。popup を当該要素の直下に表示させるためには、ナビゲーションバーをブロック要素に変更しなければなりません。そしてこのブロックを float-left スタイルを使って横一列に並べなければなりません。また DOM 操作のための id も振らねばなりません。
なお、画像をリンクタグ内に含めると IE においてマウスが離れた時に文字列を含むリンク全体が点滅するので、矢印画像はリンク外に外しました。
<div class="navi_container">
<!--nextentry--><div id ="beforeEntryTitle" class="f_l lh_11 pl_15"
style="background:url('http://blog1.fc2.com/image/e/64.gif') transparent no-repeat left center">
<a href="<%nextentry_url>" onclick="this.blur();" title="<%nextentry_title>" accesskey="4">直前のEntry(4)</a></div>
<div class="f_l lh_11"> | </div><!--/nextentry-->
<div id ="recentEntryTitle" class="f_l lh_11"><a href="<%url>" accesskey="5">ホーム(5)</a>
</div><!--preventry--><div class="f_l lh_11"> | </div>
<div id ="afterEntryTitle" class="f_l lh_11 pr_15" style="background:url('http://blog1.fc2.com/image/e/63.gif') no-repeat right center transparent">
<a href="<%preventry_url>" title="<%preventry_title>" onclick="this.blur();" accesskey="6"> 直後のEntry(6)</a></div><!--/preventry-->
<div class="c_b"></div></div>
(1)float-left 指定、(2) float 指定の解除、(3) popup 絶対配置要素指定───この3つをクラス名で設定しました。
その他汎用しているクラス名も活用しました。
.f_l {float:left;}
.c_b {clear:block;}
.popup {
position: absolute; z-index:1000;
color: #eee; background-color: #2f4f4f;
margin: 0;
padding : 4px ;
line-height : 1.2; text-align: left;
border: 2px ridge #aeb;
display: block;
visibility: hidden;
}
.ta_c {text-align:center;}
.em {font-weight:bold;}
.lh_11 {line-height:1.1}
.pl_15 {padding-left:1.5em}
.pr_15 {padding-right:1.5em}
1 :/* 2 : * fileName : get3modeEntryTitles.js 3 : * released : 2008/03/01 4 : * verup : 2008/07/04, 2008/08/09 5 : */ 6 :// 個別表示モードではない場合には何もしないでコード進行を終える。 7 :if (location.href.indexOf("entry")==-1) (function (){return;})(); 8 :else{ 9 :(function($){ 10 : var now=function(){return +new Date;}; // 現在時刻取得 11 : $.extend({ // 所要時間計測・待機起動回数記録用 jQuery 拡張オブジェクト 12 : tr:{ 13 : start:now(), // 時刻値を取得 14 : registerEvent:"", 15 : ajax:{ recent:[],before:[],after:[] }, 16 : end:"", 17 : setEndingCnt:0,waitRecentAjaxCnt:0 18 : } 19 : }); // load 中であることを示す文言の登録 20 : var loading="<div id='loading' class='ta_c'><img src='http://blog1.fc2.com/h/hkom/file/loading_16.gif' width='16' height='16' border='0' alt='' /> Now Loading...</div>"; 21 : $(function(){ // container内に以前/最新/以後の各々のエントリイタイトルを表示するタグを用意 22 : $("#container").append( 23 : "<div id='popup_before' class='popup'>"+loading+"</div>", 24 : "<div id='popup_recent' class='popup'>"+loading+"</div>", 25 : "<div id='popup_after' class='popup'>"+loading+"</div>" 26 : ); 27 : 28 : // イベント発生要素(ナビゲーションブロック)からの mouseout メソッド 29 : var hidePopup = function(e) { 30 : var itsIdName = e ? e.relatedTarget.id : window.event.toElement.id; 31 : if (itsIdName.indexOf("popup") < 0) $(".popup").css("visibility","hidden"); 32 : } 33 : 34 : // イベント発生要素に沿ってpopupを表示する 35 : var popupAlong = function (idName,width,align) { 36 : var targetElem = this; 37 : var jQidName = "#" + idName; 38 : var popupInst = jQuery(jQidName); 39 : 40 : // left,center及びright配置を行うために CSS 値を取得する。 41 : var shift = $("#container").width() -(width || 400) 42 : - parseInt(popupInst.css("border-left-width")) 43 : - parseInt(popupInst.css("border-right-width")) 44 : - parseInt(popupInst.css("padding-left")) 45 : - parseInt(popupInst.css("padding-right")); 46 : // そして popup の横位置指定 47 : popupInst[0].style.left = $("#container").position().left +"px"; 48 : popupInst[0].style.marginLeft = 49 : (align == "left" ? parseInt(popupInst.css("border-left-width")) : 50 : align == "right" ? shift : shift/2 )+ "px"; 51 : // Elementの高さだけ下に 52 : popupInst[0].style.top = $(this).position().top + targetElem.offsetHeight +"px"; 53 : // popupElementの幅を設定(デフォルトは600とする) 54 : popupInst[0].style.width = (width || 600) +"px"; 55 : popupInst[0].style.visibility = "visible"; 56 : } 57 : 58 : // 前・最新・後リストの表示/隠蔽イベントハンドラー 59 : $.each( ["before","recent","after"] ,function(i,item){ 60 : if ( !!document.getElementById( item +"EntryTitle" ) ){ 61 : document.getElementById( item + "EntryTitle" ).onmouseover = function(){ 62 : popupAlong.call(this,'popup_'+item ,600,['left','center','right'][i]); 63 : }; 64 : document.getElementById(item + "EntryTitle").onmouseout = hidePopup; 65 : } 66 : }); 67 : 68 : // 表示された popup の hover イベントハンドラー 69 : $(".popup").hover( 70 : function(e){if ( $(this).css("visibility","visible") ) return;}, 71 : function(e){ $(this).css("visibility","hidden"); } 72 : ); 73 : }); //End of $(function(){}) 74 : 75 : // variable 76 : var html = {recent:[],before:[],after:[]}, getStr={recent:0,before:0,after:0},lastNo, regExpr,thisEntryNo, complement,itval, border={before:0, after:0},realElm = {before:0,after:0}; 77 : 78 : // 最近のタイトルを取得する関数を定義 79 : var makeRecentEntryList = function (limit){ // limitは取得タイトル数 // この関数内で使用する変数を定義する 80 : var No, subject, date, iter=0, ret=[]; 81 : var target ={ //xml ファイル内での順番 82 : link:[], //0 83 : title:[], //1 84 : // description:[], //2……今回は使用しない 85 : // content:[], //3……今回は使用しない 86 : subject:[], //4 87 : date:[] //5 88 : }; // Ajax 通信を行う。 89 : $.ajax({ // 開いている頁のURIアドレスからhttp://○○FC2.com/?xmlを生成する 90 : url: /http:.+fc2\.com\//.exec(location.href)[0] + "?xml" || null, 91 : type: "GET", 92 : dataType: "xml", // データタイプ xml を指示 93 : success: function(xml){ //取得した xml 文書情報を引数 xml に代入 // XML文書が取得できなかった場合「ありません。」を変数に代入 94 : 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>'; 95 : if (xml==undefined || xml==null) {getStr.recent = tmpStr; return;} // この時点の時刻値を取得 96 : $.tr.ajax.recent["start"]=now(); // 各々の target オブジェクト(link、title等)に対して巡回処理。 // 引数 key で target オブジェクトの各プロパティを受け取る。 // xml文書内から item タグを抽出し、その各々に対して巡回処理。 // ここに xml文書内にある item タグはブログの環境設定で登録した // エントリイ数だけ存在し、当該の各エントリイに対応している。 97 : $.each(target,function(key){ // 各 item タグの各子要素から必要なタグを抽出し ret 配列に格納する。 // 必要なタグは 0:link、1:title、4:subject、5:date であり、 // ret[i] は i 番目の item タグの情報(つまりエントリイ情報)が格納される // 配列になる。ret = [ [link0,title0,subject0,data0], [],...,[] ] である。 98 : $.each($(xml).find("item"), function(i,n){ 99 : ret[i]= [$(n).children().eq(0), $(n).children().eq(1), $(n).children().eq(4),$(n).children().eq(5)]; // 取得した各エントリイの link などの4つの情報を、target オブジェクト // 内の各々のプロパティ配列に挿入する。 100 : target[key].push( ret[i][iter].text() ); 101 : }); // 変数 iter の値は target オブジェクトのプロパティ毎に順に増加する。 // iter 値に対応する項目は順に 0:link、1:title、2:subject、3:date となる。 102 : iter++; 103 : }); // xml文書から取得した諸情報をブログ内で表示するために整序する。 104 : for (var i=0; i < limit; i++) { // アドレス情報(target.link[i])からエントリイナンバーを抽出する。 // 抽出する個数は limit 値により制限される。 105 : No = /entry-([0-9]+)/.exec(target.link[i])[1]; // 最終のエントリイ番号を取得する。 106 : i==0 && (lastNo = Number(No)); // カテゴリー名は subject タグに登録されている。 107 : subject =" , " +target.subject[i]; // 日付情報から時刻を除去し年月日だけを抽出する。 108 : date =" , " +target.date[i].substring(0,10); // 上で整序したタイトル名などを格納した配列から各要素を取り出して一連の文字 // 列にする。 109 : html.recent.push( "<li><a href='" + target.link[i] + "' target='_blank'>" + target.title[i] + "</a> (No." + No + subject + date + ")</li>"); 110 : } // 時刻を記録 111 : $.tr.ajax.recent["end"]=now(); // 表示された時に分かりやすいように、キャプションを付け、 // まとめた情報を popup される絶対配置要素内に挿入する 112 : getStr.recent = "<div class='ta_c'><em>Recent " + limit + " Entries</em></div><ul class='ml_1_5'>" + html.recent.join('') + "</ul>"; // 表示に当たって DOM ready Listに待機させる。 113 : $(function(){$("#popup_recent").html(getStr.recent);}); 114 : } //End of success() 115 : }); //End of ajax() 116 : }; //End of makeRecentEntryTitle func 117 : 118 : // 前後のタイトルを取得するための準備を行う // 引数は順に前か後かを表す文字列と求めるタイトル数 119 : var makeEntryList = function(beforeafter,limit){ // ローカル変数定義 120 : var thisHTTP, getEntryNos=[], thisURL=[]; 121 : regExpr = /(http:.+entry-)([0-9]+)/; // 今、開いているエントリイのエントリイ番号を取得 122 : thisEntryNo = Number(regExpr.exec(location.href)[2]); // 今、開いているエントリイのエントリイアドレスの番号より前の文字列を取得 123 : thisHTTP = regExpr.exec(location.href)[1]; 124 : border[beforeafter] = Math.min(limit+1, beforeafter == "before" ? thisEntryNo :Number(lastNo)-thisEntryNo+1 ); // マイナスの番号にならぬように調整すると共に、先行する Ajax通信 // で取得した lastNo 値を使って最終エントリイ番号を設定する。 // 開いているエントリイが 1 番か最終エントリイの場合 125 : if (border[beforeafter]==1) thisURL.length=0; // 連続する limit 個のエントリイ URI を設定し、配列に格納する。 126 : else { 127 : for (var i=1; i < border[beforeafter]; i++) 128 : thisURL.push(thisHTTP + (thisEntryNo - (beforeafter == "before" ? i : -i)) +".html" ); 129 : } 130 : // 準備完了! Ajax 通信開始 131 : getTitlesByAjax.call(this, beforeafter,thisURL); 132 : } 133 : 134 : // Ajax 通信により前後のエントリイタイトル等を取得する関数の定義 // 今開いているエントリイの前後のエントリイタイトル等を Ajax 通信で取得するために // 必要な関数を定義する。この関数は makeEntryList()から呼び出して使用する。 // 引数 tense は前か後を指定するための before/after 値を受け取り、thisURL は // タイトル名等を取得するための、全てのエントリイの URI アドレスを格納した配列である。 135 : function getTitlesByAjax(tense,thisURL){ // エントリイ番号値が存在すれば 136 : if ( thisURL.length != 0 ) { 137 : regExpr = /<title>(.*)<\/title>/; 138 : $.each(thisURL,function(i,aryitem){ // この時点の時刻値取得 139 : $.tr.ajax[tense][i]=[]; 140 : $.tr.ajax[tense][i]["start"]=now(); 141 : $.get(aryitem,function(data){ // data は thisURL[i] の html テキスト文 // title 文字列からブログタイトルを削除する。 142 : var titleStr = regExpr.exec(data)[1].substring(19); 143 : if ( /\S+/.test(titleStr)){ // 空白だけのタイトル名は補足しない。 144 : ++realElm[tense]; // タイトルを取得する数をカウントする。 // 取得結果を表示用に整序して配列に格納 145 : html[tense][i] = "<li><a href='" + aryitem + "' target='_blank'>" + titleStr +" (EntryNo." + /entry-([0-9]+)/.exec(aryitem)[1] + ")</a></li>"; 146 : } 147 : $.tr.ajax[tense][i]["end"]=now(); // 終了時刻を記録 // 時制が「以後」で最後のエントリイアドレスになったら、取得結果をまとめる関数を起動 148 : if (tense == "after" && aryitem == thisURL[thisURL.length-1]) 149 : itval = setInterval(setEnding,20); // インターバル関数を起動 150 : }); 151 : }); // エントリイ番号値が存在しない場合 152 : } else {if (tense=="after") itval = setInterval(setEnding,20);} 153 : }; 154 : // 最終処理用の関数を定義 155 : var setEnding = function (){ 156 : var AjaxLog=""; $.tr.setEndingCnt++; // 繰り返し数を記録 157 : if (jQuery.active==0){ // 全ての Ajax 通信結果が取得出来ていれば // itval 変数があればタイマーをクリアし、その値を null 値とする。 158 : if (itval) {clearInterval(itval);itval=null;} // 以前/以後の順に 159 : $.each(["before","after"],function(i,tense){ 160 : if (realElm[tense]==0) // 1 つも値がなければ // 変数値にその旨を示す情報を設定する。 161 : getStr[tense]="<div class='ta_c'>"+ (tense=='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>"; // 1 つ以上の値があれば 162 : else // 欠番がある場合にそのことを示す文字列を設定 163 : complement = (border[tense]-1 -realElm[tense]!=0) ? 164 : " ( " +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") +" )" : ""; // 以前/以後の別に取得結果とその説明を HTML 文にまとめる。 165 : getStr[tense] = "<div class='ta_c'><strong>"+ (tense=='before' ? 'Before ' : 'After ') + realElm[tense] + " Entries" + complement +"</strong></div><ul style='margin-left:1.5em;list-style-type:disc'>" + html[tense].join('') + "</ul>"; // 以前タイトル値取得所要時間計測結果処理 166 : var beforeTime=$.tr.ajax.before.length ? "<li>以前タイトル取得 Ajax 通信所要時間: "+ ($.tr.ajax.before[realElm.before-1].end-$.tr.ajax.before[0].start)/1000 +" 秒</li>" : ""; // 以後タイトル値取得所要時間計測結果処理 167 : var afterTime=$.tr.ajax.after.length ? "<li>以後タイトル取得 Ajax 通信所要時間: "+ ($.tr.ajax.after[realElm.after-1].end-$.tr.ajax.after[0].start)/1000 +" 秒</li>" : ""; // 所要時間を示すための文字列を構成する。 168 : AjaxLog ="<ul style='margin:0.5em;border-top:white dotted 1px;padding:0.5em 0.5em 0 1em;list-style-type:circle'>"+ 169 : "<li>クリック後 Ajax 通信開始迄の所要時間: "+($.tr.ajax.recent.start-$.tr.start)/1000 +" 秒</li>"+ 170 : "<li>最新タイトル取得 Ajax 通信所要時間: "+ ($.tr.ajax.recent.end-$.tr.ajax.recent.start)/1000 +" 秒</li>"+ beforeTime + afterTime + 171 : "<li>このプロジェクト全体の所要時間: "+ (($.tr.end=now())-$.tr.start)/1000 +" 秒</li></ul>"+ // この頁へのリンクをボタンで設置 172 : <div style='text-align:right;margin:-2em 1em 0.5em 0 '><button onclick='this.blur();window.open(\"http://hkom.blog1.fc2.com/blog-entry-626.html\",target=\"_blank\")'>この Ajax 通信や所要時間について</button></div>"; // 取得結果を表示させるために DOM Ready 登録する。 173 : $(function(){$("#popup_"+tense).html(getStr[tense]+AjaxLog)}); 174 : }); // 最新エントリイ情報の所要時間記録を取得結果表示 HTML 文に追記する。 175 : $(function(){$("#popup_recent").append(AjaxLog)}); 176 : } 177 : } 178 : 179 : // 前後及び最新のタイトルリスト作成 180 : makeRecentEntryList(10); // 最近リスト取得実行 // 反復待機関数 181 : var nextAjaxTimer = function(){ 182 : $.tr.waitRecentAjaxCnt++; // 反復回数を記録 // Recent Entries'Ajax 通信結果が取得出来ていれば 183 : if (jQuery.active==0) { // インターバル変数を無効にする。 184 : if (ival) {clearInterval(ival);ival=null;} 185 : // ここは連続して履行しても問題なく取得結果を html 化できる。 186 : makeEntryList("before",10); // 以前エントリイ 187 : makeEntryList("after",10); // 以後エントリイ 188 : } 189 : } // 待機関数を間欠的に起動する。 190 : var ival = setInterval(nextAjaxTimer,100); // 無名関数を引数付きで起動する 191 :})(jQuery); 192 :}
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が開きます。