Tilesの自動生成

Bulma Tiles are created automatically

タイルのレイアウト Layout: Tiles

Javascript を使って、Tilesを自動生成します。

並び方パターン: 0000000
並び方パターン: 0000000

上記のソースコード

<!-- tilesLayout$$.html -->

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <title>Bulma Project Javascript Tiles</title>
    <meta name="description" content="Bulma Tiles are created automatically" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />

    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css"
    />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bulma-extensions@6.2.7/dist/css/bulma-extensions.min.css"
    />

    <link
      rel="icon"
      type="image/png"
      href="/assets/img/favicon-c2.png"
      sizes="16x16"
    />

    <script
      defer
      src="https://use.fontawesome.com/releases/v5.7.1/js/all.js"
    ></script>

    <script src="/src/js/shortBulma$$.js"></script>
    <!-- <script src="../../js/shortBulma$$.js"></script> -->

    <style>
      .box {
        min-height: 50px;
      }

      .box-max {
        min-height: 200px;
      }
    </style>
  </head>

  <body>
    <section class="section">
      <div class="container">
        <div class="columns is-mobile has-background-white-bis">
          <div class="column"></div>
          <div class="column is-8 content">
            <article class="message is-primary">
              <div class="message-header">
                <p>タイルのレイアウト Layout: Tiles</p>
              </div>

              <div
                class="message-body has-background-white-bis"
                style="border-bottom: inset 2px #aaaa88"
              >
                <p>
                  <strong>Javascript</strong>
                  を使って、Tilesを自動生成します。
                </p>
              </div>
            </article>

            <main>
              <form>
                <!--  -->
                <div class="box mb-2 py-2">
                  <nav class="level">
                    <div class="level-item mb-3">
                      <div class="field">
                        <!-- <div class="field is-grouped"> -->
                        <label class="label" title="count of tiles">枚数</label>
                        <div class="control">
                          <div class="select">
                            <select id="sel">
                              <option value="3">3</option>
                              <option value="4">4</option>
                              <option value="5">5</option>
                              <option value="6">6</option>
                              <option value="7">7</option>
                              <option value="8">8</option>
                              <option value="9">9</option>
                              <option value="10">10</option>
                              <option value="11">11</option>
                              <option value="12">12</option>
                            </select>
                          </div>
                        </div>
                      </div>
                    </div>

                    <div class="field mt-3">
                      <div class="control" id="rGroup">
                        <input
                          type="radio"
                          class="is-checkradio"
                          id="rad1"
                          name="question"
                          value="1"
                        />
                        <label for="rad1" class="radio" title="ascending"
                          >昇順
                        </label>

                        <input
                          type="radio"
                          class="is-checkradio"
                          id="rad2"
                          name="question"
                          value="2"
                        />
                        <label for="rad2" class="radio" title="random order"
                          >ランダム
                        </label>

                        <input
                          type="radio"
                          class="is-checkradio"
                          id="rad3"
                          name="question"
                          value="3"
                        />
                        <label for="rad3" class="radio" title="descending"
                          >降順
                        </label>
                      </div>
                    </div>

                    <div class="level-item">
                      <div class="field">
                        <div class="control">
                          <button
                            id="refresh"
                            class="button is-medium is-danger is-light mt-4 mb-3"
                            title="update button"
                          >
                            更新
                          </button>
                        </div>
                      </div>
                    </div>
                  </nav>
                </div>
              </form>

              <div class="box">
                <div
                  class="has-text-centered mb-5 has-text-grey-dark"
                  title="layout pattern"
                >
                  並び方パターン:
                  <span
                    id="pat1"
                    class="has-text-primary-dark has-text-weight-semibold is-size-5"
                  ></span>
                </div>

                <!-- // Ancestor -->
                <div class="tile is-ancestor is-mobile">
                  <div class="tile is-parent">
                    <div class="tile is-child box"></div>
                  </div>
                  <div class="tile is-parent">
                    <div class="tile is-child box"></div>
                  </div>
                </div>

                <template id="t0">
                  <div class="tile is-parent">
                    <div class="tile is-child box"></div>
                  </div>
                </template>

                <template id="t1">
                  <div class="tile">
                    <div class="tile is-parent">
                      <div class="tile is-child box"></div>
                    </div>

                    <div class="tile is-parent">
                      <div class="tile is-child box"></div>
                    </div>
                  </div>
                </template>

                <div
                  class="has-text-centered mb-2 has-text-grey-dark"
                  title="layout pattern"
                >
                  並び方パターン:
                  <span
                    id="pat2"
                    class="has-text-primary-dark has-text-weight-semibold is-size-5"
                  ></span>
                </div>
              </div>
            </main>

            <div class="box">
              <div class="box">
                <h2 class="is-size-4 has-background-white-ter p-2 km">解説</h2>
                <div class="content">
                  <ul>
                    <li>
                      Tilesにも
                      <span class="has-text-danger-dark">is-mobile</span
                      >等が機能すると面白いのですが。
                    </li>
                    <li>
                      BulmaでJavascriptを利用するために、このWebサイトでは<br />
                       <a href="shortBulma.html"
                        ><strong>shortBulma$$.js</strong> または
                        <strong>shortBulma.js</strong></a
                      ><br />
                      というライブラリを使います。
                    </li>
                    <li class="pt-2">
                      使い方の例:&lt;script
                      src=&quot;/src/js/shortBulma$$.js&quot;&gt;&lt;/script&gt;<br />
                      headタグ内に挿入。但し、pathは状況によって変わります。
                    </li>
                    <li class="pt-2">
                      上記のpathの設定の確認をしておいてください。
                      <p class="pt-3 px-3">
                        例えば、notification$$.htmlとshortBulma$$.jsが同じフォルダにある時は<br />
                        &lt;script
                        src=&quot;./shortBulma$$.js&quot;&gt;&lt;/script&gt;
                        または<br />
                        &lt;script
                        src=&quot;shortBulma$$.js&quot;&gt;&lt;/script&gt;
                        となります。
                      </p>
                    </li>
                    <li>
                      より詳しくは<a href="shortBulma.html"
                        ><strong> shortBulma$$.js </strong> </a
                      >をご覧ください。
                    </li>
                    <hr />

                    <li class="pt-1">
                      <dl>
                        <dt>$$de = (f) => { ...'DOMContentLoaded', f)</dt>
                        <dd class="py-2">ロード時にイベントリスナーfを設定</dd>
                        <dt>$$qAll('div.tile')</dt>
                        <dd class="py-2">
                          セレクター'div.tile'を持つ全ての要素を取得
                        </dd>
                        <dt>$$qe('#sel', f)</dt>
                        <dd class="py-2">
                          セレクター'#sel'を持つ要素にイベントリスナーfを設定
                        </dd>
                        <dt>$$qAe('#rGroup input', f)</dt>
                        <dd class="py-2">
                          セレクター'#rGroup
                          input'を持つ全ての要素にイベントリスナーfを設定
                        </dd>
                        <dt>$$Id('#sel')</dt>
                        <dd class="py-2">idが'sel'である要素を取得</dd>
                        <dt>$$ocL(o, cL, 'add')</dt>
                        <dd class="py-2">要素oのクラスリストに、cLを追加</dd>
                        <dt>$$oqAll(o, 'div.traceF')</dt>
                        <dd class="py-2">
                          要素oの子孫で、セレクター'div.traceF'を持つ全ての要素を取得
                        </dd>
                        <dt>$$DF()</dt>
                        <dd class="py-2">DocumentFragmentを作成</dd>
                        <dt>$$tCc('t0')</dt>
                        <dd class="py-2">
                          idが't0'であるテンプレート要素からクローンを作成します。(複製)
                        </dd>
                      </dl>
                    </li>
                  </ul>
                </div>
              </div>
              <hr />
            </div>
          </div>
          <div class="column"></div>
        </div>
      </div>
    </section>

    <!-- <script src="/src/sub/js/bgColors.js"></script> -->
    <!-- <script src="bgColors.js"></script> -->

    <script type="text/javascript">
      let tilesN = 9;
      let patternNo = 3; // '00000000'; // 降順
      let patternSS;
      let lastANode = null;

      const bgColors = [
        'has-background-primary',
        'has-background-info',
        'has-background-success',
        'has-background-warning',
        'has-background-danger',
        'has-background-primary-dark',
        'has-background-success-dark',
        'has-background-warning-dark',
        'has-background-danger-dark',
      ];

      $$de(() => {
        // 画面初期表示
        $$Id('#sel').value = tilesN;
        $$Id('#rGroup').children[2 * patternNo - 2].checked = true;
        // tree生成 {色・ランダム}
        update();

        // event ~~~
        $$qe('#sel', (e) => (tilesN = e.target.value), 'change');
        // 重要 tilesN

        $$qAe(
          '#rGroup input',
          (e) => {
            patternNo = +e.target.value;
          },
          'change'
        );

        $$qe('#refresh', (e) => {
          e.target.disabled = true;
          e.preventDefault();

          tilesN = +$$q('#sel').value;
          patternNo = +getRadioValue('question');
          update();
          e.target.disabled = false;
        });
      });

      // functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~

      const update = () => {
        const Ancestor = $$q('.is-ancestor');
        // let stepBss = zeroPadding_2();
        // let stepBss = '00000000'; // 降順
        // let stepBss = '10101010';
        // let stepBss = '01010101';
        // let stepBss = '11111111'; // 昇順

        patternSS = getPattern();
        dispPattern();
        // dummy for a classList.add() trouble
        if (patternSS.charAt(0) === '1') {
          Ancestor.replaceChild(mkF0(), Ancestor.children[1]);
          setColor0(Ancestor.children[1].children[0]);
          Ancestor.replaceChild(mkF(), Ancestor.children[0]);
          // swapTwo(Ancestor);
        } else {
          Ancestor.replaceChild(mkF0(), Ancestor.children[0]);
          setColor0(Ancestor.children[0].children[0]);
          Ancestor.replaceChild(mkF(), Ancestor.children[1]);
        }
      };

      const setColor0 = (o) => {
        $$ocL(o, bgColors[getRNum(bgColors.length)], 'add');
      };

      const getPattern = () => {
        switch (patternNo) {
          case 1:
            return '111111111111111'.slice(-(tilesN - 2)); // 昇順
          case 2:
            return zeroPadding_2();
          case 3:
            return '000000000000000'.slice(-(tilesN - 2)); // 降順
          default:
            console.log('getPattern -> patternNo=1~3', patternNo);
        }
      };

      const dispPattern = () => {
        $$Id('pat1').textContent = patternSS;
        $$Id('pat2').textContent = patternSS;
      };

      const swapTwo = (parent) => {
        let child1 = parent.firstElementChild;
        let child2 = child1.nextElementSibling;
        if (!child1 || !child2) {
          throw new Error("Can't get child!");
        }

        parent.insertBefore(child2, child1); // 置換
      };

      const mkF0 = () => {
        // dummy
        if (tilesN <= 2) return null;

        let DF0 = $$DF(); // new DocumentFragment()
        let tCc = $$tCc('t0'); // document.importNode($$tC(id), b)
        DF0.appendChild(tCc);
        return DF0;
      };

      const mkF = () => {
        if (tilesN <= 2) return null;

        let DF = $$DF(); // new DocumentFragment()
        let traceTile = null;

        for (step = 2; step <= tilesN - 1; step++) {
          // setup tCclone
          const tCclone = $$tCc('t1'); // document.importNode($$tC(id), b)
          const cloneTop = tCclone.firstElementChild;

          if (step % 2 === 0) cloneTop.classList.add('is-vertical');

          const i = patternSS.charAt(step - 2) === '1' ? 1 : 0;

          setColor0(cloneTop.children[0].firstElementChild);
          setColor0(cloneTop.children[1].firstElementChild);
          $$ocL(cloneTop.children[1 - i], 'anchorF');
          if (step === tilesN - 1) {
            setColor0(cloneTop.children[1 - i].firstElementChild);
          }
          if (step === 2) {
            DF.appendChild(tCclone);
            traceTile = DF.firstElementChild;
          } else {
            traceTile.replaceChild(tCclone, traceTile.children[1 - i]);
            traceTile = traceTile.children[1 - i];
          }
          $$ocL(traceTile, 'traceF');
        }
        return DF;
      };

      const getTraceTile = (o) => {
        let tiles = $$oqAll(o, 'div.traceF');
        console.log('getTraceTile -> tiles.length - 1', tiles.length - 1);
        return tiles[tiles.length - 1];
      };

      const setColor = () => {
        let tiles = $$qAll('div.tile');

        let i = 0;
        tiles.forEach((t) => {
          const x = bgColors[getRNum(bgColors.length)];
          if (i === tiles.length - 1) {
            $$ocL(t, x, 'add');
            return;
          }

          if (i % 3 === 2) {
            $$ocL(t, x, 'add');
            // if (i <= 5) console.log('setColor -> x', x);
          }
          i++;
        });
      };

      const getRNum = (n) => {
        return Math.floor(Math.random() * n);
      };

      const zeroPadding = (num, length) => {
        return ('000000000000000' + num.toString(2)).slice(-length);
      };

      const zeroPadding_2 = () => {
        const steps = tilesN - 1;
        const rnd = Math.floor(Math.pow(2, steps) * Math.random());
        return ('000000000000000' + rnd.toString(2)).slice(-(steps - 1));
      };

      const getRadioValue = (na) => {
        let ret = '';

        $$na(na).forEach((elm) => {
          if (elm.checked) {
            ret = elm.value;
          }
        });
        return ret;
      };
    </script>
  </body>
