テーブルを弄る。たぶんその3

以前、オブジェクト指向のコードの書き方で、「移譲しまくる」というのを思い出しました。
WAI-AREA の弄り方も勉強ならず…。


仕様を大幅に変更して、tbody の番号(no)が指定されていないと、
各tbodyに対して、それぞれの操作するようにしました。
(この方が現実的かな〜。)


(横長のモニターを縦にして使いたくなります。 (^^;
 やるなら、縦に2段。見上げればモニターが…。
 ある意味、それが理想っぽい環境。)

呼び出しに、いちいち getTBody.call (this, no) を渡すのは意味がない。
検討中。

<!DOCTYPE html>
<title></title>

<style type="text/css">
tr[aria-hidden="true"] {
  visibility: collapse;
}

table, td, th {
  border: 1px #bbb solid;
}
</style>

<form>
  <p>
    <select onchange="table && table.find(new RegExp( this.value ), 1)">
      <option value="">-
      <option value="岩手">岩手県
      <option value="青森">青森県
    </select>
    <select onchange="table && table.find(new RegExp( this.value ), 2)">
      <option value="">-
      <option value="市">市
      <option value="町">町
    </select>
    <select onchange="table && table.find(new RegExp( this.value ), 3)">
      <option value="">-
      <option value="おいしい">おいしい
      <option value="おしい">おしい
      <option value="お.*しい">お*しい
    </select>
    <select onchange="table && table.limit(this.value)">
      <option value="100">-
      <option value="1">1件
      <option value="3">3件
      <option value="5">5件
    </select>
    <input type="checkbox" id="sort">(逆順)
    <select onchange="table && table.sort(-this.form.elements['sort'].checked, +this.value)">
      <option value="">ソートします
      <option value="0">項目1
      <option value="1">項目2
      <option value="2">項目3
      <option value="3">項目4
    </select>
    <input type="button" value="Reverse" onclick="table && table.complement ()">
    <input type="button" value="Reset" onclick="table && table.reset ()">
  </p>
</form>

<table id="HOGE">
  <col class="No" />
  <col class="Prefecture" />
  <col class="Cities" />
  <col class="Comments" />
  <thead>
    <tr>
      <th scope="col" id="HOGE.No">No</th>
      <th scope="col" id="HOGE.Prefecture">Prefecture</th>
      <th scope="col" id="HOGE.Cities">Cities</th>
      <th scope="col" id="HOGE.Comments">Comments</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td headers="HOGE.No">1</td>
      <td headers="HOGE.Prefecture" scope="row" axis="岩手, 洋野">岩手県</td>
      <td headers="HOGE.Cities">洋野町</td>
      <td headers="HOGE.Comments">ウニがおいしい</td>
    </tr>
    <tr>
      <td headers="HOGE.No">2</td>
      <td headers="HOGE.Prefecture" scope="row" axis="青森, 八戸">青森県</td>
      <td headers="HOGE.Cities">八戸市</td>
      <td headers="HOGE.Comments">イカがおいしい</td>
    </tr>
    <tr>
      <td headers="HOGE.No">3</td>
      <td headers="HOGE.Prefecture" scope="row" axis="岩手, 久慈">岩手県</td>
      <td headers="HOGE.Cities">久慈市</td>
      <td headers="HOGE.Comments">美しすぎる海女さんで、おしい</td>
    </tr>
    <tr>
      <td headers="HOGE.No">4</td>
      <td headers="HOGE.Prefecture" scope="row" axis="青森, 八戸">青森県</td>
      <td headers="HOGE.Cities">八戸市</td>
      <td headers="HOGE.Comments">美しすぎる市議会議員で、さわがしい</td>
    </tr>
    <tr>
      <td headers="HOGE.No">5</td>
      <td headers="HOGE.Prefecture" scope="row" axis="岩手, 洋野">岩手県</td>
      <td headers="HOGE.Cities">洋野町</td>
      <td headers="HOGE.Comments">鮑がおいしい</td>
    </tr>
    <tr>
      <td headers="HOGE.No">6</td>
      <td headers="HOGE.prefecture" scope="row" axis="青森, 八戸">青森県</td>
      <td headers="HOGE.Cities">八戸市</td>
      <td headers="HOGE.Comments">B級グルメ「せんべい汁」がおいしい</td>
    </tr>
    <tr>
      <td headers="HOGE.No">7</td>
      <td headers="HOGE.Prefecture" scope="row" axis="岩手, 洋野">岩手県</td>
      <td headers="HOGE.Cities">洋野町</td>
      <td headers="HOGE.Comments">天然ホヤがおいしい</td>
    </tr>
  </tbody>
</table>

<script type="application/javascript; version=1.8">
(function () { // Asymmetrical JavaScript Abridgment Exclusively

  var getTBody =
    (function (no)
      let (b = this.table.tBodies)
      ('number' === typeof no)
      ? [b[no]]
      : b);
      
  var ariaHidden =
    (function (tr)
      tr.setAttribute ('aria-hidden', String (this)));

  var ascend =
    (function (cell1, cell2)
      let (
        s1 = cell1.textContent.trim(),
        s2 = cell2.textContent.trim()
      )
      (s1 > s2) - (s1 < s2));
      
  var descend =
    (function (cell1, cell2)
      -(ascend.apply (this, arguments)));
  
  var toggle =
    (function (tr)
      ariaHidden.call (tr.getAttribute ('aria-hidden') === 'false', tr));
 
  var _find =
    (function (tr)
      let (
        t = ('undefined' === typeof this.cellIndex ||
             -1 === this.cellIndex)
            ? tr
            : tr.cells[ this.cellIndex ]
      )
      this.reg.test (t.textContent) || ariaHidden.call (true, tr));
      
  var moveTR =
    (function (cell)
      this.appendChild (cell.parentNode));
  
  var selecter =
    (function (row)
      row.cells[this]);

//____________

  var disp =
    (function (tb) Array.forEach (tb.rows, ariaHidden, false));
 
  var limit =
    (function (tb) Array.slice (tb.rows, this).forEach (ariaHidden, true));

  var complement =
    (function (tb) Array.forEach (tb.rows, toggle));

  var find =
    (function (tb) Array.forEach (tb.rows, _find, this));

  var sort = function (tb) {
    var cloneTBody = tb.cloneNode (false);
    Array.map (tb.rows, selecter, this.cellIndex) //セルを集め
         .sort (this.compare) // 並び替え
         .forEach (moveTR, cloneTBody); // クローンに移す
    tb.parentNode.replaceChild (cloneTBody, tb); // もとと入れ替える 
  };

//____________

  var TableViewer = function (node) { // オブジェクト
    this.table = node;
    this.reset ();
  };

  TableViewer.prototype.reset = function (no) {
    Array.forEach (getTBody.call (this, no), disp);
    return this;
  };
  
  TableViewer.prototype.limit = function (n, no) {
    Array.forEach (getTBody.call (this, no), limit, n);
    return this;
  };
  
  TableViewer.prototype.complement = function (no) {
    Array.forEach (getTBody.call (this, no), complement);
    return this;
  };
  
  TableViewer.prototype.find = function (reg, cellIndex, no) {
    Array.forEach (getTBody.call (this, no), find, { reg: reg, cellIndex: cellIndex || 0});
    return this;
  };
  
  TableViewer.prototype.sort = function (cmp, cellIndex, no) {
    Array.forEach (getTBody.call (this, no), sort, {
      compare: ('function' === typeof cmp) ? cmp: (cmp < 0) ? descend: ascend,
      cellIndex: cellIndex || 0
    });
    return this;
  };

//____________
  this.createTableViewer =
    (function (table)
      (table instanceof HTMLTableElement)
      ? new TableViewer (table)
      : null);

})();

var table = createTableViewer (document.getElementById ('HOGE'));

</script>