# Introduction to Brython

This page shows a few examples of how you can interact with a web page using Python as the scripting language : create new elements, access and modify existing elements, create graphics, animations, send Ajax requests, etc.

The scripts use objects - elements shown in the page, styles applied to these elements, events, etc. - that are described in the Document Object Model (DOM), defined by the W3C. The reference used in this page is the Mozilla Developer Network (MDN) documentation.

Although the DOM is by nature language-independant, most examples in the MDN documentation are written with Javascript, not (yet ;-) in Python. The translation is usually straightforward, since Brython supports all the DOM types and their attributes and methods.

In some cases, Brython adds a more Pythonic syntax : you will discover them by browsing the examples.

More documentation and examples can be found on the Brython site.

`browser` is a Brython-specific module that defines the objects used to interact with the page.

`document` is an object representing the HTML document ; `document[element_id]` is the element with attribute id equal to element_id. In this example, `document["button0"]` is a reference to the button you click on.

`bind(event)` is a method that returns a decorator, applied to the function to call when the event occurs on the element. When the user clicks on the element, this event is called "click". The code means : when the user clicks on the element (here, the button with the text "display an alert box"), call the function `hello()`. The function takes one argument, an object representing the event.

`alert` is used to display small popup windows.

Initial content

The attributes and methods of the elements are described in the Document Object Model (DOM), which is abundantly documented (by Mozilla for instance).

`textContent` is an attribute of Node instances ; it is used to get or set an element's text content.

Brython supports all the DOM methods and attributes ; for text content it provides a shortcut, `text`, so that the function body can also be written :

        def change(event):
            document["zone1"].text = "New Content"

coloured content

Elements have an attribute `style`, which itself has (among many others) the attributes `color` (text color), `backgroundColor` (background color), `fontWeigth` ("bold" or "normal"), `fontSize` (size of the letters, in pixels), etc.

Look here for a reference on CSS.

Note that the attribute names that have a hyphen is CSS are written in camelCase in Python code : for instance, to set the CSS attribute `background-color`, the syntax is `style.backgroundColor`

a random text

Elements have an attribute `classList` with the values set in the attribute `class` of the element.

It is an instance of the class `DOMTokenList`, which supports the methods `add()` and `remove()`.

on / off

`display` is another attribute of `style`. Setting it to `"none"` hides the element.

initial content

This example uses the standard DOM methods to create elements (`document.createElement()`, `createTextNode()`) and append them to other elements or to the document (`Node.appendChild()`).

Note that on the last line, we use the standard DOM method `EventTarget.addEventListener()` : the method `bind()` used in the other examples is Brython-specific.

Also note the use of f-string for string formatting (PEP 448, introduced in Python 3.6) in the line

            txt = document.createTextNode(f" {nb}")

initial content

To create DOM elements, Brython provides the module `browser.html`. It defines classes with the name of all the valid HTML tags in uppercase ; `html.B("message")` creates the element `<B>message<B>`

To include an element inside another one, Brython uses the operator `<=` : think of it as a left arrow, not as "inferior or equal". The use of an operator is more concise and avoids having to use a function call.

- element

We use the standard DOM method insertBefore()

- element

We use the standard DOM method insertBefore() and insert the element after element.nextSibling. If the element is the last in its parent's children, `nextSibling` is `null` so the new element is inserted at the end.

initial content

The attributes of a tag are defined as keyword arguments of the html classes constructor.

Note that the style attribute is passed as a dictionary ; also note that, since `class` is a Python keyword, it can't be used as a key, so we use `Class` instead (tag attributes are case-insensitive).

To build a table, we use the HTML tags `TABLE, TR, TH` and `TD`.

The first attribute passed to the classes defined in `browser.html` is either a string, another instance of a class, or an iterator on such elements.

Here we use a Python generator expression to include several headers (`TH`) in the first row (`TR`) of the table, and the same for the table cells (`TD`) in the next rows.

