10 | 2010/11 |  12

  1. 無料サーバー

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

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


スポンサーサイト

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

ブログ頁内ジャンプ移動に際して、ジャンプ先からジャンプ元に直ぐに戻れるようにする jQuery プラグイン

このエントリイの後に、別のもっとクールな 目次自動作成プラグイン を作りました。

このエントリでは 2 通りの目次が作成され、表示されるようにしましたが、それはここで述べているプラグインが、旧バージョンの目次作成プラグインを前提に作成されているからです。

なお、新しい目次自動作成プラグインについては、こちらで 述べています。

ここで作成した backNforth プラグインは animatedPopup プラグインの使用を前提にしていますが、その animatedPopup プラグインは恐縮ですが IE では動きません。原因は jquery.js ver 1.4.2 の CSS スタイルに係る部分に、IE に対してバグとなってしまう箇所があるようです。この問題は ver 1.4.4 でも解決していないようです。

長文 Web サイト閲覧で困ること

エントリイ情報が多い場合スクロールも大変であるとともに、目次があってそこからそれぞれのアイテム箇所にジャンプできるとしても、ジャンプ後に再び目次に戻りたい場合があります。

その場合には「目次に戻る」ジャンプ機能を搭載すればよいわけですが、他にも直前にジャンプした箇所に戻りたいこともあります。

つまり、あちこちの箇所に容易に行ったり来たりすることが出来れば、閲覧に際して目的の箇所に簡単に辿り着けることになります。

そこでそのようなことを可能とする jQuery プラグインを作ってみました。

当面の運用に際して、次の5つのジャンプ先がリスト表示されて、目的の箇所名をクリックすれば、直ぐにその箇所が表示されるようにしました。

その 5 つのジャンプ先とは、ページトップ、ページエンド、直前の箇所、その前の箇所、最初の箇所です。

▲ToTop

頁内移動を容易にするために

上記 5 つのジャンプ先に簡単に移動するためには、それらがダイアログ内にリスト表示され、目的箇所名をクリックすれば直ぐにそこにジャンプするようにすればよいと考え、そのリストダイアログをポップアップ表示することにしました。

ポップアップは、目次などジャンプする為に使用する箇所に起動イベントを仕込み、ジャンプした後にその画面内のトップ位置にリストダイアログが表示されるようにしました。

ジャンプ先ダイアログをアニメーション表示/隠蔽する

ダイアログは animatedPopup プラグインを使用して出現を演出しました。

しかも、そのポップアップは二段階にして、最初は余り露骨ではなく控えめに表示し、ジャンプダイアログを使いたくなければ直ぐに閉じられるようにしました。

控えめなポップアップからリストダイアログ表示への移行を容易にするために、単純にcloseBar 以外の箇所にマウスオーバーすれば良いようにしました。

何はさておき実例を

  1. このページの上の方にスクロールして、目次を表示してください。
  2. その中の適当な行をクリックすると頁内の該当箇所にジャンプします。
  3. すると移動直後に画面上部中央に小さなポップアップが表示されます。
  4. その closeBar 以外の箇所にマウスオーバーすると、ジャンプダイアログがアニメートポップアップされますので、その 5 つのリスト内から適当な箇所をクリックすれば、目的の箇所に移動します。
  5. ジャンプダイアログにはスクロールイベントハンドラーを組み込み、移動後も常にページ上部中央部に表示され続けるようにしたので、次のジャンプも容易に行えます。

スクリプトコード

  1:(function($){
  2:$.fn.backNforth = function(opts){
    /* 頁内リンク移動を行うポップアップを表示し、容易にジャンプ元に戻ったり
     * 頁トップ、頁ボトムなどへの移動をポップアップ内から指定出来るメソッドで、
     * 全面的に animatedPopup プラグインメソッドを利用している。
     * 当該メソッドの起動元インスタンスは、任意のジャンプ元要素(複数可) とする。
     * 特徴的なことは、href 属性に基づくリンク先移動のためのクリックイベントと
     * 当該プラグインメソッドを起動するイベントが、同じクリックイベントであること。
    * 勿論、他のイベントでも当該メソッドを起動出来るがクリックが一般的だろう。
     * 引数はオブジェクト形式で指定する。ポップアップ内に表示するジャンプ先情報と、
     * ポップアップの現れ方 (0~8)を指定する。
     * 但しジャンプ先情報はスクリプト本体を書き換える必要があるので、一般には指定する必要がなく、
     * 既定値と異なるジャンプ先を表示したい場合には、コードの書き換えが必要となる。
     * release:2010/11/12
     */
  3:  var jQ=this; if (jQ.size()<1) (function(){return false})();
  4:  var jumpList=[], o, $animPopup,$destination,guidePos;
  5:  if (opts==="?" || opts==="?"){
  6:    var mes = "■backNforth プラグインの引数指定方法■\n";
  7:    mes +="{ guidePos : num }\nnum は頁内移動 guide の表示位置を意味し、\n0~8 の数値にする。\n";
  8:    mes +="0:center of window,1:leftTop,2:rightTop,3:rightBottom\n";
  9:    mes +="4:leftBottom,5:topEdge,6:rightEdge,7:bottomEdge,8:leftEdge";
 10:    alert(mes);return;
 11:  }
 12:  o = $.extend({}, $.fn.backNforth.opts, opts && typeof opts==="object" && opts.constructor === Object && opts || {});
 13:  var errFunc = function(){
 14:    if (o.guidePos <1 || o.guidePos >8){
 15:      alert("guidePos の値が不正です。\nguidePosは 0~8 の数値にしてください。"); return;
 16:    }
 17:  }
 18:  var setGuidePos = function(num){
 19:    var obj = num === 0 ? {left:"center",top:"center"} :
 20:      num === 1 ? {left:"0px",top:"0px"} :
 21:      num === 2 ? {right:"0px",top:"0px"} :
 22:      num === 3 ? {right:"0px",bottom:"0px"} :
 23:      num === 4 ? {left:"0px",bottom:"0px"} :
 24:      num === 5 ? {left:"center",top:"0px"} :
 25:      num === 6 ? {right:"0px",top:"center"} :
 26:      num === 7 ? {left:"center",bottom:"0px"} : {left:"0px",top:"center"};
 27:    return $.extend({},obj,{opacity:0.8,origin:num}); //若干透明にする
 28:  }
 29:  var displayJumplist = function(){
 30:    $(this).animatedPopup(o.moveStr,{
 31:      popupCSS:$.extend({},this.guidePos,{textAlign:"left",cursor:"pointer",opacity:1}),duration:200,easing:"swing"}
 32:    );
 33:    $animPopup.children().eq(0).children().each(function(i){
 34:      var movePos = i===0 ? 0 :
 35:        i===1 ? jumpList[0] && parseInt(jumpList[0].top) || null:
 36:        i===2 ? jumpList[1] && parseInt(jumpList[1].top) || null:
 37:        i===3 ? jumpList[2] && parseInt(jumpList[2].top) || null:
 38:        i===4 ? $(document).height() : null;
 39:      $(this).click(function(e){
 40:        jumpList[2] = jumpList[3];
 41:        $("html,body").animate(
              {scrollTop:movePos,scrollLeft:0},500,"easeInSine",
              function(){!$("#popup").size() && $("#popup").bind("hover");});
 42:        jumpList[3] = {top:movePos+"px",left:0};
 43:        $(this).blur();
 44:        return false;
 45:      });
 46:    });
 47:  }
 48:
 49:  $(function(){
 50:    var txt = "この頁内で移動する";
 51:    jQ.each(function(){
 52:      var that = this;
 53:      that.pos = $(that).offset();
 54:      $destination = $($(that).attr("href"));
 55:      that.destinationPos = $destination.offset();
 56:      jumpList = [that.pos, that.destinationPos, that.pos];
 57:      that.guidePos = setGuidePos(o.guidePos);
          // ダミーアニメ(サイズ計測が適切に行われないため、一度起動する。
          // 但し何も表示させないよう透明化する)
 58:      $("body").animatedPopup(" ",{popupCSS:{opacity:0},queue:false,duration:10});
          // guide窓を若干透明にして表示する。
 59:      $("body").animatedPopup(txt,{popupCSS:that.guidePos,duration:200,easing:"easeInOutQuint"});
 60:      $(":animated").queue('fx',[]); // 登録済みのアニメを削除する
 61:      $animPopup = $animPopup===undefined ? $("#animPopup") : $animPopup;
 62:      $animPopup.children().eq(0).mouseover(function(){
 63:        if ($(this).text()===txt){
              // guide の替わりにジャンプ先リストを表示する。
 64:          displayJumplist.call(that);
 65:        } else return;
 66:      });
 67:    });
 68:  });
 69:  return jQ;
 70:};
 71:
 72:$.fn.backNforth.opts = {
 73:  moveStr : "<div accesskey='T'>(T) 頁最上部へ移動</div><div accesskey='1'
        >(1) 最初の位置へ移動</div><div accesskey='2'>(2) 次の位置へ移動
        </div><div accesskey='3'>(3) 直前の位置へ移動</div><div accesskey='B'>(B) 頁最下部へ移動</div>",
      // 0:center of window,1:leftTop,2:rightTop,3:rightBottom
      // 4:leftBottom,5:topEdge,6:rightEdge,7:bottomEdge,8:leftEdge
 74:  guidePos : 5
 75:};
 76:})(jQuery);

// backNforth プラグイン起動用スクリプト
$(function(){
	$("a[href*='contents'],[id*='contents']").addClass("backNforth");
	$(".backNforth").click(function(){$(this).backNforth({guidePos:5})});
});
 
スポンサーサイト

任意の数の clone 要素を、任意の位置に配置する jQuery プラグイン

ID 名または class 名を持つ要素の clone 要素の活用

Web ページ内に存在する要素には一般に ID 属性や class 属性を有する要素が沢山存在し、それぞれに固有の ID 値が与えられ、あるいは複数の種類の class 名が、複数の要素に対して与えられています。

さて、多くの需要があるとは思えませんが、ID や class 名を有する要素を複写して、あれこれの位置に複数表示させたい場合が、時々発生します。例えば、popup 要素を複数同時に表示させたい場合等です。

あるいはページスクロールが発生した際に、或る位置に或る要素を常時表示させたい場合に、当該要素は元のままにして、clone 要素を作って常時表示させることにも活用出来ます。このように頁内での「影武者活用」は他にもあり得ると思われます。

今回作成した jQuery プラグインは ID 属性または class 属性を有する要素の存在を前提として、それらの clone 要素を任意の数だけ作成し、それをまとめて任意の要素の前後、内部あるいは外部に配置するものです。

要素を頁内に挿入するための各種 jQuery インスタンスメソッド

HTML 要素を Javascript で操作することは DOM の操作として大変興味深いものですが、jquery が登場するまでは、スクリプトを使って要素の配置換えや挿入を行うには、大変な労力を費やす必要がありました。

しかし、jquery が登場したことにより、要素の配置換えや挿入は極めて容易な行為に変化しました。因みに要素を操作する各種 jQuery インスタンスメソッドこそ、その容易さ故に jquery の威力を知らしめる格好のツールと言えるかもしれません。

さて、頁内の任意の位置に挿入配置するか、あるいは既に頁内に存在する要素を、任意の要素の前/後/内/外に配置換えするための jQuery インスタンスメソッドは数多く存在しています。よく知られていて利用されるメソッド群だと思いますが、列挙すれば以下の通りです。

凡例:A は操作対象とする要素で S、P、B は A 要素の配置対象とする要素

  1. S.after(A) or A.insertAfter(S) : A 要素を兄弟要素 S の直後に配置
  2. S.before(A) or A.insertBefore(S) : A 要素を兄弟要素 S の直前に配置
  3. P.append(A) or A.appendTo(P) : A 要素を親要素 P の最後の子要素として配置
  4. P.prepend(A) or A.prependTo(P) : A 要素を親要素 P の最初の子要素として配置
  5. P.html(A) : A 要素を親要素 P の子要素として配置
  6. P.wrapInner(A) : P 要素に子要素 A を挿入して、それ迄存在した全ての子要素を A の子要素( = P の孫要素)に変更する
  7. A.wrap(P) : A 要素(複数ある場合にはその各々)を P 要素で包含する
  8. A.wrapAll(P) : A 要素の全てをまとめて P 要素で包含する
  9. B.replaceWith(A) or A.replaceAll(B) : B 要素を A 要素で置換する

▲ToTop

プラグインの動作結果を実例で示します

何はともあれ、ぐだぐだ説明する前にどんなプラグインが完成したのか示すべきでしょう。

行われる一連の作業の概要は次の通りです。

  1. 以下のボタンをクリックすると、
  2. 直ぐに clone 要素の配置方法を選択する select ボックスが表示されます
  3. ボックス内のメソッドリストから配置メソッドを選択すると、
  4. この頁内にあって display:'none' で隠蔽されている ID名 'popup' 要素を元とする clone が作成され、
  5. 選択された配置メソッドによってボタン内に書かれた要素を配置基準として clone 要素が配置されます。

