もりけん塾 JavaScript課題13 モーダルの表示とリクエスト送信の実装

もりけん塾 JavaScript課題13 モーダルの表示とリクエスト送信の実装

課題13は、課題12の続きで、12で作ったボタンをクリックしたらモーダルウィンドウが開き、リクエスト送信できるようにします。

課題12の学習記録は、こちら↓

お題

クリックしたらモーダルが出てきて、12で作ったボタンを押したらリクエストされ表示するようにしてください

最初のコード

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="stylesheet" href="reset.css" type="text/css" />
    <link rel="stylesheet" href="style.css" type="text/css" />
    <script src="script.js" defer></script>
    <title>JavaScript課題13 モーダルウィンドウの表示</title>
  </head>
  <body>
    <ul id="js-list"></ul>
    <button type="button" id="js-open-btn" class="btn">Click</button>
    <div id="js-modal" class="modal">
      <div class="modal-content">
          <div class="close-btn" id="js-close-btn">
            <img src="img/xmark-solid.svg" alt="クローズボタン">
          </div>
          <button type="button" id="js-request-btn" class="btn">Request</button>
      </div>
    </div>
  </body>
</html>
function showLoadingImg(){
    const div = document.createElement('div');
    const loadingImg = document.createElement('img');
    div.id = "js-loading";
    loadingImg.src = "img/loading-circle.gif";
    loadingImg.alt = "ローディング画像";
    document.body.insertAdjacentElement('afterbegin',div).appendChild(loadingImg);
}

function removeLoadingImg(){
    document.getElementById('js-loading').remove();
}

async function fetchdata(){
    const endpoint = "https://api.json-generator.com/templates/szdgGQcOLXuk/data?access_token=hu4bc7qh9znx2m8f53mn4mz2hryvdntkavwbw8j0";
    const response = await fetch(endpoint);
    //responseがokではないとき
    if(!response.ok){
    throw new Error(`${response.status}:${response.text}`);
   const json = await response.json();
    const data = await json.data;
    return data;
}

function renderList(result) {
    const fragment = document.createDocumentFragment();
    const ul = document.getElementById('js-list');
        for(const list of result){
            const li = document.createElement('li');
            const a = document.createElement('a');
            const img = document.createElement('img');
            a.textContent = list.text;
            a.href = `/${list.a}`;
            img.src = list.img;
            img.alt = list.alt;
            fragment.appendChild(li).appendChild(a).insertAdjacentElement('afterbegin',img);
        }
    ul.appendChild(fragment);
}

async function init(){
    showLoadingImg();
    try{
        const result = await fetchdata();
        //resultがtrueではないとき
        if (!result) {
            return;
        }
        renderList(result);
    }catch(e){
        document.getElementById('js-list').textContent = e;
        console.error(e);
    }finally{
        removeLoadingImg();
    }
}

function modalWindow(){
    const modal = document.getElementById('js-modal');
    const openButton = document.getElementById('js-open-btn');
    const closeButton = document.getElementById('js-close-btn');
    const requestButton = document.getElementById('js-request-btn');

    openButton.addEventListener('click',function(){
        modal.classList.add('is-show');
        openButton.classList.add('is-deactive');
    },false);

    closeButton.addEventListener('click',function(){
        modal.classList.remove('is-show');
        openButton.classList.remove('is-deactive');
    },false);

    requestButton.addEventListener('click', function(){
        modal.classList.remove('is-show');
        init();
    },false);
}

modalWindow();

レビューは、もなかさんはるさんにして頂きました!ありがとうございます。

JavaScript用のidをCSSでも使っていたため、CSS用のclassをつけた方が良いというご指摘をいただき、HTMLに下記のようなclassを追加しました。

    <title>JavaScript課題13 モーダルウィンドウの表示</title>
  </head>
  <body>
    <ul id="js-list"></ul>
    <ul id="js-list" class="list"></ul>
    <button type="button" id="js-open-btn" class="btn open-btn">Click</button>
    <div id="js-modal" class="modal">
      <div class="modal-content">

JavScriptで作るDOMにもclassNameで、classを付与。


    for(const list of result){
            const li = document.createElement('li');
            li.className = "list-item";

コードを読めばわかるような必要のないコメントを書いていたので、こちらも削除した方がいいのでは、と勧められました。

    //responseがokではないとき
    if(!response.ok){
    throw new Error(`${response.status}:${response.text}`);
    }
    //responseがokのとき

また、関数名に動詞が含まれていなかったため、こちらはMUSTで修正です。悩んだ結果、この関数の中に、複数の処理があり、適切な関数名をつけることができなかったので、処理ごとに関数として分けることにしました。

function modalWindow(){
    const modal = document.getElementById('js-modal');
    const openButton = document.getElementById('js-open-btn');
    const closeButton = document.getElementById('js-close-btn');
    const requestButton = document.getElementById('js-request-btn');

    openButton.addEventListener('click',function(){
        modal.classList.add('is-show');
        openButton.},false);classList.add('is-deactive');
    },false);

    closeButton.addEventListener('click',function(){
        modal.classList.remove('is-show');
        openButton.classList.remove('is-deactive');
    },false);

    requestButton.addEventListener('click', function(){
        modal.classList.remove('is-show');
        init();
    },false);
}
modalWindow();

