[Pas2js] Nyx framework (Mgr. Janusz Chmiel)
mister highball
mr.highball at hotmail.com
Fri Oct 9 20:45:24 CEST 2020
> ...This compiler and units have allowed Me to finally create quiz which can
> monitor even 40 editable fields at The same time. The advantage of this
> approach is, that it is not necessary to fill out questions chronologically.
> Respondent can decide The order. Respondent is not being forced to confirm
> The right answer by using some confirmation button or by even pressing Enter
> key.
> It is excellent dynamic process...
I've put together a demo showing how you could add labels to editable fields (as mentioned in a prior email) and after reading one of your use cases (dynamic quiz fields) I changed it this morning to support a more dynamic approach.
I created the demo using the standard "TBrowserApplication" template and implemented a BuildUI(AInputs) method. the browser app call the BuildUI method in the .DoRun() but first adds a list of input names (think of these as your quiz questions). AInputs is just a string list, so you could populate this list from a website or a database (or anything dynamically). The BuildUI method handles all of the nyx related logic for setting up a user interface object, adding the inputs to the UI, then adding the labels to be "parented" to them, and finally rendering to the dom.
I've pushed this example to the nyx repository, so if you have it cloned, all you would need to do is "git pull". Below I've also listed the important methods as they are right now if it's easier to look at them here, but the full example can be found here:
https://github.com/mr-highball/nyx/tree/master/demos/browser/input-labels
```
procedure TInputLabels.doRun;
var
LInputs : TStringList;
begin
//here we create a stringlist to hold the input "names". these could be
//pulled from a db, web request, or any other dynamic source, but to test
//we'll just add them manually
LInputs := TStringList.Create;
LInputs.Add('First Name');
LInputs.Add('Middle Name');
LInputs.Add('Last Name');
LInputs.Add('Did this question show correctly?');
BuildUI(LInputs);
LInputs.Free;
end;
```
```
procedure TInputLabels.BuildUI(const AInputs: TStrings);
var
I: Integer;
LLayout: INyxLayoutRelational;
LPropLayout : INyxLayoutProportional;
LContainer: INyxContainer;
(*
method to parent a label to an element, used in a "foreach" call
on the UI's elements collection
*)
procedure AddLabelToElements(const AElement : INyxElement);
var
LText: INyxElementStaticText;
LBounds: INyxRelationalBounds;
begin
//create and add the text to the UI
LText := NewNyxStaticText;
FUI.ContainerByIndex(I).Add(LText);
//set the text to the element's name
LText
.UpdateText(AElement.Name)
.UpdateFormat([sfBold]); //we'll bold for emphasis
//setup a bounds that anchors this text element to the input element
LBounds := NewNyxRelationalBounds;
LBounds
.UpdateTop(-40)
.UpdateVertAlignment(vaTop); //anchor to top
//add the text to be managed by the relational layout
LLayout.Add(LText, AElement, LBounds);
end;
(*
this method will setup proportional positions for all of
the input elements based on the index using the following formula:
Position = (Index + 1) * 0.10 (for the top)
*)
procedure PositionInputsByIndex(const AElement : INyxElement);
var
J: Integer;
begin
FUI.ContainerByIndex(I).Elements.IndexOf(AElement, J);
LPropLayout.Add(
AElement,
INyxProportionalBounds(NewNyxProportionalBounds
.UpdateTop(Succ(J) * 0.10)
.UpdateLeft(0.5) //position input to the center of the container
.UpdateHorzAlignment(haCenter))
);
end;
begin
FUI := NewNyxUI;
LLayout := NewNyxLayoutRelational;
LPropLayout := NewNyxLayoutProportional;
LContainer := NewNyxContainer;
//add inputs based on the strings and update the "name" property.
//we'll use this in the AddLabelToElements method as the label text
for I := 0 to Pred(AInputs.Count) do
LContainer.Add(NewNyxInput.UpdateName(AInputs[I]));
//add labels and size the container
FUI
.AddLayout(LLayout, I) //this layout controls the label positioning
.AddLayout(LPropLayout, I) //this layout controls the input positioning
.AddContainer(LContainer, I)
.ContainerByIndex(I)
.UpdateSize( //make the container take up 100% of the screen
NewNyxSize
.UpdateHeight(1)
.UpdateWidth(1)
.UpdateMode(smPercent) //use percent mode
)
.Container
.Elements
.ForEach(@PositionInputsByIndex);
//now that we've added all the inputs render to the screen so they have
//positions, then we need to add the labels and render again (we do this
//because of the dynamic nature of adding labels, normally only one render would be needed)
FUI.Render();
LContainer.Elements.ForEach(@AddLabelToElements);
FUI.Render();
end;
```
-Highball
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/pas2js/attachments/20201009/568278cd/attachment.htm>
More information about the Pas2js
mailing list