それぞれのボタンをクリックすると、要素配置用メソッドの一覧が選択枝として表示されるので、適当なメソッドをクリックしてください。すると指定した要素の前後、内部または外部に、popup 要素の clone が配置されます。

頁内に存在する ID 名「popup」要素の clone を 5 つ作成し、entry_body 部を配置対象として配置する。
頁内に存在する ID 名「popup」要素の clone を 3 つ作成し、この下のボタンを配置対象として配置する

実例2

今度は頁内に表示されている要素の clone を作成・配置します。ボタンをクリックして表示されるメソッドリストから、適当なメソッドを選択してクリックすれば、clone 要素が各々のボタンの近傍の指定した位置に配置されます。

まずページトップにある時計から。なお、元の時計は絶対配置されていてドラグ可能ですが、clone 時計は相対配置しますのでドラグは出来ません。

次はナビゲーションバーの clone を作って配置します。時計の場合もそうでしたが、makeNputClone 起動に際して第三引数の「 content 」を指定しなければ、第一引数である clone 元要素の clone がコンテンツとしてそのまま配置されます。

プラグイン設計上考慮したこと(1):数ある要素配置メソッドを選択的に適用させるために

プラグイン作成に際してまず検討したことは、上記のように沢山ある要素配置メソッドを、プラグイン使用時にどのように指定させるか、と言う点でした。

まさか、一々引数にメソッドを書き込んで指定する方法では、とても供用出来ません。実際、直前のエントリイで述べた方法は、まさに引数でメソッドを指定する類のものでした。

これではいけない、汎用性が全くないと判断し、その改善を思い立った訳ですが、select ボックスの活用を結論づけるまでにさほど時間は掛りませんでした。

しかし、select ボックスを表示させる方法やその配置方法などを考え始めた時、それをこのプラグイン内でゼロからコーディングすることは、いかにも稚拙であると思えました。

そこで閃きました。汎用性を持たせるために時間を掛けて改訂した animatedPopup プラグインメソッドを利用すればよい!───

このプラグインを使って、select ボックスをポップアップさせれば、clone 要素を配置した直後に、その位置までページスクロールさせるコーディングを行った時に、animatedPopup メソッドで表示させたポップアップ要素は、スクロールイベントに対応しているので、select ボックスも追随してスクロールされ、window 内の同じ位置に表示され続ける!

こうして、clone を作成・配置するプラグインは、その中から別のプラグイン animatedPopup を呼び出すものとなりました。

▲ToTop

プラグイン設計上考慮したこと(2):配置メソッドの選択が連続的に行えるように

このプラグインは clone 要素の作成それ自体よりもその頁内配置に興味を持っています。ですから。あれこれの配置を容易に試みることが出来なければ意味がありません。

そこで、連続して異なるメソッドを選択出来、かつ作成した clone 要素はその都度削除され、新たに作成された clone 要素を異なるメソッドで配置することにしました。

こうして各種配置メソッドを連続的に試すことを可能としたため、結果として各種配置メソッドの効果と差異を、一目瞭然に閲覧することが可能となりました。

2 つのプラグインから使用できる変数について

今回のプラグインで最も苦労したのは、makeNputClone メソッド内から animatedPopup メソッドを起動するにあたり、前者と後者で共通して利用する変数をどう定義するか、ということでした。

前者から一旦後者が呼び出されてしまった後でば、一般に前者内で定義した変数は後者では使用できませんし、前者から後者の変数も利用できません。引数を使って渡す方法もありますが、既に後者の引数定義は確定しており、makeNputClone メソッドからの呼び出しのために後者の引数を追加するのは邪道です。またそれぞれの関数のプロパティに変数を登録する選択肢もありますが、これは変数の記述文字数が多くなるので、コード作成上面倒です。

そこでグローバル変数である $ 変数のプロパティ利用を考えざるを得ませんでした。この方法は 「 余り美しくない 」 のかもしれませんが、他の方法を思いつかず、やむを得ないと判断しました。$.o プロパティを作り、そこに両方のメソッドで共通して使用する変数を登録することにしました。

▲ToTop

makeNputClone プラグインコード

詳細な解説は面倒なので、大きなブロック単位で簡単に説明します。

1 ~ 23 行【エラー処理ブロック】

引数をチェックしてエラーを表示するためのコーディングです。引数なしでプラグインを起動した場合には、簡易 HELP 機能が表示され、引数の指定方法を説明する alert が表示されるようにしました。

25 ~ 27 行【初期値整理ブロック】

初期値は例によって、$.extend クラスメソッドを活用して、既定値と引数値を併合します。プラグインメソッドの呼び出し元となる jQuery インスタンスを $.o プロパティに $target 名で登録します。

29 ~ 71 行 【 clone 作成・配置メソッド定義ブロック 】
fireMethod 関数は animate メソッドによるアニメーションが終わった時点で呼び出される関数として定義しました。その名の通り、配置「メソッド」を起動する機能を持たせました。

プラグインメソッドの起動元は、clone 要素の配置基準となる要素です。一旦プラグインを起動すれば select ボックス内からどのような配置方法を選択した場合でも、配置される clone はずっと同じものです。ですから配置の都度作成する必要はありません。

また、別の要素から当該プラグインを起動した後に、再び以前起動元とした要素から起動した場合でも、clone の作成元として指定した要素が替わらない限り、clone を作り直す必要はありません。

