Jemt / Fit.UI

Fit.UI is a JavaScript based UI framework built on Object Oriented principles
http://fitui.org
GNU Lesser General Public License v3.0
19 stars 7 forks source link

SelectAll in DropDown - poor performance #82

Closed FlowIT-JIT closed 4 years ago

FlowIT-JIT commented 4 years ago

Selecting all nodes in a TreeView based DropDown control performs poorly when thousands of nodes are presented in the TreeView.

Demo data (16276 nodes): data.json.zip. Generated using: https://next.json-generator.com/NydW4rJ2D

Code to reproduce problem:

// Create DropDown loading data from JSON file

dd = new Fit.Controls.WSDropDown("WSDropDown1");
dd.Url("data.json"); // Very large data set
dd.MultiSelectionMode(true);
dd.Width(400);
dd.DropDownMaxHeight(150);
dd.InputEnabled(true);
dd.GetTreeView().On
dd.OnFocus(function(sender) { console.log("Gained focus"); });
dd.OnBlur(function(sender) { console.log("Focus lost"); });
dd.Render(document.body);

// Register ContextMenu (right-click menu) with Select/Deselect All feature

ctxNode = null;
dd.GetTreeView().OnContextMenu(function(sender, node)
{
    ctxNode = node;
});
ctx = new Fit.Controls.ContextMenu();
ctx.AddChild(new Fit.Controls.ContextMenuItem("Select all", "SelectAll"));
ctx.AddChild(new Fit.Controls.ContextMenuItem("Deselect all", "DeselectAll"));
ctx.OnSelect(function(sender, item)
{
    var select = item.Value() === "SelectAll";
    dd.GetTreeView().SelectAll(select, ctxNode);
    ctx.Hide();
});
dd.GetTreeView().ContextMenu(ctx);

image

Triggering Select All on "Root node" using the right-click menu is painfully slow for this amount of data, especially on Internet Explorer.

Obviously it is hardly a valid use case selecting thousands of nodes. But if the feature is exposed to the users, they will eventually trigger it - just to try it or by accident.

When doing functional testing to verify that the improvements have not broken anything, relace dd.Url("data.json") in the example code above with the following code to test SelectAll with remote children (partially loaded TreeView):

dd.Url("https://fitui.org/demo/GetUsers.php");
dd.JsonpCallback("JsonpCallback"); // Loading data from foreign domain
dd.OnRequest(function(sender, eventArgs)
{
    eventArgs.Request.SetParameter("NoCache", Fit.Data.CreateGuid());
    eventArgs.Request.SetParameter("Search", dd.GetInputValue());
    eventArgs.Request.SetParameter("Parent", eventArgs.Node !== null ? eventArgs.Node.Value() : "");
});
FlowIT-JIT commented 4 years ago

Something that greatly impact performance is DOM manipulation that triggers reflows.

Easy fixes - reduce reflows by:

Registered MutationObservers and timers may also slightly affect performance. Consider support for temporary suspension? Same applies for type validation which is cheap but not free: Fit.Validation.Enabled(false).