重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

【GOLF me!】初月無料お試し

リストをソートしたいのですが...
下記のような<li>のchildNodesである<span>の内容でソートしたいのですが、どうすればいいでしょうか?
<table><td>でソートするのと同じなのですが、テーブルに変換せずに、リストのままソートさせたいのです。
<ul>が下の<ol>の見出しとなっており、例えば「社名」を1回クリックすると降順、もう一度クリックすると昇順のようにしたいのです。(ulとolに分ける必要は特にありません)
spanの下にclassを指定してもOKです。
DOMのrows[ ]やcells[ ]が使えないので困ってしまいました。どなたかお知恵をお願いいたします。

<ol>
<li><span>社名</span><span>仕入値</span><span>小売値</span><span>会社ID</span><span>備考(ソート不要)</span>
</li>
</ol>
<ul>
<li><span>ABC</span><span >100</span><span >200</span><span >1</span><span >テキスト(ソート不要)</span></li>
<li><span>BBB</span><span ></span><span >300</span><span >2</span><span >テキスト(ソート不要)</span></li>
<li><span>XYZ</span><span >300</span><span >300</span><span >3</span><span ></span></li>
<li><span>A-AA</span><span >100</span><span >120</span><span >4</span><span >テキスト(ソート不要)</span></li>
<li><span>A-17</span><span >150</span><span >200</span><span >5</span><span >テキスト(ソート不要)</span></li>
</ul>

A 回答 (7件)

理想はこれか!?


超短いからコードの理解も簡単!
しかもデータの構造(たぐ)を崩さないかぎり複数使える!?
そしてソートも完璧!?
文字の区切りに'|'を使っているので、これは使えません!
<html>
<head><style>span{border:1px solid;margin:4px}</style></head>
<body>
<ol>
<li>
<span><a href="#" onClick="narabi(this,0)">社名</a></span>
<span><a href="#" onClick="narabi(this,1)">仕入値</a></span>
<span><a href="#" onClick="narabi(this,2)">小売値</a></span>
<span><a href="#" onClick="narabi(this,3)">会社ID</a></span>
<span>備考(ソート不要)</span>
</li>
</ol>
<ul>
<li><span>ABC</span><span >100</span><span >200</span><span >1</span><span >テキスト(ソート不要)</span></li>
<li><span>BBB</span><span ></span><span >300</span><span >2</span><span >テキスト(ソート不要)</span></li>
<li><span>XYZ</span><span >300</span><span >300</span><span >3</span><span ></span></li>
<li><span>A-AA</span><span >100</span><span >120</span><span >4</span><span >テキスト(ソート不要)</span></li>
<li><span>A-17</span><span >150</span><span >200</span><span >5</span><span >テキスト(ソート不要)</span></li>
</ul>
</body>

<script>
var af=[];
function narabi(ob,cidx){
af[cidx]=af[cidx]?0:1;
var dt=[];
var tg=parentSearch(ob,'OL').nextSibling;
var li=tg.getElementsByTagName('li');
for(var i=0,m=li.length;i<m;i++){
var sp = li[i].getElementsByTagName('span');
dt[i]=sp[cidx].innerHTML+'|';
for(var j=0;j<4;j++) dt[i]+=sp[j].innerHTML+'|';
}
dt.sort();if(af[cidx]) dt.reverse();
for(var i=0,m=dt.length;i<m;i++){
var sp = dt[i].split('|');
for(var j=0;j<4;j++) li[i].getElementsByTagName('span')[j].innerHTML=sp[j+1];
}
}
function parentSearch(o,t){while(o.tagName!=t)o=o.parentNode;return o;}
</script>
</html>
    • good
    • 0
この回答へのお礼

ありがとうございます。
Firefoxで動作しないようですが...、エラーコンソールによると「tg.getElementsByTagName is not a function」と表示されます。
原因を究明してみます。
ありがとうございました。

お礼日時:2008/09/20 20:15

<li>の部分を1000個にしてIEで約20秒、Firefoxで3秒ぐらいでしたよ。

    • good
    • 0
この回答へのお礼

こちらでもテストしてみました。
RAMを多く積んでいるせいか、IEでも相当早かったです。
丁寧に教えていただきありがとうございました。

これで回答を締め切らせていただきます。
回答いただいた皆様、ありがとうございました。

お礼日時:2008/09/21 22:51

27行目付近


var tg=parentSearch(ob,'OL').nextSibling;
の次に
while(tg.nodeName!='UL') tg=tg.nextSibling;
を追加でFireFoxでも動きます!
    • good
    • 0
この回答へのお礼

動きました! ありがとうございます。

お礼日時:2008/09/20 23:43