そのため、data クラスメソッドを活用して効率的なインタープリトが可能となるようにしました。( #52~54 )

73 ~ 85 行 【 DOM Ready・selectリスト表示アニメーションブロック 】

最初の 2 行は animate メソッドの complete 引数に代入する関数です。第二引数で makeNputClone メソッドの全ての引数を fireMethod 関数に渡しています。引数を一括指定出来る function.apply メソッドの大きな利点を活用しました。

DOM Ready 関数の最初で改めて第一引数 selector のチェックを行っています。これはエラー処理ブロックでは引数をその文字列で評価しましたが、ここでは指定した ID 名や class 名の要素の存在をチェックしています。

指定した名称が、jquery が解釈する文字列としては正しくても、肝心の該当要素が存在しなければ意味がないからです。

82 ~ 83 行で animatedPopup プラグインを使って、select ボックスを表示するアニメーションを引き起こします。

▲ToTop

88 ~ 164 行は既定値オブジェクトです。3 つのプロパティ別に説明します。

88 ~ 101 行 【 select ボックスリスト作成用 】

select ボックスを作成するための HTML 文字列です。

select リストの文字がデフォルトでは小さすぎるので、fontサイズを指定しました。

適用する配置メソッドの作用が分かりやすいよう、リスト文字列では配置先、メソッド、配置される要素の区別を表示しました。

102 ~ 162 行 【 配置メソッドオブジェクト 】

適用する配置メソッドをこのオブジェクトのプロパティ名とプロパティ値として格納しています。select ボックスでメソッドが選択されると、change イベントが発生し、対応するイベントハンドラー内で、このオブジェクトの関数が呼び出されて clone 要素が所定の位置に配置されます。

この部分で最も苦労したのは html メソッドです。作った clone 要素を敢えて html メソッドの引数として挿入するわけですから、HTML 文字列に変換しなければなりません。当然 id 名や class 名も保持させなければなりません。またスタイル属性値も最小限のものは適用させるようにしないと、clone らしくありません。

これらのハードルはそれぞれにかなり高く、文字列化とスタイル属性値の複写コードには相当苦労しました。

163 行 【 第一引数 selector の格納庫 】
同一要素からの二度目以降 のmakeNputClone メソッド呼び出しの際に、第一引数 selector の値を従前値のそれと比べるために使用します。52 行で行う比較が終わる迄は、このプロパティには、以前に起動された時の selector 名(但し、一度目の起動の際には null )が記憶されます。比較後には今回の selector 値がこのプロパティに保存されます(55 行)。
(function($){
$.fn.makeNputClone = function(selector,n,content,cloneCSS){
/* selector で抽出される最初の要素の clone を n 個作り、それを select
 * ボックス内から選択した jQuery メソッドによって、起動元インスタンス
 * の内外または前後に配置するメソッド。当該プラグインから animatedPopup
 * メソッドを起動し、select ボックスの表示に利用する。
 * selectBox から順次異なる配置位置を選択し、clone の配置換えが可能。
 * 一旦 clone を作成後に n を増やしたい場合にも、重複作成はしないよう
 * コーディングしてあるので、単純に n を指定すればよい。
 * 引数なしで起動すると引数の指定方法を alert 表示するようした。
 * release:2010/11/21
 */
  1:  var errFunc=function(al){al!==undefined && alert(al);return},p;
  2:  if (!arguments.length){
  3:    var text ="■引数の指定方法■\n"
  4:    text+="jQuery(elem).makeNputClone(selector,n,content,cloneCSS)\n\n";
  5:    text+="selector : string of original ID name\n";
  6:    text+="n : number of clones\n";
  7:    text+="content : HTML strings of clone's inner content\n";
  8:    text+="cloneCSS : CSS Object of clone";
  9:    return errFunc(text);
 10:  }
 11:  if (typeof selector !== "string" || selector.indexOf("#")<0 && selector.indexOf(".")<0){
 12:    return errFunc("指定した id 名や class 名の要素は存在しません。\n
          存在する id 名や class 名を指定してください。");
 13:  }
 14:  if (n===undefined || n===null || typeof n!=="number")
 15:    return errFunc("第二引数が不適切です。\n\n第二引数には、作成する
        clone の数を正の整数で指定してください。\n0 を指定すると作成済み
        の clone を削除します。");
 16:  if (content && typeof content !=="string"){
 17:    if (typeof content ==="object" && cloneCSS===undefined){
 18:      cloneCSS = content;
 19:    } else return errFunc("第三引数が適切ではありません。\n\n
 20:      第三引数は clone に挿入する HTML テキスト文としてください。\n
          content を指定しなければ、元要素のコンテンツが clone 要素の
          コンテンツになります。");
 21:  }
 22:  if (cloneCSS && typeof cloneCSS !=="object")
 23:    return errFunc("第四引数が適切ではありません。\n\n
        第四引数は clone に適用する CSS オブジェクトとしてください。\n
        cloneCSS を指定しなければ、元要素のスタイル設定が clone 要素に
        そのまま複写されます。");
 24:
 25:  $.o = $.data(this[0],"opts") || $.data(this[0],"opts",
 26:    $.extend({}, $.fn.makeNputClone.opts, {content:content || null,
          cloneCSS:cloneCSS || null, pluginFunc:arguments.callee,
          pluginArgs:arguments}));
 27:  $.o.$target = this;
 28:
 29:  var fireMethod = function(selector,n,content,cloneCSS){
 30:    var createClone = function(){
 31:      var clonesArray=[], $tmp=$(selector+i), temp, i=1, k=1;
 32:      for (;$tmp.length;i++) $tmp.remove();
 33:      for (; k< n+1; k++){
 34:        var temp = $($(selector)[0]).clone(true)
                .addClass(selector.slice(1) +"clone"+" draggable")
 35:        if (selector.indexOf("#")===0)
 36:          temp.attr('id',selector.slice(1)+k);
 37:        if ($.o.content)
 38:          temp.html('This is No.'+ k +' clone. '+$.o.content);
 39:        if ($.o.cloneCSS)
 40:          temp.css($.o.cloneCSS);
 41:        var $c = temp.children(":[id]");
 42:        if ($c.size()){
 43:          $c.each(function(){
 44:            $(this).attr("id", $(this).attr(selector.slice(1)+k));
 45:          });
 46:        }
 47:        clonesArray[k-1]=temp[0];
 48:      }
 49:      return $(clonesArray);
 50:    }
 51:    
 52:    $.o.$clone = $.o.beforeSelector === selector &&
 53:      $.data($.o.$target[0],"createClone") || 
 54:      $.data($.o.$target[0],"createClone",createClone());
 55:    $.o.beforeSelector = selector;
 56:    $("#thissel").change(function(){
 57:      var index = this.selectedIndex,  
 58:        resMethodName = this.options[index].value;
 59:      for (p in $.o.methodList){
 60:        if (p !== resMethodName) continue;
 61:        else {
 62:          $.o.methodList[p](); // cloneを頁に挿入する
 63:          var $its1=$("[class*='clone']:first");
 64:          $its1.length && $(window).scrollTop($its1.offset().top);
 65:          $its1.length && $its1.offset().left > $.F.getWinSize &&
                $(window).scrollLeft($its1.offset().left);
 66:          break;
 67:        }
 68:      }
 69:      // return $.o.$clone;
 70:    });
 71:  }
 72: 
 73:  var completeFunc = function(){
 74:    return fireMethod.apply($.o.$target, $.o.pluginArgs);
 75:  }
 76:  $(function(){
 77:    if (selector.indexOf("#")===0 && !$(selector).length){
 78:      return errFunc("指定した ID 名の要素は存在しません。\n
          存在する ID 名を指定してください。\nなお、冒頭に#を付ける
          ことを忘れないでください。");
 79:    } else if (selector.indexOf(".")===0 && !$(selector).length){
 80:      return errFunc("指定した class 名の要素は存在しません。\n
          存在する class 名を指定してください。\nなお、冒頭に '.' を
          付けることを忘れないでください。");
 81:    }
 82:    $.o.$target.animatedPopup($.o.selBoxHTML,{
 83:      popupCSS:{left:"center",top:"center"},duration:400,
            easing:"easeOutBack",complete:completeFunc
 84:    });
 85:  });
 86:};
 87: 
 88:$.fn.makeNputClone.opts = {
 89:  selBoxHTML :'<form><select id="thissel" name="thissel" size=12 style="font-weight:bold;font-size:16px">'
 90:    + '<option value="" disabled="desabled" style="text-align:center">メソッドを選択</option>'
 91:    + '<option value="append" selected="selected">target.append(clone)</option>'
 92:    + '<option value="prepend">target.prepend(clone)</option>'
 93:    + '<option value="after">target.after(clone)</option>'
 94:    + '<option value="before">target.before(clone)</option>'
 95:    + '<option value="wrap">target.wrap(clone)</option>'
 96:    + '<option value="wrapAll">target.wrapAll(clone)</option>'
 97:    + '<option value="wrapInner">target.wrapInner(clone)</option>'
 98:    + '<option value="replaceWith">target.replaceWith(clone)</option>'
 99:    + '<option value="replaceAll">target.replaceAll(clone)</option>'
100:    + '<option value="html">target.html(clone)</option>'
101:    + '<option value="remove">clone.remove</option></select></form>',
102:  methodList : {
103:    append: function(){
104:      $.o.methodList.remove();
105:      $.o.$target.append($.o.$clone);
106:    },
107:    prepend: function(){
108:      $.o.methodList.remove();
109:      $.o.$target.prepend($.o.$clone);
110:    },
111:    after: function(){
112:      $.o.methodList.remove();
113:      $.o.$target.after($.o.$clone);
114:    },
115:    before: function(){
116:      $.o.methodList.remove();
117:      $.o.$target.before($.o.$clone);
118:    },
119:    wrap: function(){
120:      $.o.methodList.remove();
121:      $.o.$target.wrap($.o.$clone);
122:    },
123:    wrapAll: function(){
124:      $.o.methodList.remove();
125:      $.o.$target.wrapAll($.o.$clone);
126:    },
127:    wrapInner: function(){
128:      $.o.methodList.remove();
129:      $.o.$target.wrapInner($.o.$clone);
130:    },
131:    replaceWith: function(){
132:      $.o.methodList.remove();
133:      $.o.$target.replaceWith($.o.$clone);
134:    },
135:    replaceAll: function(){
136:      $.o.methodList.remove();
137:      $.o.$clone.replaceAll($.o.$target);
138:    },
139:    html: function(){
140:      $.o.methodList.remove();
141:      var text="";
142:      $.o.$clone.each(function(){
143:        text +="<"+this.nodeName+" id='"+ +$(this).attr("id")+
            "' class='"+$(this).attr("class")+"'>"+$(this).text()+
            "</"+this.nodeName+">";
144:      });
145:      $.o.$target.html(text);
146:      var clone = $("[class*=clone]");
147:      for (var i=0; i<clone.length; i++){
148:        $.each(["width","height","margin","border","padding",
              "background"],  function(){
149:          clone[i].style[this] = $.o.$clone[i].style[this];
150:        })
151:      }
152:    },
153:    remove: function(){
154:      var clone = $("[class*=clone]");
155:      if (clone.length) {
156:        if (clone.has($.o.$target).length){
157:          $(clone[0]).before($(clone[0]).children());
158:        }
159:        clone.remove();
160:      }
161:    }
162:  },
163:  beforeSelector:null
164:}
165:})(jQuery);

▲ToTop

コード解説を行うためにコード全文から抜粋を行うコード

上記の説明では副題をクリックすると該当部分のコードが抜粋表示されます。その表示にも animatedPopup メソッドを活用したのは余興ですが、初めて採用したこの方法では、一箇所に説明用コードを全文書き込むだけで、後は抜粋作業を Javascript を使って行わせれば、容易に抜粋が可能となることを実証したつもりです。

長いエントリイの最後に、コード全文からその一部を抜粋するためのコーディングについて触れておきます。

ネームエンティティ問題

最初は、ブラウザに表示されたエントリイ内のコード全文を検索対象として、抜粋を行おうとしました。ところがこの方法には大きな落とし穴が待っていました。ネームエントリイ問題です。

コード全文掲載に当たっては、HTML 文上意味のある記号(全角で表記すると、"<"、">"、"&" 等)をネームエンティティ変換しててから、エントリイを投稿しています。それによってブログが描画される際に、これらの特殊記号は HTML 文上意味のないものとして扱われ、正しく表記されることになります。こうして、例えば投稿時には &lt; と半角で書いていた記号は、< になって表記されることになります。

さて、この正しく表記されたエントリイ上の文字列から、Javascript を使って抜粋対象を抽出すると、その抽出部分に < が含まれていた場合に、そのまま抽出結果をブログに貼り付けると問題が発生します。単なる記号としての < ではなく、タグ開始文字として HTML 文上意味のある記号となってしまうのです。

この結果、ブログエントリイから部分抽出した結果をそのまま投稿すると、表示が崩れてしまうのです。

再びネームエンティティ変換して原稿とすればよい、と考え試みてみましたが成功しませんでした。投稿した時点のネームエンティティ変換と全く同一にはならないのです。空白文字(改行マークや半角スペースなど)で区切られていない ; がネームエンティティ表記の;と誤解されるらしく、正しく復号することが出来ないのです。(ネームエンティティ変換実施(A)→ブラウザで表記(B)→再度のネームエンティティ変換(C)と辿った時に、A と C は同一にはならないのです)

解明しませんでしたが、他にも正しい「復号」を妨げる要因が複数存在しているようでした。

そこで AJax 通信を使用した

試行錯誤の結果、表記されたブラウザ内の全文コードから Javascript を使って部分抜粋を行い、抜粋部分を再び投稿する方法は、適切ではないと判断するに至りました。

そして替わりに思いついたのが、Ajax 通信を活用することでした。これによりブログエントリイ全文をテキスト形式で取得し、その中から必要部分を抜粋すればよい。そうすればネームエンティティ変換した文字は原文のまま、変換されたままで取得できます。つまり、そこから抜粋した文字列もネームエンティティ変換されたままの状態なので、意図したとおりの結果に辿り着ける───こう考えたのです。

そしてそれは見事に成功しました。

そのコーディングは以下の通りです。

  1:  var pageBody;
  2:  $.ajax({
  3:    url: このサイトのurl,
  4:    dataType:"text",
  5:    success: function(data){
  6:      pageBody = data;
  7:    }
  8:  });
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
  9:  var selectText = function(start,end){ 
 10:    return this.slice(this.indexOf(start),this.indexOf(end)-1);
 11:  };

利用は 1 行目から 8 行目がブログ・エントリイ・オープン時に実行させることを前提にしています。開いた暫く後になってからしか、コードの部分閲覧は発生しないので、その頃には十分 Ajax 通信は complete している訳で、pageBody 変数に通信結果が代入されているはずです。

つまり、Ajax 通信の成功有無はチェックする必要がないと判断しました。

利用は、selectText.call(pageBody,"抽出開始文字","次の抽出開始文字") で行います。敢えて、pageBody から関数を call 起動し、呼び出された関数内で this が pageBody を参照するようにしました。

「開始文字」から「次の開始文字」の 1 文字前迄の文字列群を、Ajax 通信で取得したブログページ全文文字列情報 pageBody から sliceする訳です。これによりコード全文から、必要部分を抜粋することが出来ます。

具体的に抽出例に触れてみます。

下のコードはコード全文から、「 1:」で始まる部分から、「 24:」で始まる部分の 1 文字前迄を抽出し、それを pre タグで囲んで animatedPopup メソッドの第一引数とし、その他当該メソッドに必要な引数を指定して、animatedPopup メソッドを起動するコーディングです。

ID 名 「dt792-1」要素のクリックイベントハンドラーとして、animatedPopup 関数を登録しています。

padding 指定を行っていますが、ブログテンプレートの指定が優先されてしまうようで、引数で指定した padding 通りには animatedPopup しません。これは animatedPopup において popup アップするコンテンツは div 要素で囲まれているのですが、この div 要素にテンプレート固有のスタイル設定が施されているためであると、推測できます。

$("#dt792-1").click(function(){
  $(this).animatedPopup("<pre id='code792-1' class='point ml_1 lh_11 ov_a'>"
    + selectText.call(pageBody,"  1:"," 24:")+ "</pre>",
    {popupCSS:{top:"10px",right:"10px",width:600,origin:2,textAlign:"left",
    paddingLeft:"3px !important",paddingTop:"3px !important",paddingBottom:"3px !important",paddingLeft:"3px !important"}});
}); 

ID 名を持つ要素の clone 要素を複数作成する jQuery プラグイン

jQuery clone インスタンスを作成するプラグイン

このプラグインは、その名の通り、jQuery clone インスタンスを作成するものです。

ポップアップ要素を複数同時に表示させたい場合などに使用することを想定しています。

以下、アンダーライン部は補足説明ポップアップが設定してあります。

起動式は jQuery("#id").makeClone(n,target-jQuery-Instance,AfterOrBefore) で、これにより ID 名として idName を持つ要素の clone を n 個作成し、target jQuery インスタンスの後ろまたは前にまとめて配置します。

必要に応じてどの要素の前後にも clone を配置出来ます。但し、或る要素の中に配置する方法はここでは採用しませんでした。別途検討したいと思います。───願わくば、前後配置内包配置包含配置の全ての配置が可能なプラグインに出来ればと夢想しています。

特徴

  1. clone 元要素は DOM ツリーのどこにあっても構いませんが、当然存在していなければなりません(苦笑)。
  2. 一旦任意の数の clone 要素を作成した後に、異なる個数の clone を、異なる要素の前後に配置することも可能です。その場合以前に作成した clone 要素は全て削除され、改めて後で指定した数の clone 要素が、新しい対象要素の前後に配置されます。
  3. 任意の要素の前後に、任意の数だけ clone 要素を配置出来ますが、同じ ID 名の要素を元とする clone 要素を、異なる要素の前後に配置する機能はありません。
  4. 作成した clone 要素はその定義から元要素の属性を全て引き継ぎます。例えば、元要素が display:'none' となっていれば、作成された clone 要素も一切描画されませんし、絶対配置されている ID 名の要素の clone は絶対配置となります。しかし、このプラグインの返値を clones jQery インスタンスにしたので、作成後に jQuery メソッドチェーンを利用して、自由に属性を変更出来ます。
  5. clone 要素の ID 名は元要素の ID 名に番号を付加したものとしました。(例)元要素の ID 名:"animPopup" → clone 要素の ID 名:"animPopup1"、"animPopup2"、・・・
  6. clone 元要素に子要素があって(孫要素は対象外)、それにも ID 名が存在した場合、clone 要素の子要素の ID 名も、子要素の ID 名 +番号 となるようにしました。
  7. clone 要素を第二引数の前または後の、いずれに配置するかを第三引数で指定します。無指定の場合には後ろに配置します。
  8. 前又は後の配置対象となる要素には ID が振られている必要はありません。任意のしかし1つの要素だけを指定出来ます。

コード

  1:(function($){
  2:$.fn.makeClone = function(n,$target,AfterOrBefore){
  3:/* ID 名として idName を持つ要素の clone を n 個作るメソッド
  4: * 当該メソッドの起動元インスタンスは clone 元要素で ID 名付きで指定する。
  5: * 一旦 clone を作成後に、n を増やしたい場合にも、重複作成はしないよう
  6: * コーディングしてあるので、単純に n を指定すればよい。
  7: * なお、作成した clone 要素をどこに挿入するかは別問題であり、挿入用の
  8: * コーディングが別途必要となる。
  9: * release:2010/11/14
 10: */
 11:	var errFunc=function(al){al!==undefined && alert(al);return false;};
 12:	if (n===undefined) errFunc("引数が指定されていません。\n作成する clone の数を
            正の整数で指定してください。\n0 を指定すると作成済みの clone を削除します。");
 13:	if ($target && !$target.jquery) errFunc("第二引数は clone を配置する前、
            または後ろの jQuery インスタンスを指定してください。");
 14:	if (AfterOrBefore && typeof AfterOrBefore!=="boolean")
          errFunc("第三引数は、trueか fault を指定してください。\ntrue は第二引数の
          後ろに、false は前に clone を配置することを意味します。\n指定しない場合には
          true 扱いとなり後ろに配置するよう設計しました。");
 15:    if (n && (!$target || $target.length===0 || $target.length >1))
          errFunc("第二引数が適切ではありません。指定し直してください。\n
          複数の要素を指し示す指定は出来ませんし、n がゼロの時以外は無指定も
          出来ません。");
 16:
 17:	// 起動元インスタンスは必ず $("#id") 形式とする
 18:	var clones=[], $tmp, i=1, k=1, id = this.attr("id");
 19:	if (!$("#"+id).length)
 20:		return errFunc("その ID 名の要素は存在しません。");
 21:	var setClone = function(){
 22:		for (;$tmp=$("#"+id +i),$tmp.size();i++) $tmp.remove();
 23:		for (;k<n+1;k++){
 24:			clones[k-1] = $("#"+id).clone().attr("id",id +k);
 25:			var $c = clones[k-1].children(":[id]");
 26:			if ($c.size()){
 27:				$c.each(function(){
 28:					$(this).attr("id", $(this).attr("id")+k);
 29:				});
 30:			}
 31:		}
 32:		return $(clones);
 33:	}
 34:	return (AfterOrBefore===undefined || AfterOrBefore) ?
          setClone().insertAfter($target) : setClone().insertBefore($target);
 35:};
 36:})(jQuery);

サンプル

頁内に存在する ID 名「popup」要素の clone を、下のボタン直下に 5 つ作る
頁内に存在する ID 名「popup」要素の clone を、この直下、ボタンの上に 3 つ作る

これらのサンプルでは、結果を見せるために元要素の CSS 設定をいくつか変更しました。例えば、position は "relative" に、display は "block" に変えています。幅も自動的に width:100% となっています。

作成苦労談

作 成 中

自作プラグイン-アニメーションポップアップを全面改訂

恐縮ですが animatedPopup プラグインは IE では動きません。原因は jquery.js ver 1.4.2 の CSS スタイルに係る部分に、IE に対してバグとなってしまう箇所があるようです。この問題は ver 1.4.4 でも解決していないようです。

animatedPopup プラグインを全面的に改訂した

1 年半ほど前に作成した animatedPopup プラグインは、いわば「勢い」で作ったものでプラグインとしての基本的作法は全く考慮せず、我流の作品に止まっていました。

しかし、真にプラグインとして汎用性を持たせるには、スクリプトコードの論理性・明快性・可読性等を考慮しなければならないと考えるに至り、この度数ヶ月を掛けて全面改訂を行いました。

なお、今回の改訂は各種プラグインから利用出来る、完成済みの jQueryクラスレベルの関数オブジェクト jQuery.F を前提に開発しています。その $.F については、こちら( 複数の jQuery プラグインで共有するオブジェクトを無名関数内に定義する )で詳細に説明してあります。

▲ToTop

animated Popup メソッドの実例

ポップアップ表示をアニメーションメソッドを使って行うことを意味しています。例えば極小の点から一定の幅と高さを有する表示ボックスをズームポップアップし、それを消すときにはズームアウトする、そんなポップアップです。

何はさておき、その実例を示すことが先決でしょう。

下のボタンをクリックするとあるいはその近傍に、あるいは画面中央に、あるいは画面右下に、あるいは指定してある位置 {left:100px,top:200px} に、ポップアップがズームイン/アウトされます。表示する際のポップアップサイズは順に300、350、400、500px に、またアニメーションに要する時間はそれぞれ 1200、600、1600、2000、2500 ミリ秒に設定してあります。

 クリックした位置の傍に、左上から現れ、左上に消えるポップアップを表示します。

クリックすると画面の中央に、中心から現れ中心に消えるポップアップを表示します。

クリックすると画面の右下に、右下から現れ右下に消えるポップアップを表示します。

クリックすると指定してある位置に、左側から現れ左側に消えるポップアップを表示します。

クリックすると画面の中央に、上部からぶら下がり上部に巻き上がるポップアップ内に或る写真を表示します。写真出典元は フォトライブラリ です。

▲ToTop

animatedPopup に様々な Easing を適用する

George Smith 氏により提供されている jQuery プラグイン「Easing Plugin」は 10 種類あり、各々に 3 つの効果(easeIn、easeOut、easeInOut)を持たせて Easing 関数が定義されているため、都合 30 種類の easing 関数があります。→ Plugins | jQuery Plugins

その Easing の各々の動きの違いを示したサイトとして興味深いのは、flash ムービーですが easing_demo が実に分かりやすく有益です。これによりそれぞれの Easing がどんな挙動をするのか一目瞭然に理解できます。easing 関数内の代数式がグラフ化されていることも非常に有益です。

そこで、このデモサイトにあやかって、jquery.js 内蔵の linear と swing イージングを加えた 32 種類の Easing 効果を、animatedPopup メソッドに適用するリストボックスを設置してみました。easing_demo に比べて文字表示の場合には各 easing の差異がわかりにくいのですが、まあそれはご愛敬ということで...。

下のリストボックスの説明
  • アニーメーションポップアップの表示位置は 「 画面中央 」 としました。
  • Easing に要する時間はそれぞれの関数の差異が分かり易いように長めに設定しました(2秒)。
  • 別の easing 関数を選択する前に表示されているポップアップを隠蔽する必要はありません。自動的に前の表示を消して、新たな表示を行います。

▲ToTop

全面改訂に当たって心掛けたこと

アンダーライン箇所には、マウスオーバーポップアップによる補足説明が設定されています。

  1. プラグイン内で作成する関数名を、その役割が一目で分かるようなものとしました。命名は基本的に「動詞+関数の機能や内容をを表す名詞」としました。
  2. 作成した関数は、それぞれが果たす役割が明確になるよう基本的に単機能としました。こうしておくとメンテナンスがしやすいからです。
  3. 各種初期値用のオブジェクトを $.fn.animatedPopup.opts プロパティに用意しました。この方法は初期値の明確化、可読性向上、メンテナンスの容易さ等のメリットがあります。
  4. 初期値に対して、可能な限りアニメーションポップアップ要素のCSS値(色、サイズ、位置等々)を自在に変更できるようにコードを工夫しました。
  5. 引数をどのように設定したのか、時間が経つほどにとかく忘れてしまうものです。そこで 特別な文字「?」(半角全角は問わない)を引数にすれば、window.alert 関数で引数の指定方法を表示するようにしました。これで引数の指定内容がいつでも分かるようになりました(いわば簡易 HELP機能です)。
  6. コード内での関数呼び出しには function.call メソッドを多用しました。呼び出された関数の実行時に、キーワード this が当該関数の呼び出し元オブジェクトを参照することを利用して、特定のオブジェクトを当該関数内で参照しやすくするためです。
  7. 当然のことですが、メソッドチェーンを可能とするために animatedPopup 関数の返値は jQuery インスタンスとしました。
  8. 初めて行ったことですが、プラグイン関数のプロパティにプラグイン関数の内部関数を登録し、プラグイン関数が終了した後でもその内部関数を呼び出せるようにしました。

▲ToTop

プラグインコード解説

コードは 200 行強の比較的短いものです。ポップアップ要素のスタイル設定もスタイルシートは使わずスクリプトで行いました。

以下コード全体をいくつかのブロックに分けて解説します。なお、末尾にはコード全体を掲載してあります。

変数設定

トップレベルに定義した変数は animatedPopup 関数全体で使用するものに限定しました。$ で始まる変数は jQuery インスタンスへの参照のためであることを示しています。

errFunc は文字通りエラー発生時に使用する関数です。errFlag 変数に true を代入することにより、animatedPopup 関数の動作を停止します。

  2:$.fn.animatedPopup = function(content,opts){
  3:  var jQ = this,errFlag = false,wait,ival,$animPopup,$xMark,
  4:      errFunc = function(){errFlag=true; return false;};
エラー対応および HELP コンテンツ定義及び各種の値の設定 makeCSS

makeCSS 関数は、$.fn.animatedPopup.opt で定めた初期値と引数 (content,opts) から、プラグイン起動元である jQuery インスタンスに対して適用する様々な値を作成するものです。作成値は CSS 値だけではありませんが、CSS 値作成部分が大半なので代表させて makeCSS と命名しました。

  5:  var makeCSS = function(){
  6:    this.startScrollPos = $.F.getScroll(window);
  7:    this.startWinSize = $.F.getSize(window);
  8:    if (opts && opts.constructor!== Object ){
  9:      alert("配置はオブジェクト形式で指定してください。\n
            例1 popupCSS:{left:\"10px\",top:\"100px\"}\n
            例2 popupCSS:{right:\"20px\",bottom:\"100px\"}");
 10:      errFunc();
 11:    };
 12:    if (!content || content==="") {
 13:      alert("ポップアップする内容が指定されていません。");
 14:      errFunc();
 15:    }
 16:    if (content==="?" || content==="?"){
 17:      var text ="jQuery(anyElement).animatedPopup(contents,opts);\n";
 18:      text +="contents: HTML strings\n";
 19:      text +="opts: Object \n";
 20:      text +="{ popupCSS:{CSS styles set of animatedPopup Element},\n";
 21:      text +="  closeBarCSS:{CSS styles set of closeBar Element},\n";
 22:      text +="  duration:time, easing:name, queue:true or false,complete:function\n";
 23:      text +="}";
 24:      alert(text);
 25:      errFunc();
 26:    }
        // popup 用の各種 CSS オブジェクトを作る。
 27:    var ret= $.extend({}, $.fn.animatedPopup.opts, {content:content}, opts &&  opts.constructor === Object && opts || {});
       // ret のサブオブジェクトが引数 opts により上書きされて
        // しまっている場合があるので、改めて拡張する
 28:    ret.popupCSS = $.extend({}, $.fn.animatedPopup.opts.popupCSS, ret.popupCSS);
 29:    ret.popupOffset = $.extend({}, $.fn.animatedPopup.opts.popupOffset, ret.popupOffset);
 30:    ret.closeBarCSS = $.extend({}, $.fn.animatedPopup.opts.closeBarCSS, ret.closeBarCSS);
 31:    ret.initPopupCSS = $.extend({},ret.popupCSS);
 32:    return ret;
 33:  }
  1. 6~7 行の this.start で始まる 2 つの変数は、ポップアップ要素表示後に window をスクロールしたり、window のサイズを変更した時に、それらのイベントに対応してポップアップ要素の位置を変化させるために使用するもので、animatedPopup 関数起動時の window スクロール値とサイズを取得します(詳細は後述)。
  2. 8~26 行は引数エラーチェックと HELP コンテンツの作成です。引数チェックは、当然 jQuery インスタンス毎に行うことになりますが、インスタンスが複数の要素からなる場合には引数が要素毎に異なる場合もありえます。そこで makeCSS 関数内にエラーチェックコードを配置し、インスタンスの要素毎にチェックするようにしました。
  3. エラーチェック後に、初期値オブジェクトに引数を合成したオブジェクトを作ります(27 行)。このとき、extend クラスメソッドが極めて効果的に働くことは言うまでもありません。このメソッドは、先置した引数オブジェクトのプロパティが後置したオブジェクトにも存在していれば、後置オブジェクトのプロパティ値で上書きし、後置オブジェクトのプロパティが前置オブジェクトに存在しなければ前置オブジェクトに当該プロパティを追加し、複数オブジュエクトを合体させます。この結果、前置オブジェクトのプロパティ値が後置オブジェクトの同一名プロパティ値で置き換えられ、前置オブジェクトになかった後置オブジェクトのプロパティは前置オブジェクトにそのまま追加されます。
  4. こうして初期値を引数値で上書きしますが、初期値のプロパティ値がオブジェクトの場合には、当該オブジェクトが opts オブジェクトの同一プロパティ名のオブジェクトで丸ごと上書きされるため、補正が必要となります。その補正を 28~30 行で行います。
  5. 補正もまた extend メソッドを使います。値がオブジェクトである初期値プロパティに、27 行で作成された同一名のプロパティ値を併合させることにより、27 行目で一部消失してしまった初期値オブジェクトの全てのプロパティを復活させ、これに、27 行目で作成した同一プロパティ名の値を上書きします。こうして全ての初期プロパティを保持したままで、その値を引数値で上書きしたオブジェクト ret が完成します。
  6. 31 行の initPopupCSS プロパティは popupCSS プロパティの初期値を保持するためのもので、window リサイズイベントハンドラー関数内で使用します。

▲ToTop

ポップアップ要素のサイズ計測関数 getSize

ポップアップされるコンテンツ毎にポップアップ要素の幅も高さも変化します。そしてその都度変化するポップアップ要素のサイズに応じて、ポップアップ要素の位置を適切に算出しなければなりません。

しかし、要素サイズは一般にそれが描画されなければ確定できません。文字列の場合特にそうです。最も簡単な解決方法は、全てのコンテンツに対して同一の幅とし、高さは自動的にブラウザに決めさせれば良いのですが、これでは余りに芸がありません。出来る限りコンテンツに相応しい幅と高さにしたいものです。

従って要素を適切にポップアップするには、描画する前にどのようにしてその幅と高さをブラウザに認識させるのか───これがポイントとなります。

 35:  var getCloseBarHeight = function(){
 36:    $animPopup.css({display:"block",visibility:"hidden"});
 37:    var temp = $xMark.outerHeight(true);
 38:    $animPopup.css({display:"none",visibility:"visible"});
 39:    return temp;
 40:  }
 41:  var getSize = function(){
 42:    var ret = this.o, pCSS = $.extend({},ret.popupCSS);
        // popup 要素にコンテンツを挿入し、popup 要素の width と height を計測
        // 1.right や bottom が指定された場合高さを正確に測れなくなるので、
        // これらの属性を削除する。
 43:    if (pCSS.right !== undefined) delete pCSS.right;
 44:    if (pCSS.bottom !== undefined) delete pCSS.bottom;
        // 2.既定の幅と高さをキャンセル後に $animPopup's width を計測し、
        // コンテンツを挿入する。
 45:    $animPopup.css({width:null,height:null,top:0,left:0})
 46:      .children().eq(0).css({width:null,height:null}).html(ret.content);
 47:    var cW = $animPopup.width();
        // 3.幅値を最適化する
 48:    cW = ret.content.match(/\ssrc/) ? cW : Math.min(cW,parseInt(pCSS.width));
        // 4.padding 値を調整する
 49:    pCSS.paddingTop = getCloseBarHeight() + parseInt(pCSS.paddingTop) + "px";
        // 5.得られた幅値を適用して隠蔽状態のまま
        // $animPopup.css メソッドを実行し、各種サイズを計測・取得する
 50:    ret.popupSize = $.F.getSize($animPopup.css($.extend(pCSS,{width:cW+"px"}))[0]);
        // 6.コンテンツが画像などではなく、かつ、幅か高さが 600 px 以上
        // の場合にはスクロールバーを配置する
 51:    if (!ret.content.match(/\ssrc/) && (ret.popupSize.cW >=600 || ret.popupSize.cH >=600)) ret.popupCSS.overflow="auto";
        // 7.取得した padding 値をポップアップ要素表示 CSS に設定する
 52:    ret.popupCSS.paddingTop = pCSS.paddingTop;
        // 8.取得したコンテンツサイズをポップアップ要素表示 CSS に設定する
 53:    ret.popupCSS.width = $animPopup.children().eq(0)[0].style.width = ret.popupSize.cW +"px";
 54:    ret.popupCSS.height = $animPopup.children().eq(0)[0].style.height = ret.popupSize.cH +"px";
 55:  }
サイズ計測のための付随関数 getCloseBarHeight(35~40 行)
  1. この関数はポップアップされた要素を閉じるための部品である closeBar の高さを計測するもので、計測結果を使ってポップアップ要素の paddingTop 値を補正します。わざわざこのようにしたのは、closeBar の CSS 値も引数で変更出来るため、padding 値を自在に設定出来るようにしておかないと使い勝手が悪くなるからです。
  2. この関数の肝は、display:none 状態の要素内にある、子要素のサイズ計測をどのように行うか、にあります。親要素の display 属性が none である限り、子要素に対して width メソッドを適用してもサイズは測れません。ここでは jQuery.swap クラスメソッドで使用している方法を利用しました。
  3. CSS 値を display:block、visibility:hidden に変更してからサイズを計測します。これにより描画させつつ表示させない状態を作って計測可能とします。計測後に display:none、visibility:visible に戻す必要があることは言うまでもありません。
サイズ計測のための前処理(42~44 行)
  1. HTML 要素の描画前にその大きさを知る為に必要となるのは、ポップアップすべきコンテンツそのものと、ポップアップ要素の CSS 値です。(なお、CSS 値は必要不可欠ではありません。また、画像や動画の場合には、要素の属性値に幅などが記載されている場合が多いため事情が異なりますが、そのことはさしあたり無視します。)
  2. しかし、いきなり CSS 値をポップアップ要素に適用すると誤った計算をしてしまう場合があります。何故ならば、CSS値には right や bottom プロパティが存在する場合があり、これらのプロパティがあるとポップアップ要素サイズは、最大で top:0、left:0、right:0、bottom:0 で囲まれた範囲、すなわちブラウザの window サイズになってしまうからです。
  3. そこで一工夫が必要となります。どんな場合であっても right 及び bottom プロパティを強制的に削除した作業用 CSS オブジェクトを用意すれば良いと考えました。その作業用 CSS オブジェクトとコンテンツから、ポップアップ要素サイズを計測すれば、当該要素ボックスの右下隅が window 右下隅になってしまう事態を避けることが出来ます。
  4. 42 行で宣言した変数 pCSS は、この作業用 CSS オブジェクトを参照させるものです。
  5. これに先立って、変数 ret に this.o を代入していますが、この this は jQuery インスタンスに登録されている要素を参照しています。後述するように jQuery インスタンスに登録されている要素を起動元として、getSize 関数に対して call メソッドを適用するからです。
ポップアップ要素の横幅計測
  1. ブラウザに対象要素を表示させることなく当該要素の幅や高さを知るには、jquery.js の inner メソッドである swap クラスメソッドを使う方法があります。しかしここでは、swap メソッドは使用せず、それが使用しているロジックを踏襲してサイズ計測を行いました。
  2. jquery.js は、隠蔽した要素に width メソッドを適用すると、算出スタイル値を取得するよう設計されているので、これを利用すれば良いわけです。但し計測対象の親要素が隠蔽状態にないことが前提となります。(別のエントリイでその具体的な利用方法を記述しました。)
  3. このコードでは 45~47行において、ポップアップ要素へのコンテンツの挿入と横幅計測を行っています。

▲ToTop

ポップアップ要素の横幅設定
  1. ポップアップする要素の大きさは、一般的に何通りかの設定スタイルがあります。ポップアップされる要素が何であれ、全て同一の幅に設定することもあれば、何通りかの既定値を定めておいて、コンテンツに応じて選択的に既定値を選択する方法もあるでしょう。あるいはコンテンツの種類(画像か文字列化など)に応じて何通りかの幅を設定する選択肢もあるでしょう。
  2. このコードでは 48 行でコンテンツ幅の設定を行いますが、画像の場合にはそのコンテンツが持つ固有の幅をポップアップ要素のコンテンツ幅とし、それ以外の場合には既定のコンテンツ幅と取得したコンテンツ幅とを比べて小さい方を採用することとしました。
  3. 言い換えれば、文字列の場合のコンテンツ幅は、固有幅が既定値に満たない場合にはその固有幅に、固有幅が既定値を超える場合には既定値幅に設定します。なお、既定値は初期値として定めた値を、引数で変更することが出来るようにしました。つまり、固有値、初期値及び引数で定めた値の 3 つから選択的に幅が決定されます。(なお、動画表示も十分可能ですが、さしあたり今後の課題とします。)
ポップアップ要素の paddingTop 値計測

getCloseBarHeight 関数を使って closeBar の外寸高さを取得し、これに既定の paddingTop 値を加算して、新たな paddingTop 値を取得します。後は取得した値と既定値を組み合わせて新しい padding 値を作るだけです。

ポップアップ要素の各種サイズ計測
  1. 横幅の計測と設定を終えれば、後はその他のサイズ(コンテンツ高さ、マージン辺幅など)を取得するだけです。その計測は 50 行で行っていますが、ここでは自作のプラグイン共用関数を使用しました。$.F.getSize(elem) 関数を使えば、elem 要素のコンテンツ、パディング辺間、ボーダー辺間及びマージン辺間の、各々の幅(cW、pW、bW、mW)と高さ(cH、pH、bH、mW)を取得することが出来ます。
  2. ここに、幅と高さをコンテンツだけでなく各種辺間距離も取得するのは、window からのポップアップ要素のはみ出し防止のために、要素マージン辺間の幅と高さを利用するためです。確かに、パディング辺間距離とボーダー辺間距離はこのコード内では利用しませんが、自作のサイズ計測関数があるので序でに取得したまでです。
  3. 51 行ではポップアップ要素サイズが大きな場合に必要となるスクロールバーの配置を行います。幅又は高さが 600 px を越えた場合には要素にスクロールバーを配置するよう、overflow 属性を "auto" に指定します。
  4. 以上による各取得値を、52~54 行で当該要素の各種プロパティに代入しアニメーションに備えます。

▲ToTop

ポップアップ要素の配置位置決定 setPos

以上でポップアップ要素の大きさが確定したので、次に行うべきことは引数などに応じて当該要素の配置位置を確定することです。つまり、top 値と left 値を与条件から算出し確定することです。そのための関数が 56~77 行の setPos 関数です。

 56:  var setPos = function(){
 57:    var pCSS = this.o.popupCSS, offCSS = this.o.popupOffset, pSize = this.o.popupSize;
        // right や bottom 指定がされた場合
 58:    if (pCSS.right !== undefined) {
 59:      pCSS.left = this.startWinSize.cW - pSize.mW - parseInt(pCSS.right) +"px";
 60:      delete pCSS.right;
 61:    }
 62:    if (pCSS.bottom !== undefined){
 63:      pCSS.top = this.startWinSize.cH - pSize.mH - parseInt(pCSS.bottom) +"px";
 64:      delete pCSS.bottom;
 65:    }
        // left 値や top 値が "center" で指定された場合
 66:    if (pCSS.left ==="center") pCSS.left = this.startWinSize.cW/2 - pSize.mW/2+"px";
 67:    if (pCSS.top ==="center") pCSS.top = this.startWinSize.cH/2 - pSize.mH/2+"px";
        // mouse cursor 近傍に popup する場合の位置指定
        // left 値か top 値に false を指定することによりその旨を指定する
 68:    if (pCSS.left === false || pCSS.top === false) {
 69:      pCSS.left = parseInt($.F.mousePos.X) + parseInt(offCSS.left) + "px";
 70:      pCSS.top = parseInt($.F.mousePos.Y) + parseInt(offCSS.top) +"px";
 71:    } else {
        // mouse cursor 近傍以外の場所に表示する場合には scroll 値を加算
 72:      pCSS.left=parseInt(pCSS.left) + this.startScrollPos.L+"px";
 73:      pCSS.top=parseInt(pCSS.top) + this.startScrollPos.T+"px";
 74:    }
        // 画面外への飛び出し防止補正
 75:    pCSS.left = Math.max(0, Math.min(this.startWinSize.cW + this.startScrollPos.L - pSize.mW, parseInt(pCSS.left)))+"px";
 76:    pCSS.top = Math.max(0, Math.min(this.startWinSize.cH + this.startScrollPos.T - pSize.mH, parseInt(pCSS.top)))+"px";
 77:  }

位置決めは引数で与えられた情報によりケース分けして行いますが、全てのケースにおいて、自作のプラグイン共用関数をフル活用しています。

  1. 引数で位置指定を行わない場合には、top も left も初期値を "center" と定めたので、ポップアップ要素は window 中心に表示されることになります。
  2. 引数で right や bottom 属性が指定された場合には、問題を単純化するためにも left やtop に置換し、right や bottom 属性を削除します。(58~65行)
  3. 引数で top や left 値に center が指定された場合の対応を 66、67行で行っています。
  4. 引数で top 又は left 値に false を指定すると、それはマウス位置の近傍にポップアップ要素を表示することを意味するように定めました。false が指定された場合の対応は、68~71 行で行い、top も left も false 値が指定されていない場合には、top 値 と left 値に window のスクロール値を加算します。ここでも自作のプラグイン共用関数をフル活用しています。(72、73行)
  5. 最後に、画面外へのポップアップ要素の飛び出しを防止する措置を 75、76 行で講じています。
ポップアップ要素の展開/縮小を演出する setShrinkOuterCSS

アニメーションポップアップの要点は当該要素の「登場・退場」の仕方にあります。

アニメーションとは言い換えれば、要素の CSS 現在値が CSS 到達値に変化する過程が動的に表示されることに他なりません。従って、隠蔽状態から表示状態へ、そしてその逆への 2 つの過程を演出するには、隠蔽状態の CSS 値を作成しなければなりません。その隠蔽状態 CSS 値を setShrinkOuterCSS 関数で作成します。

なお、OuterCSS と命名したのはポップアップ要素のマージン辺内を対象としてシュリンクさせるからです。

 79:  var setShrinkOuterCSS = function(){
 80:    var pCSS = this.o.popupCSS,
 81:        pSize = this.o.popupSize,
 82:        Xdir = pCSS.origin ===5 || pCSS.origin ===7,
 83:        Ydir = pCSS.origin ===6 || pCSS.origin ===8;
 84:    return {opacity:0,
 85:      borderLeftWidth: Xdir ? pCSS.borderLeftWidth : 0,
 86:      borderRightWidth: Xdir ? pCSS.borderRightWidth : 0,
 87:      borderTopWidth: Ydir ? pCSS.borderTopWidth : 0,
 88:      borderBottomWidth:  Ydir ? pCSS.borderBottomWidth : 0,
 89:      paddingLeft: Xdir ? pCSS.paddingLeft : 0,
 90:      paddingRight: Xdir ? pCSS.paddingRight : 0,
 91:      paddingTop: Ydir ? pCSS.paddingLeft : 0,
 92:      paddingBottom: Ydir ? pCSS.paddingBottom : 0,
 93:      marginLeft: Xdir ? pCSS.marginLeft : 0,
 94:      marginRight: Xdir ? pCSS.marginRight : 0,
 95:      marginTop: Ydir ? pCSS.marginTop : 0,
 96:      marginBottom: Ydir ? pCSS.marginBottom : 0,
 97:      width: (Xdir ? pSize.cW : 0) +"px",
 98:      height: (Ydir ? pSize.cH : 0) +"px",
 99:      width: ((pCSS.origin ===5 || pCSS.origin ===7) ? pSize.cW : 0) +"px",
100:      height: ((pCSS.origin ===6 || pCSS.origin ===8) ? pSize.cH : 0) +"px",
101:      left:parseInt(pCSS.left) + 
102:        (pCSS.origin ===0 ? pSize.mW/2 :
103:        pCSS.origin ===2 ? pSize.mW :
104:        pCSS.origin ===3 ? pSize.mW :
105:        pCSS.origin ===6 ? pSize.mW : 0) +"px",
106:      top:parseInt(pCSS.top) +
107:        (pCSS.origin ===0 ? pSize.mH/2 :
108:        pCSS.origin ===3 ? pSize.mH :
109:        pCSS.origin ===4 ? pSize.mH :
110:        pCSS.origin ===7 ? pSize.mH : 0)+"px"
111:    }
112:  }
  1. この関数の肝は origin プロパティによる CSS 属性値の編集設定です。
  2. origin プロパティは、初期値 0 を $.fn.animatedPopup.opts.popupCSS.origin に定めておき、makeCSS 関数により要素の o.popupCSS.origin に複写させます。
  3. origin 値は 0:center of element,1:leftTop,2:rightTop,3:rightBottom,
    4:leftBottom,5:topEdge,6:rightEdge,7:bottomEdge,8:leftEdge の 9 つの値を取ることが出来るよう設計しました。(これらの値以外が与えられるとエラー関数処理を行いコード進行を停止します。)
  4. 0~8 の値は順に、表示状態の対象要素の中心、左上隅、右上隅、右下隅、左下隅、上辺、右辺、下辺、左辺の位置を意味します。origin 値の初期値は 0 、つまり要素の中心から登場し、中心に消える設定にしてありますが、引数で任意に指定することにより、9 つの起終位置を指定することが出来ます。
  5. setShrinkOuterCSS 関数において、アニメがある一点から始まり、その点に収斂する場合には(これを便宜的に「点モードアニメ」と呼びます)、隠蔽状態の各種 CSS 値をゼロとしていること、これに対して線モードアニメの場合には、アニメ終了線が要素の上下の時には幅値を固定し、アニメ終了線が要素の左右の時には高さ値を固定していることに注目してください。

▲ToTop

popup 要素タグの作成

以上でポップアップ要素のサイズと位置を決める関数が終わりました。続いてポップアップ要素タグそのものを Web 頁に挿入するコードです。

113:  var makePopupElem = function(){
114:    if (!$("#animPopup").size()) {
115:      $("<div id='animPopup'></div>").css({position:"absolute",display:"none",zIndex:"1000"})
            .append("<div></div>")
            .appendTo(document.body);
116:    }
117:    $animPopup=$("#animPopup");
        // Popup 隠蔽用×タグの作成
118:    if (!$("#xMark").size()){
119:      $("<div id='xMark'>CLOSE</div>").css($.fn.animatedPopup.opts.closeBarCSS)
            .append("<div style='position:absolute;z-index:1003;top:0;right:2px;width:13px'>×</div>")
            .appendTo($animPopup);
120:    }
121:    $xMark = $("#xMark");
122:  };
  1. この部分は他言は要しないと思いますので、最小限の説明に留めます。
  2. ポップアップ要素は絶対配置、隠蔽指定を行い、コンテンツ用の div 要素を内包させます。
  3. ポップアップ要素の中にこれを閉じるための closeBar を配置しますが、これも絶対配置します。そのバーの右隅に×印があった方がそれらしくなるので、これも絶対配置で配置します。
  4. size インスタンスメソッドを使って、ポップアップ要素等が重複登録されないようにしています。また $ で始まるショートカット変数を指定して要素へのアクセスを簡便化しています。
  5. 引数で closeBar の CSS 値を適切に指定すれば、cloceBar の高さ、色等を変更出来るように、また closeBar 自体を不要とすることも出来るようにしました。但し、その場合には開いたポップアップ要素を閉じるボタン等を作るか、animPopup 要素自身をクリックした時に、hideAnim 関数を起動するように別途設定する必要があります。そのイベントハンドラーは、極めて簡単な例としては、次のようになるでしょう。但し、このコードの場合には収斂位置は指定出来ませんので、animatedPopup を使用した場合に比べると消え方はシンプルになります。
    $("#animPopup").click(function(){$(this).fadeOut()})

▲ToTop

隠蔽アニメーション関数 hideAnim

既に作成した outerShrinkCSS オブジェクトと setShrinkInnerCSS 関数呼び出し結果を第一引数として、2 つの同期的に作動する隠蔽アニメーション関数を定義します。2 つのアニメーションは同時に引き起こされること、待ち行列 fx の登録済みアニメーションを削除してから隠蔽アニメを行う必要があることに留意してください。

ここに setShrinkInnerCSS 関数はコンテンツ要素の CSS 値をシュリンクさせるものです。

また、ポップアップ要素だけでなく、コンテンツ要素にも隠蔽アニメーションを適用していることに注目してください。そうすることにより、ポップアップ要素を隠蔽する際に、そのコンテンツも同じ終点または終線に向かって収斂するようになります。

      // make CSS Object for hide animation
124:  var setShrinkInnerCSS = function(){
125:    var pCSS = this.o.popupCSS,
126:        Xdir = pCSS.origin ===5 || pCSS.origin ===7,
127:        Ydir = pCSS.origin ===6 || pCSS.origin ===8;
128:    return {
129:      width: (Xdir ? this.o.popupSize.cW : 0) +"px",
130:      height: (Ydir ? this.o.popupSize.cH : 0) +"px",
131:      opacity:0
132:    };
133:  }
134:  var hideAnim = function(){ // popup 要素の隠蔽アニメーション
135:    this.o.hidden=true;
136:    $(":animated").queue('fx',[]).stop(); >// 登録済みのアニメを全て停止する
137:    $animPopup.animate(this.o.shrinkOuterCSS,
          {queue:false,duration:this.o.duration,easing:this.o.easing})
          .children().eq(0).animate(innerShrinkCSS.call(this),
          {duration:this.o.duration,easing:this.o.easing});
138:  }
ポップアップ表示アニメーション関数 showAnim

この関数でもポップアップ要素とコンテンツ要素の 2 つを対象にして、同期アニメーションを実行します。関数の起動元は animatedPopup プラグインを起動した jQuery インスタンスです。

139:  var showAnim = function(){ // popup 要素の表示アニメーション
140:    if (errFlag) {
141:      errFlag = false; //$(this).unbind("click");
142:      return errFunc();
143:    }
144:    $(":animated").queue('fx',[]).stop(); // 登録済みのアニメを全て停止する
        // 表示する前に、animPopup の幅と高さをゼロにして所定位置に
        // 非表示描画で配置する。
145:    if (this.o.hidden===undefined)
146:      $animPopup.css(this.o.shrinkOuterCSS).children().eq(0).css(innerShrinkCSS);
        // 表示アニメーション
147:    this.o.popupCSS.display="block";
148:    var fn = function(){$.fn.animatedPopup.running=false;} // 初期化
149:    $animPopup.animate(this.o.popupCSS,{
150:      queue:this.o.queue, duration:this.o.duration,
151:      easing:this.o.easing, complete:this.o.complete}
152:    ).children().eq(0).animate(
153:      {width:this.o.popupCSS.width,height:this.o.popupCSS.height,opacity:this.o.popupCSS.opacity},
154:      {queue:false,duration:this.o.duration,easing:this.o.easing}
155:    );
156:  }
  1. 実行に先立ち、もしエラーがあれば、errFunc 関数を起動して return 値を return して、コード進行から抜け出します。二度の return が必要なのは showAnim メソッドがトップレベルではなく、doAnim メソッド内から呼び出されるためです。なお、jQuery インスタンスから click バインドを外すことも検討しましたが、一度きりのエラーの alert 表示だけでは不十分と考え、アンバインドは無効としました。(140~143 行)
  2. 次に、待ち行列に登録されている全てのアニメーションの登録を解除します。そうしないと アニメ起動時に、待ち行列に登録されている他の同期アニメーションも起動してしまうからです。(144 行)
  3. 既に隠蔽アニメーションが起動済みの時には、隠蔽 CSS 設定を行う必要がないため、o.hidden プロパティ値を検査します。未だ一度も隠蔽アニメーションが起動していなければ、つまり初めての表示アニメーションである場合には、ポップアップ要素に隠蔽 CSS 値を設定して、表示アニメ起動前のポップアップ要素の状態を作ります。(145~147 行)
  4. 148 行で display 値を block にすることで、表示アニメーションによってポップアップ要素が実際に表示されるようにします。
  5. 後はポップアップ要素とコンテンツに対する 2 つの同期アニメーションを起動するだけです。なお、ここに 2 つの要素をアニメ対象としたのは、コンテンツの器であるポップアップ要素だけでなく、そのコンテンツにもアニメを適用することにより、アニメーションの視覚効果をより一層高めるためです。(149~155 行)

▲ToTop

表示アニメーションの起動 doAnim

初期値は false である running プロパティ値を true にして、アニメーションが始まることを記録します。タイマー変数を解除してから、表示アニメーション関数 showAnim を起動します。この関数も呼び出し元は jQuery インスタンスです。

157:  var doAnim = function(){
158:    $.fn.animatedPopup.running=true;
159:    if (wait) {clearInterval(wait);wait=null};
160:    showAnim.call(this);
161:  }
DOM Ready 関数

これまでの長い過程を経てやっと animatedPopup プラグインの最後の関数に辿り着きました。最後の関数である DOM Ready 関数の中で、これまで説明してきた全ての関数の起動が行われる、と言っても過言ではありません。

163:  $(function(){
164:    makePopupElem();
165:    return jQ.each(function(){
166:      var that=this, // this=jQ[i]
          // animPopup を目的の位置に配置するCSSオブジェクトを作る。
167:      if ($xMark.css("display")!=="none")
168:        $xMark.click(function(){hideAnim.call(that)});
169:      else $animPopup.click(function(){hideAnim.call(that)});
170:      that.o = makeCSS.call(that);
171:      getSize.call(that);
172:      setPos.call(that);
173:      that.o.shrinkOuterCSS = setShrinkOuterCSS.call(that);
174:      if ($.fn.animatedPopup.running){
175:        wait = setInterval(function(){doAnim.call(that)},1000);
176:      } else doAnim.call(that);
177:      $(window).scroll(function(){
178:        this.endScrollPos = $.F.getScroll(window);
179:        that.o.popupCSS.left = parseInt(that.o.popupCSS.left)
180:          + this.endScrollPos.L - this.startScrollPos.L + "px";
181:        that.o.popupCSS.top = parseInt(that.o.popupCSS.top)
182:          + this.endScrollPos.T - this.startScrollPos.T + "px";
183:        that.o.shrinkOuterCSS = setShrinkOuterCSS.call(that);
184:        $animPopup.css({left:that.o.popupCSS.left,top:that.o.popupCSS.top});
185:        this.startScrollPos = this.endScrollPos;
186:      });
187:      $(window).resize(function(){
188:        this.endWinSize = $.F.getSize(window),
189:          x = that.o.initPopupCSS.left==="center" && 2 ||
                  that.o.initPopupCSS.right!==undefined && 1 || false,
190:          y = that.o.initPopupCSS.top==="center" && 2 ||
                  that.o.initPopupCSS.bottom!==undefined && 1 || false;
191:        if (x){
192:          that.o.popupCSS.left = parseInt(that.o.popupCSS.left)
193:            + this.endWinSize.cW/x - this.startWinSize.cW/x + "px";
194:        }
195:        if (y){
196:          that.o.popupCSS.top = parseInt(that.o.popupCSS.top)
197:            + this.endWinSize.cH/y - this.startWinSize.cH/y + "px";
198:        }
199:        that.o.shrinkOuterCSS = setShrinkOuterCSS.call(that);
200:        $animPopup.css({left:that.o.popupCSS.left,top:that.o.popupCSS.top});
201:        this.startWinSize = this.endWinSize;
202:      });
203:    });
204:  }); // End of "DOMReady function"
205:  arguments.callee.hideAnim = function(){hideAnim.call(jQ[0]);};
206;  return jQ;
207:}; // End of "animatedPopup function"
アニメーション起動前の各種準備とアニメ起動
  1. 何はさておき、animatedPopup プラグイン起動直後に、ポップアップ要素や closeBar 要素を頁内に設置します。(163 行)
  2. 165 行以下は jQuery インスタンスが複数のタグ要素を含んでいることを前提にしています。また、jQuery インスタンスに登録されている要素を指し示すために this を多用しますが、参照先が随時変動する this の悪影響を受けぬよう、変数 that に this を代入して利用します。こうしておけば関数内で this がグローバルオブジェクト(つまり window オブジェクト)を参照してしまっても、that によって意図したとおり確実に jQuery インスタンスに登録されている要素を指し示すことが出来ます。(166 行)
  3. 諸関数の起動前に closeBar に対する click イベントを登録します。(163行)
  4. その後順次、makeCSS、getSize、setPos、setShrinkOuterCSS を起動し、ポップアップ要素のアニメーションに必要となる表示状態と隠蔽状態の各 CSS 値設定を行います。(170~173 行)なお、全ての関数が call メソッドを適用して呼び出されていることに注目してください。また、呼び出された関数内では this キーワードが起動元を参照することを積極的に活用していることにも注目してください。
  5. 全ての設定を終えた後に、174~176 行でアニメーション起動を行います。

▲ToTop

アニメーション起動後のイベント登録

ポップアップ要素のアニメーションが終わってから、スクロールすることもあれば、window サイズを変更することもあり得ます。これらに対応出来るように、window オブジェクトに 2 つのイベントを登録しました。

まずスクロールイベントから。

このスクロールイベントはポップアップ後に左右上下のスクロールが発生した場合、表示済みのポップアップ要素を window 内での「初期表示位置」に保つことを目的とします。初期表示位置とは、引数 opts で指定した位置( 指定しない場合には、初期値で指定してある window 座標の top:"center",left:"center" )です。

このイベントハンドラーにより、例えば、画面右下に配置指定を行って animatedPopup プラグインを起動した場合、スクロールイベントが発生しても、当該のポップアップ要素はずっと画面右下に配置され続けるようにします。

  1. 最初にスクロールイベント発生後の頁座標上の top 値、left 値を this.endScrollPos オブジェクトのプロパティに取得します。(178 行)
  2. 次に、このオブジェクトのプロパティ値と、スクロールイベント発生前に作成済みの startScrollPos オブジェクトのプロパティ値の差分値を算出し、top 値と left 値を補正します(179~182 行)。この差分値がスクロール量になります。
  3. 補正した top 値、left 値をポップアップ要素の隠蔽用 CSS セットと表示用 CSS セットに上書きし、それにより表示済みポップアップ要素の位置を変化させ、隠蔽アニメーションの収斂点や収斂線を移動します。(183~184 行)
  4. 最後にスクロールイベント発生後の top 値、left 値をスクロールイベント発生前の値に代入し、更なるスクロールイベントの発生に備えます。

次はwindow リサイズイベントです。

このリサイズイベントはポップアップ後に window サイズが変更された場合、表示済みのポップアップ要素を window 内での「初期表示位置」に保つことを目的とします。初期表示位置とは、引数 opts で指定した位置( 指定しない場合には、初期値で指定済みの top:"center",left:"center" )です。

スクロールイベントの場合には全ての配置形式において、配置位置を変更させるようにコーディングしましたが、window リサイズイベント発生時に要素配置を変更させる意味があるのは、センター配置と right プロパティや bottom プロパティが指定された場合のみと考えました。top 値、left 値が値で指定された場合には、リサイズしても位置を変更させる必要はありません。

このイベントハンドラーにより、例えば、画面横及び縦方向の中心位置にポップアップ要素を配置するように指定して animatedPopup プラグインを起動した場合、window サイズを変更しても当該のポップアップ要素は引き続き画面横及び縦方向の中心位置に配置され続けます。

  1. 最初に、リサイズイベント発生直後の window サイズを取得し this.endWinSize オブジェクトのプロパティに記録します。
  2. また配置指定が center で行われた場合には x や y に 2 を代入し、right や bottom 指定が行われた場合には x や y に 1 を代入します。x や y はリサイズ時に必要な補正を行うための変数です。
  3. その補正を 191~198 行で行います。
  4. その後、表示及び隠蔽アニメーション用 CSS セットに補正値を代入し、配置位置を決めます。(199~200 行)
  5. リサイズ直後の配置位置オブジェクトを更なるwindowリサイズに備えて、this.startWinSize オブジェクトに代入します。(201 行)

▲ToTop

プラグイン関数に、よく使うその内部関数を登録する

これはふと思いついたにしては、大変効果が大きく素晴らしいと思っているコードです。

プラグイン関数の中で定義した、プラグイン内部だけで使用する関数を、当該プラグインが起動し終えた後でも、つまりコード進行が終わった後でも使用したい場合にはどうすればよいだろうか?───それが事の発端です。

特にポップアップ要素の場合、随時任意に閉じられることが重要で、jQuery インスタンスメソッドである animatedPopup 関数が起動を終えてから、隠蔽関数 hideAnim を起動させる方法はないものか...と考えた結果、ふと思いついたものです。

205 行の arguments.callee.hideAnim = function(){hideAnim.call(jQ[0])}; がそれです。animatedPopup 関数内部におかれた arguments.callee は、animatedPopup 関数それ自体を指し示しますから、そのプロパティに hideAnim を登録し、hideAnim が起動するコードと同様のコードを function 内に記述したのです。

こうすることにより、animatedPopup 関数が終了した後でも、$("#animPopup").animatedPopup.hideAnim() を起動すれば、収斂点や収斂線の指定はそのままに、設計通りの隠蔽アニメーションが起動出来るのです。

これを使用すれば、closeBarCSS を表示しない引数指定を行った場合に、次のように、#animPopup 要素にクリックイベントを登録することによって、隠蔽アニメーションを意図したとおりに起動させることが出来ます。

$("#animPopup").click(function(){$(this).animatedPopup.hideAnim()});

引数の初期値オブジェクト $.fn.animatedPopup.opts

初期値をこの形式で設定する方法は、cycle プラグインに拠りました。非常に重宝するので必ず使用している程使いやすいものです。プラグイン関数の opts プロパティにオブジェクトを代入して設定します。

    // 引数の初期値を設定
208:$.fn.animatedPopup.opts = {
209:  content:"",
210:  popupOffset:{left:"16px",top:"16px"},
211:  popupCSS:{
212:    position:"absolute",zIndex:1000,left:"center",top:"center",
213:    color:"white",fontWeight:"bold",
214:    width:"400px",backgroundColor:"royalblue", margin:0,
215:    paddingTop:"5px",paddingBottom:"5px",paddingLeft:"5px",paddingRight:"5px",
216:    borderWidth:"5px", borderColor: "plum", borderStyle:"ridge",
217:    textAlign:"center", display:"none",
218:    opacity:1, overflow:"visible",
        // 0:center of element,1:leftTop,2:rightTop,3:rightBottom
        // 4:leftBottom,5:topEdge,6:rightEdge,7:bottomEdge,8:leftEdge
219:    origin:0
220:  },
221:  closeBarCSS:{
222:    position:"absolute",zIndex:"1002",
223:    textAlign:"center",
224:    opacity:0.75,top:0,left:0,cursor:"pointer",
225:    fontSize:"small",lineHeight:"1.2em",width:"100%",
226:    backgroundColor:"midnightblue",display:"block"
227:  },
228:  queue:true, duration:800, easing:"swing", complete:function(){}
229:};
230:})(jQuery);
  1. content は何も指定せず、引数でこれを指定しない場合にはエラー関数が起動するようにしました。
  2. popupOffset プロパティはマウスカーソル位置をクリックした位置から、どの程度離すかを定めたものです。初期値は右及び下に 16px 離す設定です。
  3. popupCSS プロパティは animatedPopup によって起動するポップアップ DIV 要素の CSS 値を定めるものです。
  4. closeBarCSS はポップアップ DIV 要素の上部に表示するボックス隠蔽機能を持った要素のCSSを設定するものです。
  5. 228 行は animate メソッドの第 2 引数オブジェクトのプロパティとなる各種初期値です。

animatedPopup 全コード

  1:(function($){
  2:$.fn.animatedPopup = function(content,opts){
  3:  var jQ=this,errFlag=false,wait,ival,$animPopup,$xMark,
  4:      errFunc = function(){errFlag=true; return false;};
  5:  var makeCSS = function(){
  6:    this.startScrollPos = $.F.getScroll(window);
  7:    this.startWinSize = $.F.getSize(window);
        // 入力エラー及び help 対応
  8:    if (opts && opts.constructor!== Object ){
  9:      alert("配置はオブジェクト形式で指定してください。\n
            例1 popupCSS:{left:\"10px\",top:\"100px\"}\n
            例2 popupCSS:{right:\"20px\",bottom:\"100px\"}");
 10:      errFunc();
 11:    };
 12:    if (!content || content==="") {
 13:      alert("ポップアップする内容が指定されていません。");
 14:      errFunc();
 15:    }
 16:    if (content==="?" || content==="?"){
 17:      var text ="jQuery(anyElement).animatedPopup(contents,opts);\n";
 18:      text +="contents: HTML strings\n";
 19:      text +="opts: Object \n";
 20:      text +="{ popupCSS:{CSS styles set of animatedPopup Element},\n";
 21:      text +="  closeBarCSS:{CSS styles set of closeBar Element},\n";
 22:      text +="  duration:time, easing:name, queue:true or false,complete:function\n";
 23:      text +="}";
 24:      alert(text);
 25:      errFunc();
 26:    }
        // popup 用の各種 CSS オブジェクトを作る。
 27:    var ret= $.extend({}, $.fn.animatedPopup.opts, {content:content}, opts && opts.constructor !== Object && {} || opts);
        // ret のサブオブジェクトが引数 opts により上書きされて
        // しまっている場合があるので、改めて拡張する
 28:    ret.popupCSS = $.extend({}, $.fn.animatedPopup.opts.popupCSS, ret.popupCSS);
 29:    ret.popupOffset = $.extend({}, $.fn.animatedPopup.opts.popupOffset, ret.popupOffset);
 30:    ret.closeBarCSS = $.extend({}, $.fn.animatedPopup.opts.closeBarCSS, ret.closeBarCSS);
 31:    ret.initPopupCSS = $.extend({},ret.popupCSS);
 32:    return ret;
 33:  }
 34:
 35:  var getCloseBarHeight = function(){
 36:    $animPopup.css({display:"block",visibility:"hidden"});
 37:    var temp = $xMark.outerHeight(true);
 38:    $animPopup.css({display:"none",visibility:"visible"});
 39:    return temp;
 40:  }
 41:  var getSize = function(){
 42:    var ret = this.o, pCSS = $.extend({},ret.popupCSS);
        // popup 要素にコンテンツを挿入し、popup 要素の width と height を計測
        // 1.right や bottom が指定された場合高さを正確に測れなくなるので、
        // これらの属性を削除する。
 43:    if (pCSS.right !== undefined) delete pCSS.right;
 44:    if (pCSS.bottom !== undefined) delete pCSS.bottom;
        // 2.既定の幅と高さをキャンセル後に
        // $animPopup's width を計測し、コンテンツを挿入する。
 45:    $animPopup.css({width:null,height:null,top:0,left:0})
 46:      .children().eq(0).css({width:null,height:null}).html(ret.content);
 47:    var cW = $animPopup.width();
        // 3.幅値を最適化する
 48:    cW = ret.content.match(/\ssrc/) ? cW : Math.min(cW,parseInt(pCSS.width));
        // 4.padding 値を調整する
 49:    pCSS.paddingTop = getCloseBarHeight() + parseInt(pCSS.paddingTop) + "px";
        // 5.得られた幅値を適用して隠蔽状態のまま
        // $animPopup.css メソッドを実行し、各種サイズを計測・取得する
 50:    ret.popupSize = $.F.getSize($animPopup.css($.extend(pCSS,{width:cW+"px"}))[0]);
        // 6.コンテンツが画像などではなく、かつ、幅か高さが 600 px 以上
        // の場合にはスクロールバーを配置する
 51:    if (!ret.content.match(/\ssrc/) && (ret.popupSize.cW >600 || ret.popupSize.cH >600)) ret.popupCSS.overflow="auto";
        // 7.取得した padding 値をポップアップ要素表示 CSS に設定する
 52:    ret.popupCSS.paddingTop = pCSS.paddingTop;
        // 8.取得したコンテンツサイズをポップアップ要素表示 CSS に設定する
 53:    ret.popupCSS.width = $animPopup.children().eq(0)[0].style.width = ret.popupSize.cW +"px";
 54:    ret.popupCSS.height = $animPopup.children().eq(0)[0].style.height = ret.popupSize.cH +"px";
 55:  }
 56:  var setPos = function(){
 57:    var pCSS = this.o.popupCSS, offCSS = this.o.popupOffset, pSize = this.o.popupSize;
        // right や bottom 指定がされた場合
 58:    if (pCSS.right !== undefined) {
 59:      pCSS.left = this.startWinSize.cW - pSize.mW - parseInt(pCSS.right) +"px";
 60:      delete pCSS.right;
 61:    }
 62:    if (pCSS.bottom !== undefined){
 63:      pCSS.top = this.startWinSize.cH - pSize.mH - parseInt(pCSS.bottom) +"px";
 64:      delete pCSS.bottom;
 65:    }
        // left 値や top 値が "center" で指定された場合
 66:    if (pCSS.left ==="center") pCSS.left = this.startWinSize.cW/2 - pSize.mW/2+"px";
 67:    if (pCSS.top ==="center") pCSS.top = this.startWinSize.cH/2 - pSize.mH/2+"px";
        // mouse cursor 近傍にpopupする場合の位置指定
        // left 値か top 値に false を指定することによりその旨を指定する
 68:    if (pCSS.left === false || pCSS.top === false) {
 69:      pCSS.left = parseInt($.F.mousePos.X) + parseInt(offCSS.left) + "px";
 70:      pCSS.top = parseInt($.F.mousePos.Y) + parseInt(offCSS.top) +"px";
 71:    } else {
        // mouse cursor 近傍以外の場所に表示する場合には scroll 値を加算
 72:      pCSS.left=parseInt(pCSS.left) + this.startScrollPos.L+"px";
 73:      pCSS.top=parseInt(pCSS.top) + this.startScrollPos.T+"px";
 74:    }
        // 画面外への飛び出し防止補正
 75:    pCSS.left = Math.max(0, Math.min(this.startWinSize.cW + this.startScrollPos.L - pSize.mW, parseInt(pCSS.left)))+"px";
 76:    pCSS.top = Math.max(0, Math.min(this.startWinSize.cH + this.startScrollPos.T - pSize.mH, parseInt(pCSS.top)))+"px";
 77:  }
      // 幅/高さが極小の要素 css 値を設定する。これにより展開/縮小を演出する。
 78:  var setShrinkOuterCSS = function(){
 79:    var pCSS = this.o.popupCSS,
 80:        pSize = this.o.popupSize,
 81:        Xdir = pCSS.origin ===5 || pCSS.origin ===7,
 82:        Ydir = pCSS.origin ===6 || pCSS.origin ===8;
 83:    return {opacity:0,
 84:      borderLeftWidth: Xdir ? pCSS.borderLeftWidth : 0,
 85:      borderRightWidth: Xdir ? pCSS.borderRightWidth : 0,
 86:      borderTopWidth: Ydir ? pCSS.borderTopWidth : 0,
 87:      borderBottomWidth:  Ydir ? pCSS.borderBottomWidth : 0,
 88:      paddingLeft: Xdir ? pCSS.paddingLeft : 0,
 89:      paddingRight: Xdir ? pCSS.paddingRight : 0,
 90:      paddingTop: Ydir ? pCSS.paddingLeft : 0,
 91:      paddingBottom: Ydir ? pCSS.paddingBottom : 0,
 92:      marginLeft: Xdir ? pCSS.marginLeft : 0,
 93:      marginRight: Xdir ? pCSS.marginRight : 0,
 94:      marginTop: Ydir ? pCSS.marginTop : 0,
 95:      marginBottom: Ydir ? pCSS.marginBottom : 0,
 96:      width: (Xdir ? pSize.cW : 0) +"px",
 97:      height: (Ydir ? pSize.cH : 0) +"px",
 98:      width: ((pCSS.origin ===5 || pCSS.origin ===7) ? pSize.cW : 0) +"px",
 99:      height: ((pCSS.origin ===6 || pCSS.origin ===8) ? pSize.cH : 0) +"px",
100:      left:parseInt(pCSS.left) + 
101:        (pCSS.origin ===0 ? pSize.mW/2 :
102:        pCSS.origin ===2 ? pSize.mW :
103:        pCSS.origin ===3 ? pSize.mW :
104:        pCSS.origin ===6 ? pSize.mW : 0) +"px",
105:      top:parseInt(pCSS.top) +
106:        (pCSS.origin ===0 ? pSize.mH/2 :
107:        pCSS.origin ===3 ? pSize.mH :
108:        pCSS.origin ===4 ? pSize.mH :
109:        pCSS.origin ===7 ? pSize.mH : 0)+"px"
110:    }
111:  }
112:
      // popup 要素及び幅事前計測用の div 要素タグの作成
113:  var makePopupElem = function(){
114:    if (!$("#animPopup").size()) {
115:      $("<div id='animPopup'></div>")
            .css({position:"absolute",display:"none",zIndex:"1000"})
            .append("<div></div>").appendTo(document.body);
116:    }
117:    $animPopup=$("#animPopup");
        <span class="aquamarine">// Popup 隠蔽用×タグの作成</span>
118:    if (!$("#xMark").size()){
119:      $("<div id='xMark'>CLOSE</div>")
            .css($.fn.animatedPopup.opts.closeBarCSS)
            .append("<div style='position:absolute;z-index:1003;top:0;right:2px;width:13px'>×</div>")
            .appendTo($animPopup);
120:    }
121:    $xMark = $("#xMark");
122:  };
      // for hide animation
123:  var setShrinkInnerCSS = function(){
124:    var pCSS = this.o.popupCSS,
125:        Xdir = pCSS.origin ===5 || pCSS.origin ===7,
126:        Ydir = pCSS.origin ===6 || pCSS.origin ===8;
127:    return {
128:      width: (Xdir ? this.o.popupSize.cW : 0) +"px",
129:      height: (Ydir ? this.o.popupSize.cH : 0) +"px",
130:      opacity:0
131:    };
132:  }
133:  var hideAnim = function(){ // popup 要素の隠蔽アニメーション
134:    this.o.hidden=true;
135:    $(":animated").queue('fx',[]).stop(); >// 登録済みのアニメを全て停止する
136:    $animPopup.animate(this.o.shrinkOuterCSS,
          {queue:false,duration:this.o.duration,easing:this.o.easing})
          .children().eq(0).animate(setShrinkInnerCSS.call(this),
          {duration:this.o.duration,easing:this.o.easing});
137:  }
138:
139:  var showAnim = function(){ // popup 要素の表示アニメーション
140:    if (errFlag) {
141:      errFlag = false; //$(this).unbind("click");
142:      return errFunc();
143:    }
144:    $(":animated").queue('fx',[]).stop(); // 登録済みのアニメを全て停止する
        // 表示する前に、animPopup の幅と高さをゼロにして
        // 所定位置に非表示描画で配置する。
145:    if(this.o.hidden===undefined)
146:      $animPopup.css(this.o.shrinkOuterCSS).children().eq(0).css(setShrinkInnerCSS.call(this));
        // 表示アニメーション
147:    this.o.popupCSS.display="block";
148:    var fn = function(){$.fn.animatedPopup.running=false;} // 初期化
149:    $animPopup.animate(this.o.popupCSS,{
150:      queue:this.o.queue, duration:this.o.duration,
151:      easing:this.o.easing, complete:this.o.complete}
152:    ).children().eq(0).animate(
153:      {width:this.o.popupCSS.width,height:this.o.popupCSS.height,opacity:this.o.popupCSS.opacity},
154:      {queue:false,duration:this.o.duration,easing:this.o.easing}
155:    );
156:  }
157:  var doAnim = function(){
158:    $.fn.animatedPopup.running=true;
159:    if (wait) {clearInterval(wait);wait=null};
160:    showAnim.call(this);
161:  }
162:
163:  $(function(){
164:    makePopupElem();
165:    jQ.each(function(){
166:      var that=this, // this=jQ[i]
          // animPopup を目的の位置に配置するCSSオブジェクトを作る。
167:      if ($xMark.css("display")!=="none")
168:        $xMark.click(function(){hideAnim.call(that)});
169:      else $animPopup.click(function(){hideAnim.call(that)});
170:      that.o = makeCSS.call(that);
171:      getSize.call(that);
172:      setPos.call(that);
173:      that.o.shrinkOuterCSS = setShrinkOuterCSS.call(that);
174:      if ($.fn.animatedPopup.running){
175:        wait = setInterval(function(){doAnim.call(that)},1000);
176:      } else doAnim.call(that);
177:      $(window).scroll(function(){
178:        this.endScrollPos = $.F.getScroll(window);
179:        that.o.popupCSS.left = parseInt(that.o.popupCSS.left)
180:          + this.endScrollPos.L - this.startScrollPos.L + "px";
181:        that.o.popupCSS.top = parseInt(that.o.popupCSS.top)
182:          + this.endScrollPos.T - this.startScrollPos.T + "px";
183:        that.o.shrinkOuterCSS = setShrinkOuterCSS.call(that);
184:        $animPopup.css({left:that.o.popupCSS.left,top:that.o.popupCSS.top});
185:        this.startScrollPos = this.endScrollPos;
186:      });
187:      $(window).resize(function(){
188:        this.endWinSize = $.F.getSize(window),
189:          x = that.o.initPopupCSS.left==="center" && 2 ||
                  that.o.initPopupCSS.right!==undefined && 1 || false,
190:          y = that.o.initPopupCSS.top==="center" && 2 ||
                  that.o.initPopupCSS.bottom!==undefined && 1 || false;
191:        if (x){
192:          that.o.popupCSS.left = parseInt(that.o.popupCSS.left)
193:            + this.endWinSize.cW/x - this.startWinSize.cW/x + "px";
194:        }
195:        if (y){
196:          that.o.popupCSS.top = parseInt(that.o.popupCSS.top)
197:            + this.endWinSize.cH/y - this.startWinSize.cH/y + "px";
198:        }
199:        that.o.shrinkOuterCSS = setShrinkOuterCSS.call(that);
200:        $animPopup.css({left:that.o.popupCSS.left,top:that.o.popupCSS.top});
201:        this.startWinSize = this.endWinSize;
202:      });
203:    });
204:  }); // End of "DOMReady function"
205:  arguments.callee.hideAnim = function(){hideAnim.call(jQ[0]);};
206;  return jQ;
207:}; // End of "animatedPopup function"
    // 引数の初期値を設定
208:$.fn.animatedPopup.opts = {
209:  content:"",
210:  popupOffset:{left:"16px",top:"16px"},
211:  popupCSS:{
212:    position:"absolute",zIndex:1000,left:"center",top:"center",
213:    color:"white",fontWeight:"bold",
214:    width:"400px",backgroundColor:"royalblue", margin:0,
215:    paddingTop:"5px",paddingBottom:"5px",paddingLeft:"5px",paddingRight:"5px",
216:    borderWidth:"5px", borderColor: "plum", borderStyle:"ridge",
217:    textAlign:"center", display:"none",
218:    opacity:1, overflow:"visible",
        // 0:center of element,1:leftTop,2:rightTop,3:rightBottom
        // 4:leftBottom,5:topEdge,6:rightEdge,7:bottomEdge,8:leftEdge
219:    origin:0
220:  },
221:  closeBarCSS:{
222:    position:"absolute",zIndex:"1002",
223:    textAlign:"center",
224:    opacity:0.75,top:0,left:0,cursor:"pointer",
225:    fontSize:"small",lineHeight:"1.2em",width:"100%",
226:    backgroundColor:"midnightblue",display:"block"
227:  },
228:  queue:true, duration:800, easing:"swing", complete:function(){}
229:};
230:})(jQuery);

職場のWebサイトにNAMAZUを導入───6年越しの念願が叶う

2005年1月に開設した職場のWebサイト

それはこの Fc2 無料ブログサービスが始まって間もない時期だった。

現在の職場に、外部からアクセスできない Web サイトを HTML、CSS、Javascript により全くオリジナルの形式で開設したのは、2005 年 1 月だった。

それは専ら仕事に関わる情報だけを取扱い、常時業務情報にアクセスしやすいように心掛けたラン内で閉じたサイトで、業務情報へのショートカット、パソコンの使い方・ソフトやデバイスドライバのインストール解説・Office ソフトの使い勝手向上等々の Web サイトリンク集等々を寄せ集めた、小さな小さな Web サイトである。

それでもリンク情報は日に日に増大し、アクセスできる情報(職場内の各種システムへのショートカット、基礎資料、業務関連 WWW サイトへのリンク集など)は、6年の星霜を重ねて優に万の単位に累積し、「常時必要な情報に直ぐにアクセス出来る」機能性は、アクセス情報が増えるにつれ、年々徐々に低下していた。

トップ頁に掲載している文字情報だけでは、それが分類されていても探す手間が大変になってきていた。

だから当然、サイト内検索機能を搭載する必要性が年々高まっていた。

Web サーバーソフトは 04Web サーバー

開設に当たって Web サーバーソフトの選択を迫られたわけだが、AN HTTP や Apache ではなく 04Web サーバーを選んだのは、偏に導入が簡単に思えたからに他ならない。

実際、極めて容易に開設に漕ぎ着けたのだが、そのこととは裏腹に、NAMAZU との相性についての情報は少なく、かつ NAMAZU 自体の情報も素人が容易に理解出来るサイトは決して豊富にある訳ではなく、NAMAZU 導入の敷居は非常に高かった。

実際過去に数度、NAMAZU 導入にチャレンジしたことはあるが、その都度 NAMAZU インストールで躓いてしまい、成功しなかった苦い経験もした。

だから、半ば諦めかけ、日々の業務に負われる中で次第に NAMAZU から遠ざかってしまっていた。

かくして気づけば 6 年の歳月が流れ去った。

▲ToTop

ついに NAMAZU を導入

今回、性懲りもなく NAMAZU 導入にチャレンジしたのは、サイト内検索の必要性がますます高まる中で、その機能がどうしても必要であるとの思いを新たにし、かつ、いくつかの Web サイトを探索してみて、04Web サーバーでも問題なく NAMAZU が作動すると確信を得たからである。

そして、今導入出来なければこの先もずっと不可能であると判断したからである。

実際、NAMAZU のインストールは何度やってもなかなか成功せず、PPM インストールの段階で何度も何度も躓き、今回もまたしても不成功か?!───と諦めかけていた。

そんな折に、偶々検索してヒットしたサイトから PPM に関連するプログラムのダウンロードを試みて、手動で PPM ファイルのインストールを試みたところ、成功してしまったのである!

その、躓きつつも成功した NAMAZU 導入の苦労談は別途まとめることにしたい。

 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が開きます。

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