WEB相談室

Webページ作成に関しての何でも掲示板です。

タイトル:TABLEの動的ソート

0:[投稿] 江田島 [2005/12/09 20:31 ] [環境:IE6 UNIX]

既存のHTMLにこのようなTABLEがあったとして、

<table>
<tr><th>野菜</th><th>始値</th><th>終値</th></tr>
<tr><td>大根</td><td>100</td><td>200</td></tr>
<tr><td>人参</td><td>200</td><td>300</td></tr>
<tr><td>白菜</td><td>300</td><td>100</td></tr>
</table>

このHTMLに適当なSCRIPTを追加して、たとえばボタンを押したら「終値」でソートされて表示される、
ということをしたいのですが、可能でしょうか?
サンプルか何かがある場所を教えていただけたら幸いです。
ブラウザ限定でも構いません。


1:[回答] sim [2005/12/10 02:37 ]

<script type="text/javascript">
<!--
function sortTable(sortCell,sortType) {
    obj = document.getElementById('sortTable');

    for(i = 0;i < obj.rows.length;i++) {
        sortNo = 0;
        num = obj.rows[i].cells[sortCell].firstChild.nodeValue;

        for(j = i + 1;j < obj.rows.length;j++) {
            if(sortType){
                if(num < obj.rows[j].cells[sortCell].firstChild.nodeValue) {
                    sortNo = j;
                }
            }else{
                if(num > obj.rows[j].cells[sortCell].firstChild.nodeValue) {
                    sortNo = j;
                }
            }
        }
        if(sortNo){
            obj.insertBefore(obj.rows[sortNo],obj.rows[i]);
        }
    }
}
//-->
</script>
<table>
<tr><th>野菜</th><th>始値</th><th>終値</th></tr>
<tbody id="sortTable">
<tr><td>大根</td><td>100</td><td>200</td></tr>
<tr><td>人参</td><td>200</td><td>300</td></tr>
<tr><td>白菜</td><td>300</td><td>100</td></tr>
</tbody>
</table>

<input type="button" value="始値昇順" onclick="sortTable(1,0)">
<input type="button" value="始値降順" onclick="sortTable(1,1)">
<input type="button" value="終値昇順" onclick="sortTable(2,0)">
<input type="button" value="終値降順" onclick="sortTable(2,1)">

こんなのはどうでしょう。


2:[回答] sort [2005/12/12 23:16 ]

質問者ではありませんが、気に入ったので使わせてもらおうと思います。
ボタンが場所をとるのでリンクに変更し、クリック毎に昇順、降順が変わるように修正してみました。

ところで、一つ問題があります。ソートは左詰めの文字列として実行されるので野菜の例では数値の桁数が異なると期待した結果になりません。空白を付けても無視されます。ゼロをつけるわけにもいきませんし、何か解決策はあるでしょうか?

<script type="text/javascript">
<!--
  sortType = 0;
function sortTable(sortCell) {
  if(sortType == 0) {
     sortType = 1;
  }else{
     sortType = 0;
  }

  obj = document.getElementById('sortTable');

  for(i = 0;i < obj.rows.length;i++) {
     sortNo = 0;
     num = obj.rows[i].cells[sortCell].firstChild.nodeValue;

     for(j = i + 1;j < obj.rows.length;j++) {
        if(sortType){
           if(num < obj.rows[j].cells[sortCell].firstChild.nodeValue) {
              sortNo = j;
           }
        }else{
           if(num > obj.rows[j].cells[sortCell].firstChild.nodeValue) {
              sortNo = j;
           }
        }
     }
     if(sortNo){
        obj.insertBefore(obj.rows[sortNo],obj.rows[i]);
     }
  }
}
//-->
</script>
<table border=1>
<tr>
<th><a href="javascript:sortTable(0);">野菜</a></th>
<th><a href="javascript:sortTable(1);">始値</a></th>
<th><a href="javascript:sortTable(2);">高値</a></th>
<th><a href="javascript:sortTable(3);">安値</a></th>
<th><a href="javascript:sortTable(4);">終値</a></th>
</tr>
<tbody id="sortTable">
<tr><td>大根</td><td align=right>100</td><td align=right>200</td><td align=right>100</td><td align=right>200</td></tr>
<tr><td>人参</td><td align=right>200</td><td align=right>300</td><td align=right>200</td><td align=right>300</td></tr>
<tr><td>白菜</td><td align=right>300</td><td align=right>300</td><td align=right>100</td><td align=right>100</td></tr>
<tr><td>胡瓜</td><td align=right>100</td><td align=right>120</td><td align=right> 50</td><td align=right> 80</td></tr>
<tr><td>玉葱</td><td align=right>150</td><td align=right>200</td><td align=right> 80</td><td align=right>200</td></tr>
</tbody>
</table>


