2013年8月31日土曜日

【jQuery】iframe要素をモーダルウィンドウっぽいポップアップで読み込ませる


課題でつかったjQueryの一部を復習かねてまとめます。

こんなかんじで、ある要素をクリックした時点で画面全体をグレーアウトさせるレイヤーとその上にポップアップする外部ファイルを読み込むiframe要素を生成し、グレーアウト部分をクリックするとポップアップもグレーアウトレイヤーも消えて元画面に戻ります。
特にプラグインは必要なく、jQuery本体があれば実装できるつくりになっています。

イメージとしてはこんな感じ。


--------------------------------------------------------------------

HTMLはjQueryが動作しない時、javascriptの動作を許可しないユーザーのために

<a href="URL" target="_blank">リンク文字</a>

と別窓リンクを設定しておきます。
HTMLはこれだけで。

---------------------------------------------------------------------

CSSの設定は以下。

/*グレーアウトのスタイル定義*/
#gray{
background:#000;
opacity:0.8;
width:100%;
height:100%;
position:fixed;
top:0;
left:0;
display:none;
z-index:500;
}

/*ポップアップ部分のスタイル定義*/
#square{
display:block;
width:490px;
height:510px;
z-index:510;
background-color:#fff;
overflow:hidden;
}

#popup{
display:block;
width:490px;
height:510px;
overflow:hidden;
border:none;
}


---------------------------------------------------------------------
以下はjQueryのコード。

