javascriptでクイズやテスト勉強に便利な問題作成できるものを作成しました

2022年4月15日

テスト勉強やクイズを自分でできるように、以下を作りました。

ボタンを押したら、黒塗りがはがれるます。
テキストも変更でき、テスト勉強などの暗記に使えると思います。

CSV形式(○○,○○)の時は「,」の右側が隠され、CSV形式じゃない時は文章の途中に[]があればその部分が黒塗りになります。
最大10問(10行)作成できます。

CSSとJavascriptのソースは以下です。

<style>
#anki {
  font-size: 1.75em;
  font-weight: bold;
  padding: .25em .5em;
  line-height: 1.2;
}
#anki .qa {
  font-size: .75em;
  border: 1px dashed gray;
  padding: .125em .25em;
  margin: 0 0 .5em 0;
}
#anki .qa p {
  margin: 0 0 .125em 0;
  padding: 0;
  line-height: 1.2;
}
#anki .qa p:last-child {
  margin-bottom: 0;
}
#anki .anki_btn button {
  font-size: .625em;
  font-weight: bold;
  padding: .125em .5em;
  margin: .125em .75em 0 0;
}
#anki textarea {
  font-size: 1em;
  font-weight: bold;
  width: 100%;
  display: block;
  margin: 0 0 .125em 0;
  line-height: 1;
}
#anki span {
  display: inline-block;
  padding: 0;
  margin: 0;
}
#anki span.yohaku {
  margin: 0 .25em;
}
#anki span.hide {
  background-color: #000;
  position: relative;
  padding: 0 .25em;
  margin: 0 .25em;
}
#anki p.hide {
  background-color: #000;
  position: relative;
}
#anki .hide::before {
  content: '';
  position: absolute;
  border: .62em solid #000;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
</style>
<div id="anki"></div>
<script>
"use strict";
function makeQA(id) {
  const d = document.getElementById(id);
  const cHide = "hide";
  const cBtn = "anki_btn";
  const cQa = "qa";
  const cYohaku = "yohaku";
  let bkupTxt = "";
  
  init();
  
  function init() {
    d.innerHTML = '';
    
    let textarea = document.createElement("textarea");
    textarea.maxLength = 500;
    textarea.rows = 10;
    textarea.value = bkupTxt;
    d.appendChild(textarea);
    ajastTxtareaHeight(textarea);
    textarea.focus();
    
    let btnDiv = document.createElement("div");
    btnDiv.setAttribute("class",cBtn);
    
    let btn = document.createElement("button");
    btn.innerHTML = 'スタート';
    btn.onclick = function() {
      startQA();
    }
    btnDiv.appendChild(btn);
    d.appendChild(btnDiv);
  }
  function startQA () {
    let t = document.getElementsByTagName("textarea")[0];
    let txt = t.value.trim();
    t.value = txt;
    if (txt === "") {
      alert("入力してください。");
      t.focus();
      return;
    }
    if (txt.length > 500) {
      alert("500文字以上は入力できません。");
      t.focus();
      return;
    }
    
    let qas = txt.split("\n");
    if (qas.length > 10) {
      alert("10行以上は入力できません。");
      t.focus();
      return;
    }
    bkupTxt = txt;
    setQA(qas);
  }
  function setQA (qas) {
    d.innerHTML = '';
    
    for (let i = 0; i < qas.length; i++) {
      let qa = qas[i].trim();
      if (qa.length === 0) {
        continue;
      }
      let div = document.createElement("div");
      div.setAttribute("class",cQa);
      
      let indexComma = qa.indexOf(',');
      if (indexComma > 0 && qa.length > 1) {
        // QA形式
        let q = qa.substr(0, indexComma);
        let a = qa.substr(indexComma + 1);
        let p1 = document.createElement("p");
        let p2 = document.createElement("p");
        p1.textContent = q;
        p2.textContent = a;
        p2.setAttribute("class",cHide);
        
        div.appendChild(p1);
        div.appendChild(p2);
      } else {
        let p = document.createElement("p");
        let indexBrackets = qa.indexOf('[');
        if (indexBrackets === -1) {
          // 全隠し
          p.setAttribute("class",cHide);
          p.textContent = qa;
        } else {
          // []の部分のみ隠す
          let arrTxt = qa.split('');
          let tmp = [], x = 0;
          tmp[0] = "";
          for (let i = 0; i < arrTxt.length; i++) {
            let c = arrTxt[i];
            if (c === "[" || c === "]") {
              x++;
              tmp[x] = "";
            }
            else {
              tmp[x] = tmp[x] + c;
            }
          }
          for (let i = 0; i < tmp.length; i++) {
            let sp = document.createElement("span");
            if(i % 2 !== 0) {
              sp.setAttribute("class",cHide);
            }
            sp.textContent = tmp[i];
            p.appendChild(sp);
          }
        }
        div.appendChild(p);
      }
      
      let p_btn = document.createElement("p");
      p_btn.setAttribute("class",cBtn);
      
      let btnOpen = document.createElement("button");
      btnOpen.innerHTML = '開く';
      btnOpen.onclick = function() {
        removeHideClass(this);
      }
      p_btn.appendChild(btnOpen);
      div.appendChild(p_btn);
      
      d.appendChild(div);
    }
    
    let div_btn = document.createElement("div");
    div_btn.setAttribute("class",cBtn);
    
    let btnReset = document.createElement("button");
    btnReset.innerHTML = 'テキストを変更する';
    btnReset.onclick = function() {
      init();
    }
    div_btn.appendChild(btnReset);
    
    d.appendChild(div_btn);
  }
  function setTxt (txt) {
    if ( ! txt) {
      return;
    }
    let t = document.getElementsByTagName("textarea")[0];
    if (t !== undefined) {
      t.value = txt;
      ajastTxtareaHeight(t);
    }
  }
  function removeHideClass (btn) {
    let el = btn.parentNode.previousElementSibling;
    if (! el) {
      return;
    }
    if (el.classList.contains(cHide)) {
      el.classList.remove(cHide);
    } else {
      let tags = el.getElementsByTagName('span') ,tag;
      for (let i = 0; i < tags.length; i++) {
        tag = tags[i];
        if (tag.classList.contains(cHide)) {
          tag.classList.remove(cHide);
          tag.classList.add(cYohaku);
        }
      }
    }
  }
  function ajastTxtareaHeight (textarea) {
    if ( textarea.scrollHeight > textarea.clientHeight ) {
     textarea.style.height = (textarea.scrollHeight + 12) + 'px';
    }
  }
  return {
    setTxt: function (txt) {
      setTxt(txt);
    },
    startQA: function () {
      startQA();
    }
  };
}

let qanda = makeQA("anki");
let data = "attend,世話をする、出席する、注意する\n"
         + "past,過去\n"
         + "faith,信頼、信仰\n"
         + "全部隠し\n"
         + "江戸幕府の3代目の将軍は?,徳川家光\n"
         + "[鶏口]となるも[牛後]となるなかれ\n"
         + "台形の面積の公式は?,(上底+下底)×高さ÷2\n"
         + "鉄の元素記号は?,Fe\n"
         + "「切磋琢磨 」の読み方,せっさたくま\n"
         + "(12×[5]+7)×8 = 536";
qanda.setTxt(data);
qanda.startQA();
</script>

同様な感じで文章を黒塗りにできるのも作りましたので、よろしければ以下も確認してください。