ちなみにソートのアルゴリズムに関しては、多種多様なやり方があります。



http://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%BC% …

javascriptへの実装という意味では以下が参考になると思います。

http://www.openspc2.org/reibun/javascript2/index …

私の例示した#3は、クイックソートを用いています。
再帰計算をする関係でスタックオーバーフローをおこす可能性もあるので
若干注意が必要です。
他の方がどのソートアルゴリズムを使っているか検証なさると
勉強になると思いますよ。

通常1万件のデータを羅列すること、またそれをjavascriptでソートする
ことは、ユーザービリティやスピードの面であまり現実的ではないかも
しれません。(javascriptの処理はあくまでもクライアントのマシン
スペックに依存しますので、負荷の高い処理をユーザー側に委ねることは
危険です)

私がやるなら、データはSQLで管理し、30~50件でページング処理を
いれます。
    • good
    • 0
この回答へのお礼

どうもありがとうございます。
大変勉強になります。

ご指摘の通り、javascriptでソートするのは現実的でないですね。

丁寧に教えていただきありがとうございました。

お礼日時:2008/09/20 20:25

めんどうなので逆順ソートは割愛。

(たぶんフラグ処理でいけます)
DOMとはいいがたいですがこんなんでどうですか?
なおhtmlのspanにclassをつけているのは見にくいので色をつけただけです。
ソートにはclassをつかっていません。

//hoge.js
window.onload=function(){
var lhead=document.getElementById("lhead");
var li=lhead.getElementsByTagName("li")[0];
var spans=li.getElementsByTagName("span");
for(var i=0;i<spans.length;i++){
spans[i].index=i;
spans[i].onclick=function(){
if(this.innerHTML.match(/ソート不要/)) return false;
var lbody=document.getElementById("lbody");
var tags=lbody.getElementsByTagName("li");
var list=new Array();
for(var i=0;i<tags.length;i++){
list[i]=new Object();
list[i].key=tags[i].getElementsByTagName("span")[this.index].innerHTML;
list[i].data=tags[i].innerHTML;
}
list.sortData=sortData;
list.sortData(0,list.length -1 );
for(var i=0;i<tags.length;i++){
tags[i].innerHTML=list[i].data;
}
}
}
}

function sortData(start,end) {
var x = this[Math.floor((start + end) / 2)].key;
var i = start;
var j = end;
while (true) {
while (this[i].key < x) i++;
while (x < this[j].key) j--;
if (i >= j) break;
var n = this[i];
this[i] = this[j];
this[j] = n;
i++;
j--;
}
if (start < i-1) this.sortData(start,i-1);
if (j+1 < end) this.sortData(j+1,end);
}

//hoge.css
.s0{background-Color:lime;}
.s1{background-Color:aqua;}
.s2{background-Color:fuchsia;}
.s3{background-Color:yellow;}
.s4{background-Color:red;}

//hoge.htm
<link rel="stylesheet" href="hoge.css">
<script src="hoge.js"></script>

<ol id="lhead">
<li><span class="s0">社名</span><span class="s1">仕入値</span><span class="s2">小売値</span><span class="s3">会社ID</span><span class="s4">備考(ソート不要)</span>
</li>
</ol>

<ul id="lbody">
<li><span class="s0">ABC</span><span class="s1">100</span><span class="s2">200</span><span class="s3">1</span><span class="s4">テキスト(ソート不要)</span></li>
<li><span class="s0">BBB</span><span class="s1"></span><span class="s2">300</span><span class="s3">2</span><span class="s4">テキスト(ソート不要)</span></li>
<li><span class="s0">XYZ</span><span class="s1">300</span><span class="s2">300</span><span class="s3">3</span><span class="s4"></span></li>
<li><span class="s0">A-AA</span><span class="s1">100</span><span class="s2">120</span><span class="s3">4</span><span class="s4">テキスト(ソート不要)</span></li>
<li><span class="s0">A-17</span><span class="s1">150</span><span class="s2">200</span><span class="s3">5</span><span class="s4">テキスト(ソート不要)</span></li>
</ul>
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
逆順は自力で試してみます。

お礼日時:2008/09/20 19:47

どのようにもとのリストを作成しているのか不明ですが、もしそれほどの量でないのであれば、もとから配列に入れておいて(もしくは最初に読み取って)、ソート結果をリスト内に書換えるだけにしたほうが簡単では?


