createDocumentFragment

Been searching around for performance tips and ran across the general idea of using documentfragments to marshall new DOM elements that are being created so they can be added all at once rather than individually.

I can't seem to figure out how to get this to work in TMS WEB Core though? I can create a TJSDocumentFragment, but how do you create a new, say, TWebButton and have it attached to the fragment instead of the document? And in the examples elsewhere, they create an element and then use fragment.appendchild, but here that seems to require a JSNode value which isn't what is created normally?

We have used fragments in underlying control code (you can lookup on fragment in Core Source folder) but haven't worked with trying to map control classes on HTML elements in document fragments. Not sure it is technically possible. We'll need to allocate time to investigate this deeper.

Alright. Then do you have any suggestions on how to create a lot of objects (TWebButtons in my case) really quickly? And given your post a few minutes ago that dramatically sped up populating TWebComboBoxes, maybe you've got some ideas here, too?

I'm just adding them to a TWebPanel like this:

    NewButton                 := TWebButton.Create(SubPanel+'-'+IntToStr(i));
    NewButton.Parent          := Panel;
    NewButton.Caption         := Classes[i];
    Newbutton.Tag             := i;
    NewButton.WidthStyle      := ssAuto;
    NewButton.HeightStyle     := ssAuto;
    NewButton.ElementPosition := epRelative;
    NewButton.ElementClassName := 'btn btn-secondary btn-sm m-1 lh-1 Small BtnClass';
    NewButton.OnClick         := UseButton;
    NewButton.DragMode        := dmAutomatic;

But dozens at a time.

This test code creates 100 buttons in approx. 40ms here:

procedure TForm1.WebButton1Click(Sender: TObject);
var
  i,j: integer;
  btn: TWebButton;
begin
  console.time('controls');
  BeginUpdate;

  for i := 0 to 9 do
  begin
    for j := 0 to 9 do
    begin
      btn := TWebButton.Create(Self);
      btn.Top := i * 30 + 100;
      btn.Left := j * 96;
      btn.Caption := 'btn'+i.ToString+':'+j.ToString;
      btn.Parent := Self;
    end;
  end;
  EndUpdate;
  console.timeend('controls');
end;

The BeginUpdate/EndUpdate improves performance with +/- factor 5.
It is also beneficial to set the Parent as last property.

Deferring setting ElementClassName seemed to be a big help as well!

Thanks for these tips. Improves things dramatically.

Andrew.

1 Like