Examplained Examples ==================== These are all standalone examples, i.e. they are all you need and should just run as-is. The code for the exaples below can be found in the ``examples`` folder of the git repository. The comments in the code have been removed for clarity but further explanation is provided outside the code. Basic ----- This is the same example shown in the home page but we disect it a little further. It contains the bare minimum for a single-application server. .. code-block:: python :linenos: from jibe import MainApp, Button, Input class ExampleApp(MainApp): def __init__(self, connection): super().__init__(connection) self.children = [ Button(), Input(value='The value') ] self.children[0].register('click', self.on_button_click) def on_button_click(self, source, message): self.children[1].value = "Hello!" if __name__ == "__main__": ExampleApp.run(port=8881) .. raw:: html This example shows a standalone Jibe application that we have defined as ``ExampleApp``, starting on line 3. It does not require a separate web server. The server for the application is started on line 19 and it listens on port 8881 of the machine it is started on. You can access it by going to ``http://localhost:8881`` on any web browser. The application is defined by creating a class which inherits from the ``MainApp`` class. All Jibe applications are defined in this way. Jibe relies heavily on object orientation, so if you are unfamiliar with concepts like classes and inheritance we suggest that you strengthen your grasp of these concepts first. The ``MainApp`` class contains all the complexity that makes a Jibe application. It is there for you to access it when you need it, otherwise it is hidden to make your code clearer. To put the ``MainApp``'s machinery into acction we must call it's constructor (line 6) in our constructor (lines 5-12). Since it requires a ``connection`` parameter, our constructor must also accept this same parameter. An important detail to know at this point is that the ``MainApp`` class also inherits from ``Widget``. Therefore, ``ExampleApp`` **is a** ``Widget``, as all Jibe applications are. Widgets can have child widgets, which allows us to build complex widgets out of simpler widgets simply by combining them together as children of the complex widget. In this case, our application (or top-level widget) contains two children, a ``Button`` and an ``Input``. On lines 8 to 11 we creates instances of these two classes, we put them together in a list and assign it to the ``children`` variable of the application. The ``children`` variable is special in the sense that it is "aware" of its changes. As soon as it is assigned to (or changed), it communicates with the browser to update the widget's representation there. On line 12 we specify that we want to react to `click` events on the button. The ``register`` method of widgets takes the name of the event and a function (or method) to call when it happens. On lines 14 and 15 we defined the "event handler" that we specified on line 12. Event handlers take 2 parameter: ``source`` is the widget that triggered the event (it will allways be that specific button in this case), and ``message`` is the message that was sent from the server that alerted us that this event has happened. The message may contain useful additional information about the event (which we don't need in this case). The body of ``on_button_click`` is an assignment to the ``value`` variable of the ``Input`` widget. This variable is a **property**. Properties are special variables, similar to ``children`` in that they are also "aware" of changes, causing an immediate update on the browser. Therefore, when the button is clicked, the value of the Input, "The value", changes to "Hello!". MultiApp -------- This example illustrates how to have a multiple-application server. For web platforms that require a little more complexity is it convenient to have the ability to combine multiple Jibe applications together. .. code-block:: python :linenos: from jibe import MainApp, Button, Input, CheckBox, \ Redirect, MultiApp class ExampleAppA(MainApp): def __init__(self, connection): super().__init__(connection) self.btn_go2b = Button(label='Go to B') self.btn = Button() self.input = Input(value='The value') self.redir = Redirect() self.children = [self.btn_go2b, self.btn, self.input, self.redir] self.btn.register('click', self.on_button_click) self.btn_go2b.register("click", self.on_go2b) def on_button_click(self, source, message): self.input.value = "Hello!" def on_go2b(self, source, message): self.redir.redirect('/b') class ExampleAppB(MainApp): def __init__(self, connection): super().__init__(connection) self.btn_go2a = Button(label='Go to A') self.chk = CheckBox() self.btn = Button() self.redir = Redirect() self.children = [self.btn_go2a, self.chk, self.btn, self.redir] self.btn_go2a.register("click", self.on_go2a) self.btn.register("click", self.on_btn_click) def on_btn_click(self, source, message): self.chk.checked = True def on_go2a(self, source, message): self.redir.redirect('/a') if __name__ == "__main__": mapp = MultiApp( a=ExampleAppA, b=ExampleAppB ) mapp.run() Application ``ExampleAppA`` at ``http://localhost:8881/a``: .. raw:: html Apllication ``ExampleAppB`` at ``http://localhost:8881/b``: .. raw:: html A Jibe ``MultiApp`` allows us to serve multiple Jibe ``MainApp`` together. On lines 49 to 52 we create an instance of ``MultiApp`` and pass the individual applications as keyword parameter to the constructor. The keywords, ``a`` and ``b`` in this case, define the relative URLs of the apps. Asside from the use of ``MultiApp``, there is little more to this example. However, we make use of of the ``Redirect`` widget, which is invisible on the page, but as its name implies, allow us redirect the browser to another URL. In this case, we use it to jump from one application to the other in response to the `click` event of the respective buttons, on lines 24 and 46.