javascriptでDOMの一部を差し替える


経緯

多言語サイトの年齢認証モーダルで、モーダルの内容を選んだ言語に合わせて内容が変わるものが必要になった。
ブラウザ設定言語によって初回ロード時は各言語に振り分けしてるが、モーダル内の言語選択でも内容が変わらないとおかしいよねwww
プロマネに言われるまで気づかなかった(爆)

姑息な方法として各言語の内容をCLASSでONOFFすれば良いが、個人的に嫌というかダサいので違う方法を模索。
結果、以下の方法で実装することとした。

実装

デフォルト表示させるスタティックなHTMLを用意する

私は日本語をデフォルト表示とした。
jsによってID[modal]の内容が差し替わります。

default.haml
#modal
  %h1 こんにちは!
  %ul{onclick: 'loadModal(event)'}
    %li{data:{lang: 'en'}} EN
    %li.active{data:{lang: 'ja'}} JA
    %li{data:{lang: 'zh'}} ZH
    %li{data:{lang: 'fr'}} FR

各言語切り替え用モーダル部品を用意する

lang_ja.html
<h1>こんにちは!</h1>
<ul onclick='loadModal(event)'>
  <li data-lang='en'>EN</li>
  <li class='active' data-lang='ja'>JA</li>
  <li data-lang='zh'>ZH</li>
  <li data-lang='fr'>FR</li>
</ul>

lang_en.html
<h1>Hello!</h1>
<ul onclick='loadModal(event)'>
  <li class='active' data-lang-type='en'>EN</li>
  <li data-lang='ja'>JA</li>
  <li data-lang='zh'>ZH</li>
  <li data-lang='fr'>FR</li>
</ul>

lang_fr.html
<h1>Bonjour!</h1>
<ul onclick='loadModal(event)'>
  <li data-lang='en'>EN</li>
  <li data-lang='ja'>JA</li>
  <li data-lang='zh'>ZH</li>
  <li class='active' data-lang='fr'>FR</li>
</ul>

lang_zh.html
<h1>您好!</h1>
<ul onclick='loadModal(event)'>
  <li data-lang='en'>EN</li>
  <li data-lang='ja'>JA</li>
  <li class='active' data-lang='zh'>ZH</li>
  <li data-lang='fr'>FR</li>
</ul>

JS

クリックイベントでdata属性の値を取得し、その値を利用してロードするhtmlを制御します。

sample.js
function loadModal(e){
  var lang = e.target.getAttribute('data-lang');
  XHR = new XMLHttpRequest();
  XHR.onreadystatechange = checkingStatus;
  XHR.open("GET", "/modal_" + lang + ".html", true);
  XHR.send(null);
};
function checkingStatus(){
  if (XHR.readyState == 4 && XHR.status == 200){
    var target = document.getElementById("modal");
    target.innerHTML = XHR.responseText;
  }
}

CSS

簡易的なものなのでご自由に

sample.scss
#modal{
  width: 300px;
  box-sizing: border-box;
  color: #FFF;
  background-color: #000;
  border-radius: 5px;
  padding: 40px 20px;
  margin: 100px auto 0;
  h1{
    font-size: 30px;
    text-align: center;
    margin-bottom: 20px;
  }
  ul{
    display: flex;
    justify-content: space-around;
    li{
      display: inline-block;
      color: #B7B7B7;
      cursor: pointer;
      &.active{
        color: #FFF;
      }
    }
  }
}

こんなかんじ