テーブルを弄る。その3 ソートも一応できた。

丸々1日考えて、ソートの処理を書いてみた。
もう〜さっぱりだ。


しかも質問者は、think49 さんの追加レスを待っているようですぜぇ!
締め切るまで、どんどん書き込んでやろうか!? ^^;
しかし、逆に言えば、俺のアホが知れるかぁ〜

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

<style type="text/css">
tr[aria-hidden="true"] {
  visibility: collapse;
}
</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>
    <select onchange="table && table.sort(+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.reverse ()">
    <input type="button" value="Reset" onclick="table && table.reset ()">
  </p>
</form>

<table border="1" id="hoge">
  <thead>
    <tr>
      <th>No
      <th>Prefecture
      <th>Cities
      <th>Comments
  </thead>
  
  <tbody>
    <tr>
      <td>1
      <td>岩手県
      <td>洋野町
      <td>ウニがおいしい
      
    <tr>
      <td>2
      <td>青森県
      <td>八戸市
      <td>イカがおいしい
    
    <tr>
      <td>3
      <td>岩手県
      <td>久慈市
      <td>美しすぎる海女さんで、おしい
    
    <tr>
      <td>4
      <td>青森県
      <td>八戸市
      <td>美しすぎる市議会議員で、さわがしい

    <tr>
      <td>5
      <td>岩手県
      <td>洋野町
      <td>鮑がおいしい
      
    <tr>
      <td>6
      <td>青森県
      <td>八戸市
      <td>B級グルメ「せんべい汁」がおいしい
    
    <tr>
      <td>7
      <td>岩手県
      <td>洋野町
      <td>天然ホヤがおいしい

</table>

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

  var getTR = // tr を集める
    (function (collect)
      function (table, tbodyNo)
        ('undefined' === typeof tbodyNo)
          ? Array.reduce (table.tBodies, collect, [])
          : collect ([], table.tBodies[tbodyNo]))

    (function (result, tbody)
      result.concat (Array.slice (tbody.rows, 0)));


  var ariaHidden = // mode によって、それようの関数を返す
    function (mode)
      let (state = String (!! mode))
        function (tr) tr.setAttribute ('aria-hidden', state);
  
//____________


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


  var reset = // 初期化。すべて表示にする
    function (cbFunc, tbodyNo) {
      if ('function' !== typeof cbFunc)
        cbFunc = ariaHidden (!! cbFunc);
      
      Array.forEach (getTR (this.table, tbodyNo), cbFunc, this);
    };

  var limit = // 表示数の制限をする
    function (n, tbodyNo)
      Array.forEach (Array.slice (getTR (this.table, tbodyNo), n), ariaHidden (true));


  var reverse = // 表示状態を反転する
    (function (toggle)
      function (tbodyNo)
        Array.forEach (getTR (this.table, tbodyNo), toggle))

    (function (tr)
      tr.setAttribute ('aria-hidden', String (tr.getAttribute ('aria-hidden') === 'false')));



  var find = // 検索
    (function (checker, setter)
      function (reg, cellIndex, tbodyNo)
        Array.forEach (getTR (this.table, tbodyNo), checker (reg, cellIndex, setter)))
    
    (function (reg, cellIndex, setter)
      ('undefined' === typeof index) // index により用途に合った関数を返す
        ? function (tr) (reg.test (tr.textContent)) || setter (tr) // 行全体で検索
        : function (tr) (reg.test (tr.cells[ cellIndex ].textContent)) || setter (tr), // セル単体で検索

     ariaHidden (true)); // = setter 非表示用の関数にする
  
  
  var sort = // 並び替える
    (function (swap, createSortFunc)
      function (cellIndex, tbodyNo, cbFunc, cbObj)
        let (
          sortFunc = ('function' === typeof cbFunc)
            ? cbFunc // オリジナル関数
            : createSortFunc (cellIndex), // 標準ソート関数

          cbSortFunc = // ソート関数と swap 関数を包んで関数にする
            function (a, b)
              sortFunc.call (cbObj, a, b)
                ? swap (a, b)
                : false)

          Array.slice (getTR (this.table, tbodyNo), 0).sort (cbSortFunc))

    (function (a, b) { // swap
       a.parentNode.insertBefore (b, a); // ノードを移動するので、tbody[n] が空になりえる
       return true;
     },

     function (cellIndex) //この値で返す関数を判断
      ('undefined' === typeof cellIndex || -1 === cellIndex) //無指定 or -1
        ? function (a, b) // 行で評価する関数
            a.textContent > b.textContent

        : function (a, b) // セル(td)で評価する関数
            a.cells[ cellIndex ].textContent > b.cells[cellIndex].textContent);


  var create =
    function (table)
      (table instanceof HTMLTableElement)
        ? new TableViewer (table)
        : null;

//____________

  TableViewer.prototype.reverse = function () {
    reverse.apply (this, arguments);
    return this;
  };
  
  TableViewer.prototype.reset = function () {
    reset.apply (this, arguments);
    return this;
  };
  
  TableViewer.prototype.limit = function () {
    limit.apply (this, arguments);
    return this;
  };
  
  TableViewer.prototype.find = function () {
    find.apply (this, arguments);
    return this;
  };
  
  TableViewer.prototype.sort = function () {
    sort.apply (this, arguments);
    return this;
  };

//____________
  this.createTableViewer = create;

})();

var table = createTableViewer (document.getElementById ('hoge'));
table.sort (1);
</script>