</html>

解説

  • Tilesにも is-mobile等が機能すると面白いのですが。
  • BulmaでJavascriptを利用するために、このWebサイトでは
     shortBulma$$.js または shortBulma.js
    というライブラリを使います。
  • 使い方の例:<script src="/src/js/shortBulma$$.js"></script>
    headタグ内に挿入。但し、pathは状況によって変わります。
  • 上記のpathの設定の確認をしておいてください。

    例えば、TilesLayout$$.htmlとshortBulma$$.jsが同じフォルダにある時は
    <script src="./shortBulma$$.js"></script> または
    <script src="shortBulma$$.js"></script> となります。

  • より詳しくは shortBulma$$.js をご覧ください。

  • $$de = (f) => { ...'DOMContentLoaded', f)
    ロード時にイベントリスナーfを設定
    $$qAll('div.tile')
    セレクター'div.tile'を持つ全ての要素を取得
    $$qe('#sel', f)
    セレクター'#sel'を持つ要素にイベントリスナーfを設定
    $$qAe('#rGroup input', f)
    セレクター'#rGroup input'を持つ全ての要素にイベントリスナーfを設定
    $$Id('#sel')
    idが'sel'である要素を取得
    $$ocL(o, cL, 'add')
    要素oのクラスリストに、cLを追加
    $$oqAll(o, 'div.traceF')
    要素oの子孫で、セレクター'div.traceF'を持つ全ての要素を取得
    $$DF()
    DocumentFragmentを作成
    $$tCc('t0')
    idが't0'であるテンプレート要素からクローンを作成します。(複製)