この図でわかるように、Visual Studio 2012 のソリューション エクスプローラーと同様に動作する HTML ツリービューを作成しました。このツリーのすべてのノードは、コンテナーの残りのスペースを埋めるために引き伸ばされます。
この動作を実現するために、Javascript を使用して順不同リストを作成し、ツリーにデータを追加しています。DOM 構造は次のようになります。
<ul>
<li>
<input type="checkbox" id="node_xy" />
<label for="node_xy" /> <!-- expand/collapse button -->
<a href="javascript:nodeClickHandler();"> <!-- node text --> </a>
<ul>
<!-- subtree with li elements... -->
</ul>
</li>
</ul>
ツリーにデータを入力した後、Javascript (jQuery) を使用して各ノードの幅を調整し、コンテナーの残りのスペースを埋めます。コンテナーの幅は固定されていますが、(Visual Studio のように) スクロール可能であるため、ツリーの最大幅が変更される可能性があるため、ユーザーがツリー内のノードを展開または折りたたむたびに、同じ幅調整手順を実行する必要があります。コードの幅調整部分は次のようになります。
updateLayout: function (containerWidth) {
var self = $(this);
self.find('.treeview a').css('width', ''); /* remove the width property for the next calculation */
var maxAWidth = $('.treeview a').max(function () {
return $(this).offset().left + $(this).outerWidth();
});
var targetWidth = containerWidth || $('.treeview').width();
targetWidth = Math.max(targetWidth, maxAWidth);
$('.treeview a').each(function () {
var left = $(this).offset().left;
$(this).outerWidth(targetWidth - left);
});
}
正常に動作しますが、ツリーに多数 (数百または数千) のノードがあり、ユーザーがノードを展開または折りたたむ場合は非常に遅くなります。updateLayout
メソッドがツリービューの下の完全な DOM ツリーをトラバースするため、これらのケースではパフォーマンスが非常に悪くなります (展開/折りたたみごとに 1 ~ 2 秒の計算) 。この種のトラバースを使用しない、この「ストレッチ」問題に対する他の解決策はあるのでしょうか? ある種の純粋なCSSマジックでこの問題を解決できればいいのですが、まったく不可能のようです...
アップデート:
標準の jQuery 最適化 (クエリ結果を変数に抽出するなど) は機能しません。たとえば、次のコードは古いコードよりも高速ではありません。
updateLayout: function (containerWidth) {
var self = $(this);
var treeviewLinks = self.find('.treeview a').css('width', '').get();
var maxAWidth = -Infinity;
for(var i = 0; i < treeviewLinks.length; i++) {
var link = $(treeviewLinks[i]);
if(link.offset().left + link.outerWidth() > maxAWidth)
maxAWidth = link.offset().left + link.outerWidth();
}
var targetWidth = containerWidth || $('.treeview').width();
targetWidth = Math.max(targetWidth, maxAWidth);
for(var i = 0; i < treeviewLinks.length; i++) {
var link = $(treeviewLinks[i]);
link.outerWidth(targetWidth - link.offset().left);
}
}
ただし、updateLayout
ツリー内のすべてのノードに同じ幅を使用することで、ステップを高速化できました。
updateLayout: function (containerWidth) {
var treeviewLinks = $(this).find('.treeview a');
$('#treeViewItemStyle').remove();
var maxAWidth = treeviewLinks.max(function () {
return $(this).offset().left + $(this).outerWidth();
});
var targetWidth = containerWidth || $('.treeview').width();
targetWidth = Math.max(targetWidth, maxAWidth);
$('<style id="treeViewItemStyle" type="text/css"> #treeview a { width: '
+ (targetWidth - 19) + 'px !important; } </style>')
.appendTo('head');
}
この最適化により、updateLayout
実行速度は速くなりますが、幅が同じであるため、コンテナーの最終的な幅は必要以上に大きくなります。私は現在、それを改善するための他のソリューションを探しています...