`clear()` is a method that removes all the element contents.

We build the dropdown menu by a SELECT element, using a generator expression with the OPTION elements displayed in the menu.

When the user changes the selected option in the menu, the event "change" is triggered on the SELECT box. This is done in the line

        dropdown.bind("change", show)

So far we have used the method `bind()` as a decorator for a callback function, with the event name as single argument. It can also be used with the function as the second argument.

In function `show(event)`, `event.target` is the element itself.

A SELECT element has an attribute `selectedIndex`, the rank of the selected item in the list of options, available by its attribute `options`. The OPTION element itself has an attribute `value`, here the option text.

We start by importing the module `math`, the same as in the Python standard distribution.

Canvas is an API for drawing geometric forms in the page. The examples on the MDN pages are written in Javascript but can be easily translated for Brython.

your content here !...

We have seen how to get an element by its id : `document[element_id]`. Here, `document["zone13"]` is the bordered box at the right of the button.

The method `get(selector=css_selector)` provides a way to select elements based on the CSS selector syntax. Passing the name of a tag returns a list of all the elements with this tag ; passing `.zone` returns a list of all the elements whose attribute `class` is set to `"zone"`.

`transform` is another attribute of `style` that can make changes to the element, including a rotation by a specified angle.

The browser window provides 2 functions to start and stop an animation : `requestAnimationFrame` and `cancelAnimationFrame`.

When the user clicks on the button, the animation is started by calling the function `animloop` with an arbitrary argument. `window.requestAnimationFrame`, called with the function itself as argument, returns a reference to the animation. The drawing function, `render()` is called ; the loop is then executed repeatedly under the control of the animation loop.

In `render()`, to put the element at a specific location, we use another `transform` function, `translate(x, y)`. The moving element bounces, and its shape changes, when its position reaches the box borders.

If the user clicks the button again, calling `window.cancelAnimationFrame` on the animation object stops the animation.

drag me

This example uses other mouse events than "click" : "mousedown", "mousemove" and "mouseup".

The mouse position is available by the attributes `x`, `y` of the event object.

The position of an element can be changed by defining its attributes `left` and `top`.

The Storage API allows local storage of key/value pairs.

Notice the use of method `elt.closest(tagName)` to get the first DOM element with the specified tag name above `elt`.

The event "change" on the INPUT field is triggered when the field loses focus, if the value has been modified.

The module `browser.ajax` allows sending Ajax calls, ie sending HTTP requests to a URL and handle the reply without having to reload the page.

Here we use a public API that gives the current position of the International Space Station. The callback function `complete()` is called when the Ajax call has completed ; its argument has an attribute `responseText`, the response sent by the server. In this case, the API tells us that it's a JSON string. We decode it with the module `json` of the standard distribution.

By default, `print()` writes message in the browser console window (to open it, do Ctrl+Maj+K on Firefox, Ctrl+Maj+J on Chrome, F12 on IE, etc).

Like in Python, the output can be reset by setting `sys.stdout` to an object with a method `write()`.

        Love Bites
        Buzzcocks
        UK
        1978

        Turn On The Bright Lights
        Interpol
        USA
        2002

        Visions Of A Life
        Wolf ALice
        UK
        2017

Instead of using the XML modules in Python standard library, it's more efficient to use the Web API DOMParser to parse XML documents.

Brython provides the modules `time` and `datetime` of the standard distribution, but it can also interact with the objects defined by Javascript.

To use such objects, import the object `window` from module `browser` : it is used to get a reference to all the objects defined in the Javascript global namespace.

Because the Javascript object `Date` is a constructor (ie a function that returns new objects with the syntax var date = new Date()), we create Brython objects with the attribute `new`.

We then use the attributes of the Javascript instance of `Date()` such as `getFullYear` with the usual Python syntax.

Similarly, Brython provides the standard Python module `re` for regular expressions, but it can also use the Javascript RegExp and String classes.