修正して下記のように切り出しました。

function openModalWindow(){   
    document.getElementById('js-open-btn').addEventListener('click',function(){
        document.getElementById('js-modal').classList.add('is-show');
        this.classList.add('is-deactive');
    },false);

function closeModalWindow(){ 
    document.getElementById('js-close-btn').addEventListener('click',function(){
        document.getElementById('js-modal').classList.remove('is-show');
        document.getElementById('js-open-btn').classList.remove('is-deactive');
    },false);

function requestData(){ 
    document.getElementById('js-request-btn').addEventListener('click', function(){
        document.getElementById('js-modal').classList.remove('is-show');
        init();
    },false);
}
openModalWindow();
closeModalWindow();
requestData();

.addEventListener(‘click’, function()を関数の中に入れていたのですが、それなら、処理とクリックイベントを分けて、下記の形にするのがいいのではないか、とアドバイス頂きました。

長かったコードが、とてもスッキリして見やすくなりました!

function openModalWindow(){   
    modal.classList.add('is-show');
    this.classList.add('is-hide');
}

function closeModalWindow(){ 
    modal.classList.remove('is-show');
    openButton.classList.remove('is-hide');
}

function requestData(){ 
    modal.classList.remove('is-show');
    init();
}

openButton.addEventListener('click',openModalWindow,false);
closeButton.addEventListener('click', closeModalWindow, false);
requestButton.addEventListener('click', requestData, false);

最終的なコード

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="stylesheet" href="reset.css" type="text/css" />
    <link rel="stylesheet" href="style.css" type="text/css" />
    <script src="script.js" defer></script>
    <title>JavaScript課題13 モーダルウィンドウの表示</title>
  </head>
  <body>
    <ul id="js-list" class="list"></ul>
    <button type="button" id="js-open-btn" class="btn open-btn">Click</button>
    <div id="js-modal" class="modal">
      <div class="modal-content">
          <div class="close-btn" id="js-close-btn">
            <img src="img/xmark-solid.svg" alt="クローズボタン">
          </div>
          <button type="button" id="js-request-btn" class="btn">Request</button>
      </div>
    </div>
  </body>
</html>
function showLoadingImg(){
    const div = document.createElement('div');
    const loadingImg = document.createElement('img');
    div.id = "js-loading";
    loadingImg.src = "img/loading-circle.gif";
    loadingImg.alt = "ローディング画像";
    document.body.insertAdjacentElement('afterbegin',div).appendChild(loadingImg);
}

function removeLoadingImg(){
    document.getElementById('js-loading').remove();
}

async function fetchdata(){
    const endpoint = "https://api.json-generator.com/templates/szdgGQcOLXuk/data?access_token=hu4bc7qh9znx2m8f53mn4mz2hryvdntkavwbw8j0";
    const response = await fetch(endpoint);
    if(!response.ok){
    throw new Error(`${response.status}:${response.statusText}`);
    }
    const json = await response.json();
    const data = await json.data;
    return data;
}

function renderList(result) {
    const fragment = document.createDocumentFragment();
    const ul = document.getElementById('js-list');
        for(const list of result){
            const li = document.createElement('li');
            li.className = "list-item";
            const a = document.createElement('a');
            const img = document.createElement('img');
            a.textContent = list.text;
            a.href = `/${list.a}`;
            img.src = list.img;
            img.alt = list.alt;
            fragment.appendChild(li).appendChild(a).insertAdjacentElement('afterbegin',img);
        }
    ul.appendChild(fragment);
}

async function init(){
    showLoadingImg();
    try{
        const result = await fetchdata();
        if (!result) {
            return;
        }
        renderList(result);
    }catch(error){
        document.getElementById('js-list').textContent = error;
        console.error(error);
    }finally{
        removeLoadingImg();
    }
}

const modal = document.getElementById('js-modal');
const openButton = document.getElementById('js-open-btn');
const closeButton = document.getElementById('js-close-btn');
const requestButton = document.getElementById('js-request-btn');

function openModalWindow(){   
    modal.classList.add('is-show');
    this.classList.add('is-hide');
}

function closeModalWindow(){ 
    modal.classList.remove('is-show');
    openButton.classList.remove('is-hide');
}

function requestData(){ 
    modal.classList.remove('is-show');
    init();
}

openButton.addEventListener('click',openModalWindow,false);
closeButton.addEventListener('click', closeModalWindow, false);
requestButton.addEventListener('click', requestData, false);

まだまだ学ぶことが多いのですが、どうやったら実装できるかな?という答えが、導き出せるようになってきました。

次回も頑張ろうと思います!

私が所属しているフロントエンドエンジニアを目指す方のための塾 「もりけん塾」の森田賢二先生のTwitterはこちら!

先生のブログ「武骨日記」はこちら!

https://kenjimorita.jp/

まい

Webサービス制作会社で、Wordpressのテーマ開発や2Dシミュレーターの開発、JavaScriptを使用したフロントエンド周りの実装を担当しています。 JavaScriptが好きです。 最近は、3D Model Configuratorの制作にチャレンジしています。

もりけん塾カテゴリの最新記事