Note: この記事は、3年以上前に書かれています。Webの進化は速い!情報の正確性は自己責任で判断してください。
| num | data |
|---|---|
| row1 row1 row1 row1 row1 row1 row1 row1 row1 row1 | |
| row2 row2 row2 row2 row2 row2 row2 row2 row2 row2 | |
| row3 row3 row3 row3 row3 row3 row3 row3 row3 row3 | |
| row4 row4 row4 row4 row4 row4 row4 row4 row4 row4 | |
row5 row5 row5 row5 row5 row5 row5 row5 row5 row5 row5 row5 row5 row5 row5 |
|
| row6 row6 row6 row6 row6 row6 row6 row6 row6 row6 |
前回のサンプルを踏み台に、テーブル行を並び替えるスクリプトを作ってみる。というかコレが本当にやりたかったこと。詳しい動きは...
- 任意の行を選択する (選択行をマーキング)
- 別の行を選択する
- 2.の直前に1.の行を移動する
まあ暫くやってみれば解ると思う。てきと~にプチプチ・ソートと名付けよう。並び替えるときに同時に<input>タグのvalueも再設定してたりするんだけど、これに意味があって、まあ要するに表示メニューの並び替えを変更/登録するWebアプリのために作ったスクリプトなんだ。なかなかウケは良いですよ? Webでのドラッグ&ドロップは労力に見合うほどの効果があるか疑問だった、って判断しただけですけどね!
p.s.: ちょっと追記。使いやすいドラッグ&ドロップの設計はたいへんだ、ということ。もちろんこのスクリプトの動作も解りにくい。けど、ツールチップを表示するとか選択後のclass指定を工夫するとか考え付くことはいっぱいあって、俺にはこれをベースに弄るほうが楽に思える。
解説は以下にて。(デモは「続き」で動きます。)
rowSelect()
var rowSelect = {init: function(table){this.rowList = $(table).getElementsByTagName('tr');for(i=1; i<this.rowList.length; i++){//addEvent(this.rowList[i],'mouseover',rowSelect.msOver,false);//addEvent(this.rowList[i],'mouseout',rowSelect.msOut,false);//addEvent(this.rowList[i],'click',rowSelect.selected,false);this.rowList[i].onmouseover = rowSelect.msOver;this.rowList[i].onmouseout = rowSelect.msOut;this.rowList[i].onclick = rowSelect.selected;}},msOver: function(e){//var row = e.currentTarget;var row = this;if(row.className == 'msOver') return;if(rowSelect.selectFlag != row) addClass(row,'msOver');},msOut: function(e){//var row = e.currentTarget;var row = this;if(row.className != 'msOver') return; // '' or 'selected'if(rowSelect.selectFlag != row) delClass(row,"msOver");},selected: function(e){//var row = e.currentTarget;var row = this;if(rowSelect.selectFlag == row){delClass(row,"msOver");delClass(row,"selected");rowSelect.selectFlag = null;return;}else if(rowSelect.selectFlag && rowSelect.selectFlag != row){var selectedRow = rowSelect.selectFlag;delClass(selectedRow,"msOver");delClass(selectedRow,"selected");var cloneRow = selectedRow.cloneNode(true);//delete&insertselectedRow.parentNode.removeChild(selectedRow);row.insertAdjacentElement('beforeBegin',cloneRow);//addEventcloneRow.onmouseover = rowSelect.msOver;cloneRow.onmouseout = rowSelect.msOut;cloneRow.onclick = rowSelect.selected;rowSelect.selectFlag = null;rowSelect.setValue(row);return;}rowSelect.selectFlag = row;delClass(row,"msOver");addClass(row,"selected");},setValue: function(row){var rowList = row.parentNode.getElementsByTagName('tr');for(var i=1;i<rowList.length;i++){var targetNode = rowList[i].getElementsByTagName('input')[0];// 表示番号のリセットif(targetNode.nodeName == 'INPUT') {inpList[i] = targetNode.value = i;;}}}}
5~7行目および15、22行目はaddEventListener()/attachEvent()を使う場合の指定。まあどっちでも良いんですけどね。テーブル行に本スクリプト以外のイベントを割り当てる予定がある場合は、こっちを使いましょう。詳しい理由と解説は前回の記事を参照してくださいな。
37~55行目およびsetValue()メソッドが今回追加した部分です。流れとしては、選択行を複製→削除→複製を挿入。複製したノードにはイベントが割り振られていないので、init()にて設定したのと同じようにイベント登録しておきます。そしてsetValue()にてinputタグをごにょごにょする、と。
45行目にて要素を挿入する際、insertAdjacentElement()という耳慣れないメソッドを使っていますが、これはこのままだとFirefoxで無効になるため、ちょっと一工夫しています。この処理については以前の記事「FirefoxでInsertAdjacent系メソッドを利用する」にて軽く紹介しています。
まとめ
まあ前回で難しいとこは済ませているので、今回やったことなんてホントてきとーなんですけどね。たとえば挿入処理なんかもいろいろ分岐を増やしてより直感的な挙動にしたりとか、いろいろやりようはあると思います。ただ、道はつけたというか、この場所でこういう処理をすればちゃんとできるんだ、みたいなことが今回できたので、「後は良しなに」といったところですかね!
Note: スパム対策が面倒なので、コメント投稿を廃止しました。以前のコメントは残します。
ご意見・ご要望はtwitter@sigwygかはてブコメントにて。