Note that there are some explanatory texts on larger screens.

plurals
  1. POBad performance of stretching nodes in an HTML Treeview
    primarykey
    data
    text
    <p>I've created an HTML treeview which behaves similar to the solution explorer in Visual Studio 2012 where every node of the tree is stretched to fill the remaining space of its container as you can see on this picture:</p> <p><img src="https://i.stack.imgur.com/MH5mi.png" alt="Visual Studio 2012 solution explorer"></p> <p>In order to achieve this behaviour, I am creating an unordered list with Javascript to populate my tree - the DOM structure looks something like this:</p> <pre><code>&lt;ul&gt; &lt;li&gt; &lt;input type="checkbox" id="node_xy" /&gt; &lt;label for="node_xy" /&gt; &lt;!-- expand/collapse button --&gt; &lt;a href="javascript:nodeClickHandler();"&gt; &lt;!-- node text --&gt; &lt;/a&gt; &lt;ul&gt; &lt;!-- subtree with li elements... --&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; </code></pre> <p>After populating the tree, I am using Javascript (jQuery) to adjust the width of every node to fill the remaining space of its container. The container width is fixed but it is scrollable (like in Visual Studio), so I have to take the same width adjustment step whenever the user expand or collapse nodes in the tree because it is possible that the maximum width of the tree is changed. The width adjustment part of the code looks like this:</p> <pre><code>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); }); } </code></pre> <p>And it works fine, but it gets very slow when there are a lot of (few hundred or a thousand) nodes in the tree and the user wants to expand or collapse a node. The performance is so bad in these cases (1-2 seconds of calculation on every expand/collapse) because the <code>updateLayout</code> method traverses the full DOM tree under my treeview. I'm wondering is there any other solution for this "stretching" problem which doesn't use this kind of traversing? It would be good if I could solve this problem with some kind of pure CSS-magic, but it doesn't seem to be possible at all...</p> <p><strong>Update:</strong></p> <p>Standard jQuery optimizations (such as extracting the query result to a variable, etc.) doesn't work. For example the following code is not faster than the old one:</p> <pre><code> updateLayout: function (containerWidth) { var self = $(this); var treeviewLinks = self.find('.treeview a').css('width', '').get(); var maxAWidth = -Infinity; for(var i = 0; i &lt; treeviewLinks.length; i++) { var link = $(treeviewLinks[i]); if(link.offset().left + link.outerWidth() &gt; maxAWidth) maxAWidth = link.offset().left + link.outerWidth(); } var targetWidth = containerWidth || $('.treeview').width(); targetWidth = Math.max(targetWidth, maxAWidth); for(var i = 0; i &lt; treeviewLinks.length; i++) { var link = $(treeviewLinks[i]); link.outerWidth(targetWidth - link.offset().left); } } </code></pre> <p>However, I was able to speed up the <code>updateLayout</code> step with using the same width to all nodes in tree:</p> <pre><code> 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); $('&lt;style id="treeViewItemStyle" type="text/css"&gt; #treeview a { width: ' + (targetWidth - 19) + 'px !important; } &lt;/style&gt;') .appendTo('head'); } </code></pre> <p>With this optimization, <code>updateLayout</code> runs faster, but because of the same width, the final width of the container will be bigger then it needs to be. I'm currently looking for other solutions to make it better...</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload