jQuery UIのSortableとTabsを併用したときに発生するおかしなのをなんとかする
さっきjQueryを使っていたら少しおかしな症状が出ました. どうやらjQuery UIのSortableとTabsを併用したときに出るっぽい. たとえば下記のコードでタブレイアウトにして, なおかつそのタブを並べ替え可能にする.
<ul id="tabs"></ul>
$('#tabs').tabs().sortable();
上記のではタブがいっさいないままなので, 新たなタブを追加するボタンもつけておきます. しかも任意の位置に追加できるリッチさ! 追加する位置は省略すれば最後に追加されるようにしておきました.
追加する位置: <input type="text" id="index" /> <a href="#add_tab" id="add_tab">タブを追加</a>
var num = 0; $('#add_tab').click(function() { var url = '#new_tab_' + num; var label = 'Number: ' + num; var index = $('#index').val(); if (index == '') { $('#tabs').tabs('add', url, label); } else { $('#tabs').tabs('add', url, label, parseInt(index)); } num++; });
そして2つほどタブを追加(この時点で0, 1の順)して, 入れ替えー(そして1, 0の順). そしてタブをNumber: 1のタブの後に追加(テキストボックスに1と入力)すると…… 後に挿入しようと思ったのに先に挿入されてしまうはず……(2, 1, 0の順)!
どうやらインデックスが絡んでくる話にはすべてこのような不都合が出るらしく, タブの削除などでも同じ症状が出ます. どうやらTabsに対してなにかするときには現在のliなどの並びを見ずに, jQueryオブジェクトが保持している内部的なデータを元に対して処理するようです. なので並び替えが行われても内部的なデータは並び変わっていないのでこのような症状が出るみたいです. 仕方のない話だとは思いますが.
でも"仕方ない"では済ませたくない(済ませられない)コトもあると思うので, なんとかしてみます. というコトで内部データも並べ替えましょー.
$('#tabs').tabs().sortable({ update: function(event, ui) { var data = $('#tabs').data('tabs'); var $tabs = []; var $panels = []; var $lis = []; ui.item.parent().find('a').each(function(i, v) { var id = v.href.split('#')[1]; data.$panels.each(function(i, v) { if (v.id == id) { $tabs.push(data.$tabs[i]); $panels.push(data.$panels[i]); $lis.push(data.$lis[i]); return false; } }); }); data.$tabs = $($tabs); data.$panels = $($panels); data.$lis = $($lis); } });
書き換えるべき内部データは$tabs, $panels, $lisの3つ(多分)なので, それらが並び替えの対象です. 単純に現在の並びを元にして並び替えて, 最後の書き換えのときにはjQueryオブジェクトにして書き換えています($tabsなどはjQueryオブジェクトなので).
コレでなんとかなった! でもなんかなー…… もっといい方法ないかなー?