その他
    ホーム技術発信DoRubyクリックをトリガーに$.ajaxで外部htmlを読み込んだり削除したりする

    クリックをトリガーに$.ajaxで外部htmlを読み込んだり削除したりする

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    やりたいこと
    「条件A」なら、A.html、「条件B」なら、B.html
    のように、クリックした要素に応じた外部htmlを読み込み、
    閉じるをクリックしたら外部html部分は削除したい。
    読み込んだり削除したりを繰り返したい。
    呼び出し元・外部htmlどちらでもjsが必要だけど、
    jsファイルがすでにたくさんあるので1つにまとめたい。

    $.ajaxで外部htmlを読み込む

    まず、htmlでトリガーになる部分を作ります。

    <a href="modal_A.html" class="js-modal_trigger">Aを選択</a>
    <a href="modal_B.html" class="js-modal_trigger">Bを選択</a>
    

    今回は読み込んだ後も別の外部htmlを読み込み直したりしたいので、
    $.ajaxを使うことにします。

    $(".js-modal_trigger").click(function(e) {
      e.preventDefault();
      //読み込みたい外部htmlのファイル名を取得
      var href = $(this).attr("href"); 
    
      //読み込んだファイルを展開するdivを作る
      $(this).after("<div class=\"js-modal\"></div>"); 
    
      $.ajax({
        type: 'GET',
        url: href,
        dataType: 'html',
        success: function(data) {
          //取得したhtmlを作成したdivに追加
          $(".js-modal").append(data);
        },
        error: function() {
          alert('問題がありました。');
        }
      });
    });
    

    読み込みたいhtmlが1種類ではないので、urlに入れる値はaタグのhrefから取得しています。
    あと、読み込んだhtmlの展開用の空divが最初からhtml上にあるのも気持ち悪いので、
    クリックのタイミングで毎回作ることにしました。

    .remove()で要素を削除する

    読み込みができたので、今度は閉じるをクリックしたら外部html部分を削除する部分を作ります。

    <div class="js-modal_close">閉じる</div>
    

    htmlを用意して、読み込まれた部分を削除するjsを追加。

    $(".js-modal_close").click(function() {
      $(".js-modal").remove();
    });
    

    .js-modal_closeが読み込んだ外部htmlの中にある場合、
    呼び出し元のページで上記のjsを読み込んでいても、このままでは動きません。
    なので、これをfunctionにします。

    function modalClose() {
      $(".js-modal_close").click(function() {
        $(".js-modal").remove();
      });
    });
    

    このfunctionを外部htmlを読み込んだ後に実行します。

    $(".js-modal_trigger").click(function(e) {
      e.preventDefault();
      //読み込みたい外部htmlのファイル名を取得
      var href = $(this).attr("href"); 
    
      //読み込んだファイルを展開するdivを作る
      $(this).after("<div class=\"js-modal\"></div>"); 
    
      $.ajax({
        type: 'GET',
        url: href,
        dataType: 'html',
        success: function(data) {
          //取得したhtmlを作成したdivに追加
          $(".js-modal").append(data);
          modalClose(); //閉じる
        },
        error: function() {
          alert('問題がありました。');
        }
      });
    });
    

    閉じる以外にも、外部htmlでjsを実行したい場合は、
    同じように関数にして読み込むと良さそうです。

    番外:どんどん増殖する外部html

    最初、何も考えずに外部htmlの中でjsファイルを読みこませて動かしてみたところ、
    1回目のクリック…読み込み、削除問題なし。
    2回目のクリック…外部htmlの要素が2回読み込まれる。
    3回目のクリック…外部htmlの要素が4回読み込まれる。

    明らかにおかしい。
    クリックのイベントがいけないのかと思い、
    試しにページロード時に外部htmlを読むようにしてみようと
    ちょっと書き換えました。

    $(".js-modal_trigger").each(function(e) {
      e.preventDefault();
      //読み込みたい外部htmlのファイル名を取得
      var href = $(this).attr("href"); 
    
      //読み込んだファイルを展開するdivを作る
      $(this).after("<div class=\"js-modal\"></div>"); 
    
      $.ajax({
        type: 'GET',
        url: href,
        dataType: 'html',
        success: function(data) {
          //取得したhtmlを作成したdivに追加
          $(".js-modal").append(data);
        },
        error: function() {
          alert('問題がありました。');
        }
      });
    });
    

    その結果、<div class=”js-modal”></div>を生成し、外部htmlを取り込む処理を
    ひたすらループし続ける悲劇が…
    止まらないのでブラウザを強制終了。
    ちなみに、.load()でも同じように無限ループが発生しました。
    面倒なんて言わずに、最初からおとなしくfunctionにしておけばよかったのです…

    教訓
    同じjsファイルを再読み込みするのは良くない。