JavaScriptでTextileのCollapse
2020/10/29
RedmineのWikiでCollapseを使っている
  • Redmineはメジャーなプロジェクト管理ツールです。その情報共有の一手段としてWikiを持っていますが、このRedmine Wikiの便利マクロとして collapse があります。

  • collapse は表示を折りたたむことで隠すことができる機能です。表示の部分をクリックすれば、折りたたんでいた部分が表示され、再度クリックするとまた隠れます。

  • この必要に応じて表示する機能は「文書の構造化」に利用できるので、とても便利なのです。

作りたいのは一問一答式問題集のようなコンテンツ
  • 話は変わりますが、昔から暗記物が苦手だった私は、子供の頃特に社会のテストで苦しみました。全く覚えられない...と困り果てていたわけですが、ある時「一問一答式」の問題集を見つけ、これで何とかしていました。私にとって「暗記」とは「一問一答式」と言っても過言ではありません。(*1)

  • 一問一答式の問題集は、ページの中央に縦線があり、左側に問題/右側に回答が書かれています。そして回答側を付属の「しおり」で隠しながら問題を読み、即座に答え合わせするわけです。

  • この「問題を読んでいるときは隠し、答えはすぐに表示できる」という構造化された文書をHTMLで作れば、暗記物コンテンツも電子化しやすいわけですね。これをJavaScriptでやろうとしています。

    問題1:
    ---------------------
    ...
    回答1:
             
             
    →回答確認→ 問題1:
    ---------------------
    ...
    回答1:
     〜回答現れる〜
             
    Figure 1: 一問一答式コンテンツのイメージ

display と visibility
  • HTMLでドキュメントの要素を指定するタグとして下記があります。
    • ブロック要素
      • <p>〜</p>
      • <div>〜</div>
    • インライン要素
      • <span>〜</span>

  • これらのタグのstyleプロパティである displayvisibility をJavaScriptから操作することで、表示/非表示を切り替えることができます。

  • まず display の例です。下の「display」ボタンをクリックしてみて下さい。
    • 下の表示が切り替わりましたでしょうか。
      文書が差し込まれるように現れたと思います。
      もう一度displayボタンを押すと戻ります。

  • 具体的には下記のような記述になっています。onclickで、JavaScripの関数toggleDisplayに表示を切り替えたい要素のid(s0)を与えています。toggleDisplay関数内では、指定されたidのdisplayプロパティをblock ↔ noneの間で切り替えています。
    <input type='button' value='display' onclick=toggleDisplay('s0')>
    <span id='s0'>
      <ul>
        <li>
          下の表示が切り替わりましたでしょうか。<br>
          文書が<b>差し込まれるように現れた</b>と思います。<br>
          もう一度displayボタンを押すと戻ります。
        </li>
      </ul>
    </span>
    
    <script>
      // 表示初期設定
      document.getElementById('s0').style.display = 'none'; 
      
      // display property toggle切り替え
      function toggleDisplay(obj_id) {
          const doc_ele = document.getElementById(obj_id);
          
          if (doc_ele.style.display == 'block') {
              doc_ele.style.display = 'none';  // 非表示
          } else {
              doc_ele.style.display = 'block'; // 表示
          }
      }
    </script>

  • 次は visibility の例です。下の「visibility」ボタンをクリックしてみて下さい。(何かスペースが空いていますね...)
    • 下の表示が切り替わりましたでしょうか。
      次は空いていたスペースに表示が現れたと思います。
      もう一度visibilityボタンを押すと戻ります。

  • こちらは下記のような記述です。onclickで、JavaScripの関数toggleVisibilityに表示を切り替えたい要素のid(s1)を与えています。toggleVisibility関数内では、指定されたidのvisibilityプロパティをvisible ↔ hiddenの間で切り替えています。
    <input type='button' value='visibility' onclick=toggleVisibility('s1')>
    <span id='s1'>
      <ul>
        <li>
          下の表示が切り替わりましたでしょうか。<br>
          次は<b>空いていたスペースに表示が現れた</b>と思います。<br>
          もう一度visibilityボタンを押すと戻ります。
        </li>
      </ul>
    </span>
    
    <script>
      // 表示初期設定
      document.getElementById('s1').style.visibility = 'hidden';
      
      // visibility property toggle切り替え
      function toggleVisibility(obj_id) {
          const doc_ele = document.getElementById(obj_id);
          
          if (doc_ele.style.visibility == 'visible') {
              doc_ele.style.visibility = 'hidden';  // 非表示
          } else {
              doc_ele.style.visibility = 'visible'; // 表示
          }
      }
    </script>
    

要素が多い場合の表示初期化
  • JavaScript関数のid値を渡すonlick attributeは、<input>, <img>, <a> 等で指定できるので、表示/非表示のスイッチは画像なり文字列なり好きなものを使えば良いと思います。

  • そして関数は汎用化できているので、問題は初期化の記述になります。表示/非表示切り替え要素が増えてきた場合、下記記述は非常に面倒です。
        document.getElementById('s0').style.display = 'none'; 
        document.getElementById('s1').style.display = 'none'; 
        ...
  • せめて、要素id名の付け方にルールを付けて総数だけ管理すれば、下記が可能でしょう。例では 's0'〜's49'の要素についてdisplayプロパティを初期化します。
    <script>
      let ele_total = 50;  // Total要素数
      let id_name;         // id名を受ける変数
      
      for (let i=0; i<ele_total; i++) {
        id_name = 's' + i; // 's'は要素idの接頭辞として決めたもの。<span>から来ている。
        document.getElementById(id_name).style.display = 'none';
      }
    </script>

  • JavaScriptの表示/非表示切り替えをシンプルにできそうなので、機会あればコンテンツに適用したいと思います。
Notes
  • もし無かったらと思うと...恐ろしい。考えたくもない。
Copyright(C) 2020 Altmo
本HPについて