3:[回答] sim [2005/12/13 00:34 ]

あぁ。。以前この掲示板で同じ内容に返答したことがあったんですが、まさにその質問だった気がします。

obj.rows[j].cells[sortCell].firstChild.nodeValueが文字列扱いになっているかもなので、int型に直してあげたら動くんじゃないかと思います。

parseInt(obj.rows[j].cells[sortCell].firstChild.nodeValue)

こんな感じにしてみてください。


4:[回答] 匿 [2005/12/13 06:36 ]

> obj.rows[j].cells[sortCell].firstChild.nodeValueが文字列扱いになっているかも

「かも」ではなく、nodeValue は String(DOMString)でしかありえない。
http://www2u.biglobe.ne.jp/%7Eoz-07ams/prog/dom-ref/Core/Node.html#Node-nodeValue

関数内の変数は var 宣言しておくべき。


5:[回答] sort [2005/12/14 23:45 ]

parseIntを使えば数値としてソートができるようになりました。

ただ、元の手順のままでは、自分より大きい(小さい)一番下の行と置き換える処理になり、行数が多く複雑な並びになると一回のクリックではソートが完了しないという結果でした。トグルスイッチはクリック一回で完了することを前提としているのでソートできないケースもありました。

以下は自分より下で最大(最小)の行を見つけて置き換えるという風に変えたつもりです。この方法で問題ないでしょうか?(varは別にして)

<script type="text/javascript">
<!--
   sortType = 0;
function sortTable(sortCell) {
   if(sortType == 0) {
       sortType = 1;
   }else{
       sortType = 0;
   }

   obj = document.getElementById('sortTable');

   for(i = 0;i < obj.rows.length;i++) {
       sortNo = 0;
       numi = parseInt(obj.rows[i].cells[sortCell].firstChild.nodeValue);

       for(j = i + 1;j < obj.rows.length;j++) {
           numj = parseInt(obj.rows[j].cells[sortCell].firstChild.nodeValue);
           if(sortType){
               if(numi < numj) {
                   numi = numj;
                   sortNo = j;
               }
           }else{
               if(numi > numj) {
                   numi = numj;
                   sortNo = j;
               }
           }
       }
       if(sortNo){
           obj.insertBefore(obj.rows[sortNo],obj.rows[i]);
       }
   }
}
//-->
</script>


