Using the +OnClick Button

The standard PicoLisp GUI in "@lib/form.l" defines a prefix class +OnClick. It can be used in combination with the +Button class.

The name +OnClick is perhaps an unfortunate choice. After all, any button is supposed to react upon a "click". What is meant here is that buttons of this type directly hook into JavaScript onclick events. They take JavaScript code as an argument, to be executed in the browser whenever that button is clicked. This allows to extend the GUI with functionality not available out-of-the-box.

For example, +OnClick was also utilized in the "Single" tab in the article https://picolisp.com/wiki?canvasDrawing, though not explicitly mentioned there.

For the opposite direction, the JavaScript library for the PicoLisp GUI in "@lib/form.js" defines a function lisp(). It enables JavaScript code (in the browser) to call Lisp functions (on the server). This is a security hole, of course, so please make sure that you properly setup the *Allow environment.

Testing It

Using +OnClick is straightforward. It takes a single argument and expects it to be legal JavaScript. For a first test, let's pop up an alert:

   (gui '(+OnClick +Button) "alert('OK')" "Alert")

This creates a button with the label "Alert" in the GUI, which when pressed will display an alert with the text "OK":

onClickAlert.png

Fetching the Browser-Local Time

For something more useful, yet not available in a HTML/HTTP-based GUI without resorting to JavaScript, consider finding out the user's current local time. The GUI in "@lib/form.l" does something similar - in the expires function - to determine the user's time zone.

The local time can be obtained from a Date object, and then passed to a function setTime on the server:

   (gui '(+OnClick +Button)
      "var t = new Date();
         return lisp(this.form, 'setTime',
            t.getHours(), t.getMinutes(), t.getSeconds() )"
      "Now!" )

As mentioned above, setTime should be allowed on the server, and accept three arguments for the hour, minute and second, respectively. For a definition, see the source listing below.

Getting the Browser's Coordinates

In a similar way, we can get the browser's position, if the browser supports the Geolocation API, and if the user permits it. Assuming a setLocation function on the server, accepting the latitude (X) and longitude (Y):

   (gui '(+OnClick +Button)
      "var Form = this.form;
         navigator.geolocation.getCurrentPosition(function(pos) {
            lisp(Form, 'setLocation',
               pos.coords.latitude * 1000000,
               pos.coords.longitude * 1000000 );
         } );
         return false;"
      "Set Location" )

Note that we multiply the coordinates by 1000000, to obtain scaled integers suitable for PicoLisp.

Also note that we explicitly return false from the JavaScript onclick event handler code, to prevent the default behavior associated with that event. This should essentially always be done in such +OnClick handlers, but we omitted it in the Date() case because lisp() already takes care of that.

Complete Source

Here's the full source, complementing the above code fragments:

   # 07sep13abu
   # (c) Software Lab. Alexander Burger

   (allowed ()
      "!home" setTime setLocation "@lib.css" )

   (load "@lib/http.l" "@lib/xhtml.l" "@lib/form.l")

   (de setTime (H M S)
      (set> (: time) (time H M S)) )

   (de setLocation (X Y)
      (set> (: x) X)
      (set> (: y) Y) )

   (de home ()
      (app)
      (action
         (html 0 "OnClick Demo" "@lib.css" NIL
            (form NIL
               (<h3> NIL "OnClick Demo")
               (gui '(+OnClick +Button) "alert('OK')" "Alert")
               (----)
               (<grid> ".--"
                  "Browser Time" (gui 'time '(+Lock +TimeField) 10)
                  (gui '(+OnClick +Button)
                     "var t = new Date();
                        return lisp(this.form, 'setTime',
                           t.getHours(), t.getMinutes(), t.getSeconds() )"
                     "Now!" )
                  NIL NIL NIL
                  "Pos X" (gui 'x '(+Lock +FixField) 6 8)
                  (gui '(+OnClick +Button)
                     "var Form = this.form;
                        navigator.geolocation.getCurrentPosition(function(pos) {
                           lisp(Form, 'setLocation',
                              pos.coords.latitude * 1000000,
                              pos.coords.longitude * 1000000 );
                        } );
                        return false;"
                     "Set Location" )
                  "Pos Y" (gui 'y '(+Lock +FixField) 6 8) ) ) ) ) )

   (de main ())

   (de go ()
      (server 8080 "!home") )

   # vi:et:ts=3:sw=3



After pressing both the "Now!" and "Set Location" buttons, the corresponding GUI fields are filled with the resulting values, and my browser window shows:

onClickFilled.png

https://picolisp.com/wiki/?onclickbutton

30may19    khk
Revision History