Task
For a minimal "application", write a program that presents a form with three components to the user:
- a numeric input field ("Value")
- a button ("increment"
- a button ("random")
The field is initialized to zero. The user may manually enter a new value into the field, or increment its value with the "increment" button. Entering a non-numeric value should be either impossible, or issue an error message.
Pressing the "random" button presents a confirmation dialog, and resets the field's value to a random value if the answer is "Yes".
This task is very similar to the previously discussed task "Simple Windowed Application", so we will use the script and modify it. This is how it will look like in the end:
A hosted version can be found here.
Defining the GUI elements
In this task, we need a numeric input field that can be modfied by the user, a button called "increment" and another button called "random". Let's define them without putting any logic inside:
(gui '(+NumField) 20 "Value: ")
(gui '(+Button) "increment")
(gui '(+Button) "random")
Define the logic
We want the +NumField
to show us the value of the *Count
variable, and also be able to modify it. We can do this by setting the prefix class +Var
on the *Count
variable:
(gui '(+Var +NumField) '*Count 20 "Value: ")
Secondly, we want the button to increase the '*Count
value. So lets add a function to the button definition:
(gui '(+Button) "increment" '(inc '*Count))
And the prefix class +JS
to avoid the reload of the complete page.
(gui '(+JS +Button) "increment" '(inc '*Count))
As last step, we need to define the random function. PicoLisp has a built in function called rand
which can be used for that purpose:
(rand ['cnt1 'cnt2] | ['T]) -> cnt | flg
Returns a pseudo random number in the range of the positive short numbers
cnt1
andcnt2
(or -2147483648 .. +2147483647 if no arguments are given). If the argument isT
, a boolean valueflg
is returned.
The task description has no specification about the range, so let's use the rand
function without any arguments. When the button is pressed, we set *Count
to the random value.
(gui '(+Button) "random" '(setq *Count (rand)))
There is only one last specification to fulfill: The task description tells us that we need to open a dialog which needs to be confirmed by the user first. form.l
provides a function ask
for this purpose:
(ask Str . Prg)
Creates an alert dialog with a string, a 'Yes'- and a 'No'-button.
Str
is the text that will populate the alert,Prg
is the action triggered by the 'Yes'- button.
As you can see, the pop-up moves the position of all the other components, because it's not an overlay dialog box but a normal <form>
element that is inserted just above the form which created them.
<form enctype="multipart/form-data" ...> ...
<fieldset class="alert"> ...
<span class="ask">Reset to a random value?</span><br/>
<input type="submit" name="*Gui:-1" value="Yes" onmousedown="inBtn(this,1)" onblur="inBtn(this,0)" class="submit" id="i0--1"/>
<input type="submit" name="*Gui:-2" value="No" onmousedown="inBtn(this,1)" onblur="inBtn(this,0)" class="submit" id="i0--2"/>
</fieldset>
</form>
There is not so much we can do about the shifting, but at least we can make sure that it is inserted above instead of next to our form GUI elements by wrapping these into their own <div>
within the form
function:
(<div> "d-flex flex-column bg-light text-center mx-5"
<-- Dialog comes here! -->
(form NIL
(<div> "d-flex justify-content-center text-center my-5"
(gui '...)
(gui '...)
Due to the text-center
class in the <div>
above the dialog it gets centered. Then it looks like this:
Now our form elements get pushed down when the dialog box appears, but not to the side. Finished!
The final source code can be downloaded here, css here.
Top comments (0)