6:[回答] 老衰 [2005/12/15 10:56 ]

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META http-equiv=Content-Type content="text/html; charset=shift_jis">
<TITLE></TITLE>
<STYLE TYPE="text/css">
table {
  table-layout:fixed;
}
span {
 cursor:pointer;
}
</STYLE>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
function pre_sort(table_id) { //Usage: xxx = new preSort();
 this.isCollection = true;
 var tob = table_id ?
     document.getElementById(table_id) :
     document.getElementsByTagName("table")[0];
 var arr;
 var idx = 0;
 if (tob.getElementsByTagName("th").length > 0) idx = 1;
 arr = [];
 var mindx = idx;

 for ( ; idx < tob.rows.length;idx++) {
   arr.push([
      tob.rows[idx].cells[0].innerHTML,
      parseInt(tob.rows[idx].cells[1].innerHTML),
      parseInt(tob.rows[idx].cells[2].innerHTML)
   ]);
 }

 this.getArray = function() {
   return arr;
 }
 this.getTable = function() {
   return tob;
 }
 this.getMindx = function() {
   return mindx;
 }
}
function sort_table(table_id) {
  var ot = new pre_sort(table_id);
  var ar = ot.getArray();

  this.asort = function(col) { //単一カラム昇順ソート
    ar.sort(function(a,b) {
      if (typeof a[col] != "string") return a[col] - b[col];
      if (a[col] > b[col]) return 1;
      if (a[col] < b[col]) return -1;
      return 0;
    });
    disp_result();
  }
  this.dsort = function(col) { //単一カラム降順ソート
    ar.sort(function(b,a) {
      if (typeof a[col] != "string") return a[col] - b[col];
      if (a[col] > b[col]) return 1;
      if (a[col] < b[col]) return -1;
      return 0;
    });
    disp_result();
  }
  this.amulti = function(cols) { //複数カラム昇順ソート
    ar.sort(function(a,b) {
      for (var i=0;i < cols.length;i++) {
         var A = a[cols[i]];
         var B = b[cols[i]];
         if (typeof A != "string") {
            var n = A-B;
            if (n == 0) continue;
            return n;
         }
         else {
           if (A == B) continue;
           if (A > B) return 1;
           else return -1;
         }
      }
      return 0;
    });
    disp_result();
  }
  this.dmulti = function(cols) { //複数カラム降順ソート
    ar.sort(function(b,a) {
      for (var i=0;i < cols.length;i++) {
         var A = a[cols[i]];
         var B = b[cols[i]];
         if (typeof A != "string") {
            var n = A-B;
            if (n == 0) continue;
            return n;
         }
         else {
           if (A == B) continue;
           if (A > B) return 1;
           else return -1;
         }
      }
      return 0;
    });
    disp_result();
  }

  this.result = disp_result;

  function disp_result() {
    var tab = ot.getTable();
    var idx = ot.getMindx();

    for (var i=0;i < ar.length;i++) {
      tab.rows[idx].cells[0].innerHTML = ar[i][0];
      tab.rows[idx].cells[1].innerHTML = ar[i][1];
      tab.rows[idx].cells[2].innerHTML = ar[i][2];
      idx++;
    }
  }
}
var st = null;
window.onload = function() {
 st = new sort_table();
}
Number.prototype.z = function(n) {
  var x = "0000000000"+this;
  return x.substr(x.length - n);
}
</SCRIPT>
</HEAD>
<BODY>
<input type=button value="ascending(2,0,1)" onclick="st.amulti([2,0,1])">
<input type=button value="descending(1,2)" onclick="st.dmulti([1,2])">
<tr>
<script>
{
 var A,B,C;
 document.writeln("<table border>"+
   "<tr>"+
   "<th>ID<span onclick='st.dsort(0)'>▼</span><span onclick='st.asort(0)'>▲</span>"+
   "<th>値段<span onclick='st.dsort(1)'>▼</span><span onclick='st.asort(1)'>▲</span>"+
   "<th>個数<span onclick='st.dsort(2)'>▼</span><span onclick='st.asort(2)'>▲</span>");
 document.writeln(
    "<colgroup>"+
    "<col width=100><col width=100><col width=100>"+
    "</colgroup>");
 for (var i=0;i<20;i++) {
   A = "ID"+(i+1).z(5);
   B = Math.floor(Math.random() * 1000)+1; //
   C = Math.floor(Math.random() * 10)+1; //
   document.writeln("<tr><td>"+A+"<td>"+B+"<td>"+C);
 }
 document.writeln("</table>");
}
</script>
</BODY>
</HTML>

理解した上でご利用ください。

回答(必須): 状態:

お名前(必須):

URL:




[戻る]