$(function(){
 /*-------------------------------
 イベント処理「PopUp」を定義
 --------------------------------*/
 var PopUp = function(){
  //読み込む外部ファイルを取得しておく
  var poplink = ($(this).attr('href'));
  //要素を作成
  $('<div id="gray" class="gray_panel"></div>').appendTo($('#main'));
  $('<div id="square"><iframe id="popup" name="popup"></iframe></div>').appendTo($('#main'))
  .css('display','none');
  //ポップアップを画面中央位置になるよう、位置関係を算出
  var leftposition = Math.floor(($(window).width() - $("#square").width()) / 2);

  //グレー背景をフェードインで表示
  $('#gray')
   .fadeIn("slow")
   .css("display","block");
  //ポップアップ表示領域のスタイル定義
  $('#square')
   .fadeIn("slow")
   .css({
    "position" :"fixed",
    "top"  :"30px",
    "left"  :leftposition,
    "display" :"block",
    "overflow" :"hidden"
   });
  $('#popup')
   //ポップアップ内に外部ファイルを読み込む
   .attr('src',poplink)
   .css({
    "position" :"fixed",
    "top"  :"30px",
    "left"  :leftposition,
    "display" :"block",
    "overflow" :"hidden"
   });

  //クリックして別窓表示という本来の動作をキャンセル
  return false;
 };
 /*-------------------------------
 イベント処理「PopDown」を定義
 --------------------------------*/
 //作成したグレーアウト、iframe、表示領域をフェードアウトさせて削除する
 var PopDown = function(){
  $('#gray,#popup,#square')
   .fadeOut("slow")
   .remove();
 };

 /*-------------------------------
 定義した処理を呼び出す指示
 --------------------------------*/
 //リンクをクリックしたらイベント処理「PopUp」を呼び出し
 $('
リンクの要素名')
  .click(PopUp);
 //グレーアウト部分をクリックしたらイベント処理「PopDown」を呼び出し(追加要素へのイベント処理なのでliveメソッド使用)
 $('#gray').live('click',PopDown);
});

--------------------------------------------------------------------------
ちょこちょこ入れているコメントアウトの通りですが細かく解説をいれると以下のようになります。

1.イベント処理[PopUp]を定義

  //読み込む外部ファイルを取得しておく
  var poplink = ($(this).attr('href'));

ここで、変数poplinkを用意し、クリックした要素(HTMLのリンク文字)が持つリンク先URL(href="URL"のURL)を取得して代入しておきます。
たとえばHTMLで<a href="page1.html" target="_blank">リンク文字</a>としていたら変数poplinkにはpage1.htmlが代入されます。



  //要素を作成
  $('<div id="gray" class="gray_panel"></div>').appendTo($('#main'));
  $('<div id="square"><iframe id="popup" name="popup"></iframe></div>').appendTo($('#main'))
  .css('display','none');

ここでクリックしたときにポップアップしてくる要素を生成します。
ここではグレーアウトさせるためのdiv要素を「gray」、ポップアップするiframeを内包したdiv要素を「square」、外部ファイルを読み込むiframe要素を「popup」とID付しています。
初期状態ではCSS・display:noneで非表示にしています。



 //ポップアップを画面中央位置になるよう、位置関係を算出
  var leftposition = Math.floor(($(window).width() - $("#square").width()) / 2);

これはコメントアウトの通りです。
変数leftpositionに計算式で出した数値を代入します。



 //グレー背景をフェードインで表示
  $('#gray')
   .fadeIn("slow")
   .css("display","block");

ここで画面全体を覆うグレーアウトのdiv要素#grayをfadeInメソッドで表示させます。



//ポップアップ表示領域のスタイル定義
  $('#square')
   .fadeIn("slow")
   .css({
    "position" :"fixed",
    "top"  :"30px",
    "left"  :leftposition,
    "display" :"block",
    "overflow" :"hidden"
   });


ポップアップのiframeを内包したdiv要素・#squareを上記の#grayと同じようにフェードインさせると共に、表示位置をCSSのpositionで設定。ここでpositionのleftに、先ほど用意した変数leftpositionを使います。



$('#popup')
   //ポップアップ内に外部ファイルを読み込む
   .attr('src',poplink)


生成したdivが含むiframe ・「#popup」が読み込む外部ファイルのソースを設定します。
生成した時点では<iframe id="popup" name="popup"></iframe>と、idとname付けしかしていないのでattrメソッドで属性src,値を変数poplinkとして追加します。



 //クリックして別窓表示という本来の動作をキャンセル
  return false;

これもそのまま。javascriptが動作した場合はHTMLに設定している別窓リンクをキャンセルさせます。これって、なんでreturn falseでキャンセルされるのかいまいちわからないまま使っています。(……)



2.イベント処理「PopDown」を定義

//作成したグレーアウト、iframe、表示領域をフェードアウトさせて削除する
 var PopDown = function(){
  $('#gray,#popup,#square')
   .fadeOut("slow")
   .remove();
 };

フェードアウトさせるための処理です。
生成した#gray,#popup,#square三つの要素すべてをフェードアウトして要素を削除します。
この削除がポイント。フェードアウトさせるだけでは、非表示になるだけで、再びリンクをクリックしたタイミングで同一のIDをもつdivやiframeが新たに生成されてしまいます。
単にリンクさせている場合は特に問題なさそうですが、読み込む外部ファイルにアンカーリンクさせていると、アンカーがうまく作動しなくなりました。
なので非表示にさせるタイミングで要素辞自体を一度削除するべきでしょう。



3.定義した処理を呼び出す指示

 //リンクをクリックしたらイベント処理「PopUp」を呼び出し
 $('リンクの要素名')
  .click(PopUp);
 //グレーアウト部分をクリックしたらイベント処理「PopDown」を呼び出し(追加要素へのイベント処理なのでliveメソッド使用)
 $('#gray').live('click',PopDown);
});



リンク文字をクリックした時点、グレーアウトをクリックした時点でそれぞれ定義したイベント処理「PopUp」「PopDown」を呼び出します。
#grayはHTMLのほうにある要素ではなく、jQueryの処理の中で新たに生成・追加した要素なのでliveメソッドを使っています。
このliveメソッドを適用させるタイミングがいまいちわかっておりません。うーん。


---------------------------------------------------------------------------

ざっとこんな感じでした。
HTMLでのリンクで外部ファイルにアンカーリンクを設定していて、removeさせるという考えが全くなく、アンカーが全く効かなくて頭をひねりまくりました。
removeが必要な理由を上で考察しましたが、その理由が正解なのかはわかりません笑

それにiframeを囲むdivも本当に必要だったのか?
iframe要素だけでは成り立たないのか、検証してません。もしかしたら必要ないかもしれません。

いろいろと詰めの甘いソースですが、現在の自分が組めたのはこんなものでした。

0 件のコメント:

コメントを投稿