と思って、少し調べて勉強して作ってみました。(私も知らなかったので、付け焼刃です)
どうやら、ソーティングもできるみたいです。
下の例を参考にしてください。(インデントは全角スペースに変換してありますのでご注意)
<html>
<head>
<META HTTP-EQUIV="Content-Script-Type" CONTENT="text/javascript">
<script language="JavaScript">
<!--
//プロパティ定義
function koumoku(name, siire, kouri, id, bikou) {
 this.name = name;
 this.siire = siire;
 this.kouri = kouri;
 this.id = id;
 this.bikou = bikou;
}
//配列定義
var test = new Array();
var ttitle = new koumoku("社名","仕入値","小売値","会社ID","備考");
test[0] = new koumoku("社名1","100","789","ID1","備考1");
test[1] = new koumoku("社名2","200","456","ID2","備考2");
test[2] = new koumoku("社名3","300","123","ID3","備考3");
//配列を表示
function testDisp(){
 var lst = document.getElementById('target').getElementsByTagName('li');
 for (i=0; i<test.length; i++){
  var itm=lst[i].getElementsByTagName('span');
  itm[0].innerText=test[i].name; itm[1].innerText=' ' + test[i].siire;
  itm[2].innerText=' ' + test[i].kouri; itm[3].innerText=' ' + test[i].id;
  itm[4].innerText=' ' + test[i].bikou;
 }
}
//ソートのテスト
function testSort(){
 test.sort(cmp_kouri);
 testDisp();
}
function cmp_kouri(a,b){ return a.kouri - b.kouri; }

//HTML表示
function init(){
 document.writeln('<ol><li>');
 for (i=0; i<5; i++){document.write('<span>','</span>');}
 document.writeln('\n</li></ol>\n<ul id="target">');
 for (j=0; j<test.length; j++){
  document.write('<li>');
  for (i=0; i<5; i++){document.write('<span>','</span>');}
  document.writeln('</li>');
 }
 document.writeln('</ul>');
 testDisp();
}
//-->
</script>
</head>

<body>
最初の表示<br>
<script language="JavaScript">
<!--
init();
//-->
</script>

<form>
<input type="button" value="小売値でソート" onclick="testSort();">
</form>
<br>つづきの表示
</body>
</html>

この回答への補足

回答ありがとうございます。

実は、リストはかなり大きくなる可能性があります。
最大10000件程で、備考欄にはアスキーキャラクターで2000字ほどのテキストが入りそうな...。

確かに小さなリストもありますので、メモリに読み込ませる方法も参考にさせていただきます。

もし大きなリストにも対応できる方法がありましたらご教示いただければ幸いです。

どうぞよろしくお願いいたします。

補足日時:2008/09/20 00:39
    • good
    • 0
この回答へのお礼

お礼の欄に入れるつもりが、間違って補足の欄に書き込んでしまいました。
失礼いたしました。
追加の回答を頂ければ幸いです。よろしくお願いいたします。

お礼日時:2008/09/20 02:46

<ul id="a">


<li><span>ABC</span><span >100</span><span >200</span><span >1</span><span >テキスト(ソート不要)</span></li>
<li><span>BBB</span><span ></span><span >300</span><span >2</span><span >テキスト(ソート不要)</span></li>
<li><span>XYZ</span><span >300</span><span >300</span><span >3</span><span ></span></li>
<li><span>A-AA</span><span >100</span><span >120</span><span >4</span><span >テキスト(ソート不要)</span></li>
<li><span>A-17</span><span >150</span><span >200</span><span >5</span><span >テキスト(ソート不要)</span></li>
</ul>

<script>
alert( getLiValue('a',0,4) );
setLiValue('a',0,4,'aiueo');

function getLiValue(id,x,y){
var tb=document.getElementById(id).getElementsByTagName('li');
var td=tb[y].getElementsByTagName('span')[x];
return td.textContent||td.innerText;
}
function setLiValue(id,x,y,val){
var tb=document.getElementById(id).getElementsByTagName('li');
var td=tb[y].getElementsByTagName('span')[x];
if(td.textContent) td.textContent=val; else td.innerText=val;
}
値を抜けて、書きなおせるので、並び替えもやる気になればできるかも?

この回答への補足

回答ありがとうございます。

質問のしかたがよくなかったのですが、
まだ勉強中なのでいただいたヒントを生かし切れるようになるにはまだまだ時間がかかってしまいそうです...。
実際、この3時間ばかり試行錯誤しましたがうまくいきません。

http://chaichan.web.infoseek.co.jp/qanda/qa6479. …

ここにあるコードをうまく使えないかな、と思って試しているのですが、
ソートの動作まで教えていただけましたら幸いです。
どうぞよろしくお願いいたします。

補足日時:2008/09/20 00:33
    • good
    • 0
この回答へのお礼

お礼の欄に入れるつもりが、間違って補足の欄に書き込んでしまいました。
失礼いたしました。
追加の回答を頂ければ幸いです。よろしくお願いいたします。

お礼日時:2008/09/20 02:45

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!