I. Introduction▲
Créer en 2014, Brython est, pour résumer grossièrement, un interpréteur Python, codé en javascript.
Le but est de pouvoir remplacer aisément le javascript de nos pages web par du code Python 3.
Bien entendu, en tant qu'interprété, il ne saura être aussi rapide que du code natif. Mais il existe nombre de cas ou il sera suffisant.
Comme tout projet récent, il possède encore quelques soucis de jeunesse. Néanmoins, vous aurez l'occasion, dans cet article, de constater qu'il s'agit d'un projet prometteur, et qu'il saura répondre à de nombreux besoins.
Que vous désiriez vous mettre au web sans apprendre javascript, ou simplement curieux, je vous invite à commencer cet article.
Cet article est écrit pour Python3.x. Des différences peuvent exister avec Python2.x.
Cet article fait référence à des notions HTML et CSS. Il est donc recommandé que les lecteurs disposent déjà de quelques notions sur ces langages.
L'intégralité de vos fichiers doivent être encodés en UTF8
II. Installation▲
Brython est disponible sur pypi. Aussi, l'installation sera on ne peux plus simple.
pip install brython
puis dans un répertoire vide, exécutez :
python -
m brython --
install
A partir de là, si vous allez voir l'installation effectuée, vous aurez alors les trois fichiers suivants :
- brython.js : L'interpréteur brython même, à inclure dans le code HTML
- brython_stdlib.js : Contient toute la librairie standard pour l'interpréteur
- demo.html : Une page de démonstration avec quelques exemples intégrés
III. Les bases▲
III-A. Les mots clés▲
Les mots clés Python suivants, sont les seuls à être gérés pour le moment :
|
|
|
III-B. Les fonctions intégrées de base▲
Les fonctions intégrées dans Brython, de base, sont les suivantes :
|
|
|
Voici quelques précisions sur certaines de ces fonctions :
- del() : contrairement à du Python pur, cette fonction n'est pas automatiquement appelée lorsqu'un objet n'est plus utilisé. Il faut donc l'appeler manuellement.
- open() : cette fonction prend comme argument l'url du fichier à ouvrir. Ce fichier doit être contenu dans le même domaine. Les méthodes liées disponibles sont " read ", " readlines ", " seek ", " tell ", " close ".
- print() : par défaut la sortie s'effectue dans la console web
III-C. import de code externe▲
Dans n'importe lequel de vos scripts Brython, vous avez la possibilité d'importer du code externe Python, à condition que ce dernier soir positionné à la racine de votre projet web.
Dans vos scripts Brython, lorsqu'un import est effectué, Brython recherche le module/package demandé dans l'ordre suivant :
- libs pour le code javascript et Lib pour Python
- Lib/site-packages dans Python
- Le dossier de la page courante
III-D. Intégration aux pages web▲
Afin de pouvoir utiliser Brython dans votre code HTML, il vous faudra agir à deux niveaux :
- Spécifier qu'il faut utiliser Brython au lieu de javascript
- Spécifier le fichier contenant votre code Brython
Voici un aperçu type d'un fichier HTML :
2.
3.
4.
5.
6.
7.
8.
9.
10.
<html>
<head>
<script type
=
"text/javascript"
src
=
"brython.js"
></script>
<script type
=
"text/javascript"
src
=
"brython_stdlib.js"
></script>
</head>
<body onload
=
"brython()"
>
<script type
=
"text/python"
src
=
"test.py"
></script>
<input id
=
"zone"
><button id
=
"mybutton"
>
click!</button>
</body>
</html>
Les chemins des fichiers sont ici relatif.
Ligne 3, nous retrouvons l'import de l'interprêteur Brython. Une fois ce dernier importé, il faut l'activer. C'est la raison d'être de l'appel à la fonction " brython() " dans la balise " body ", ligne 5. Enfin, ligne 6, nous stipulons dans quel fichier trouver notre code Brython.
il est possible de passer des options lors de l'appel à la fonction " brython() ".
Les options possibles sont les suivantes :
- 0 : valeur par défaut. Aucun débogage activé
- 1 : Les messages d'erreur sont imprimés dans la console du navigateur
- 2 :La traduction du code Python en code javascript est affichée dans la console
- 10 : La traduction du code Python et des modules importés est affichée dans la console
III-E. Optimisation post développement▲
Afin d'optimiser les performances de vos développements Brython, l'outil vous offre la possibilité de générer un fichier " brython_modules.js " qui ne contiendra que le strict nécessaire pour votre projet.
Pour cela, depuis une console, placez vous dans le dossier racine de votre projet, puis exécutez la commande suivante :
python -m brython -modules
Il ne vous reste alors plus qu'à placer le fichier généré à la racine de votre projet, puis à remplacer, dans vos fichiers HTML, la ligne
<script type
=
"text/javascript"
src
=
"brython_stdlib.js"
></script>
par la ligne
<script type
=
"text/javascript"
src
=
"brython_modules.js"
></script>
III-F. Compilation▲
Afin de disposer directement su code javascript, il faut appeler la fonction 10 dans l'appel de " Brython(10) ".
Ce faisant, le code javascript équivalent sera écrit dans la console. Il ne vous restera alors plus qu'à le copier/coller dans un fichier et à mettre à jour vos pages web.
III-G. Hello world▲
Pour ceux qui ne le saurait pas, " document " est un terme désignant le contenu d'une page web.
La première chose à faire est donc d'importer le nécessaire donnant accès au document.
2.
from
browser import
document
document <=
"Hello world !"
Ici l'opérateur " <= " ne signifie pas " inférieur ou égal " mais " ajouter le contenu suivant ".
III-H. Fonctionnalités basiques▲
III-H-1. Le paquet browser▲
Le paquet " browser " définit les noms et modules intégrés à Brython. Voici les principales méthodes. Nous en verrons d'autres par la suite.
Méthode |
Description |
browser.alert(<message>) |
Affiche le message dans une pop-up |
browser.confirm(<message>) |
Affiche le message dans une pop-up. La pop-up possède deux boutons : OK et ANNULER. Retourne True si OK, False sinon. |
browser.document |
Renvoie un objet représentant le document HTML |
browser.prompt(<message>) |
Affiche le message dans une pop-up. La pop-up possède une zone de saisie. |
browser.window |
Renvoie un objet représentant la fenêtre du navigateur. |
III-H-2. Afficher une pop-up d'alerte▲
2.
from
browser import
alert
alert
(
"Hello !"
)
III-H-3. Afficher une fenêtre d'impression▲
Il suffit d'appeler la méthode print de window
2.
3.
from
browser import
window
# ...
window.print
(
text)
IV. Les événements▲
Nous allons voir ici les divers événements gérés par Brython.
IV-A. Se connecter / se déconnecter à un événement▲
Vous avez le choix d'écouter ou non les divers événements, via les mots clés suivant:
- bind
- unbind
Le premier argument doit être le type d'événement auquel il doit réagir. Le deuxième est la fonction à appeler. Cette fonction ne devra prendre en compte qu'un seul argument : l'évènement qui l'appel, souvent abrégé en " ev ".
IV-A-1. Attributs▲
Voici les attributs de " ev " :
Attribut |
Description |
bubbles |
un booléen qui indique si l'élément se propage aux parents de l'élément sur lequel l'événement s'est produit |
cancelable |
un booléen qui indique si on peut annuler l'événement |
currentTarget |
l'élément sur lequel on est en train de traiter l'événement |
defaultPrevented |
booléen qui indique si on a appelé la méthode preventDefault() sur l'élément |
eventPhase |
indique quelle phase du flux d'événement est en cours de traitement |
target |
l'élément sur lequel l'événement s'est produit |
timeStamp |
la date/heure à laquelle l'événement s'est produit (en millisecondes depuis le 1/1/1970 à 0h) |
type |
le type d'événement |
Par exemple, pour accéder à l'élément sur lequel l'évènement s'est produit, il vous faudra saisir " ev.target ".
IV-A-2. Code exemple▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
from
browser import
document
from
browser import
alert
def
myevent
(
ev):
alert
(
'ça marche !'
)
def
compteur
(
):
alert
(
'
%s
événement(s) attaché(s) à "click"'
%
len(
document['myblock'
].events
(
'click'
)))
def
attache
(
ev):
document['myblock'
].bind
(
'click'
, myevent)
compteur
(
)
document['mymessage'
].text=
'événement attaché, cliquer pour voir...'
def
detache
(
ev):
if
document['myblock'
].events
(
'click'
):
document['myblock'
].unbind
(
'click'
, myevent)
compteur
(
)
document['mymessage'
].text=
'clic désactivé'
document['attache'
].bind
(
'click'
, attache)
document['detache'
].bind
(
'click'
, detache)
IV-B. Souris▲
IV-B-1. Événement▲
Les événements disponibles pour le clavier sont les suivants :
Évenement |
Description |
mouseenter |
la souris entre dans la zone couverte par l'élément, ou un de ses descendants |
mouseleave |
la souris sort de la zone couverte par l'élément et par ses descendants |
mouseover |
la souris entre dans la zone couverte par l'élément |
mouseout |
la souris quitte la zone couverte par l'élément |
mousemove |
la souris se déplace sur l'élément |
mousedown |
appui sur le bouton gauche de la souris |
mouseup |
relâchement du bouton gauche de la souris |
click |
clic : appui puis relâchement du bouton gauche de la souris |
dblclick |
double clic |
Les événments " mouseenter " et " mouseleave " sont déclenchés quand la souris entre ou sort d'un élément. Si un élément en englobe d'autres, l'événement est déclenché à chaque fois que la souris entre ou sort d'un élément fils.
La différence avec mouseenter et mouseleave est qu'une fois que la souris est entrée dans un élément, l'événement n'est pas déclenché sur les éléments fils
IV-B-2. Attributs▲
Attribut |
Description |
button |
le numéro du bouton sur lequel on a appuyé |
buttons |
indique sur quels boutons de la souris on a appuyé pour déclencher l'événement.
Si on appuie sur plus d'un bouton, la valeur de buttons est combinée pour produire un nouveau nombre. Par exemple, si on appuie sur le bouton droit (2) et sur la roue (4), la valeur est égale à 2|4, soit 6 |
x |
la position de la souris par rapport au bord gauche de la fenêtre (en pixels) |
y |
la position de la souris par rapport au bord haut de la fenêtre (en pixels) |
clientx |
la position de la souris par rapport au bord gauche de l'élément dans lequel la souris se trouve au moment du clic (en pixels) |
clienty |
la position de la souris par rapport au bord haut de l'élément dans lequel la souris se trouve au moment du clic (en pixels) |
IV-B-3. Code exemple▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
from
browser import
document
def
_mouseenter
(
ev):
document["trace1"
].text =
'entrée dans
%s
'
%
ev.currentTarget.id
def
_mouseleave
(
ev):
document["trace1"
].text =
'sortie de
%s
'
%
ev.currentTarget.id
document["jaune1"
].bind
(
'mouseenter'
,_mouseenter)
document["jaune1"
].bind
(
'mouseleave'
,_mouseleave)
document["bleu1"
].bind
(
'mouseenter'
,_mouseenter)
document["bleu1"
].bind
(
'mouseleave'
,_mouseleave)
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
from
browser import
document
def
_mouseover
(
ev):
document["trace2"
].text =
'entrée dans
%s
'
%
ev.currentTarget.id
def
_mouseout
(
ev):
document["trace2"
].text =
'sortie de
%s
'
%
ev.currentTarget.id
document["jaune2"
].bind
(
'mouseover'
,_mouseover)
document["jaune2"
].bind
(
'mouseout'
,_mouseout)
document["bleu2"
].bind
(
'mouseover'
,_mouseover)
document["bleu2"
].bind
(
'mouseout'
,_mouseout)
2.
3.
4.
5.
6.
from
browser import
document
def
_mousemove
(
ev):
document["trace3"
].text =
'coordonnées :
%s
,
%s
'
%(
ev.x,ev.y)
document["vert"
].bind
(
'mousemove'
,_mousemove)
IV-C. Clavier▲
IV-C-1. Événements▲
Évenement |
Description |
input |
déclenché quand la valeur d'un élément <input> ou <textarea> est modifié |
keydown |
appui sur une touche quelconque du clavier |
keypress |
appui sur une touche du clavier qui produit un caractère. Par exemple, quand on entre Ctrl+C au clavier, l'événement keypress n'est déclenché qu'au moment où on appuie sur C, alors que keydown est déclenché dès l'appui sur Ctrl |
keyup |
relâchement d'une touche enfoncée |
IV-C-2. Attributs▲
Attribut |
Description |
altKey |
booléen, indique si la touche Alt (ou Option sur Mac) était enfoncée quand l'événement clavier a été déclenché |
charCode |
Le numéro de référence Unicode pour la touche. Cet attribut n'est utilisable que pour l'événement keypress |
ctrlKey |
booléen, indique si la touche Ctrl était enfoncée quand l'événement clavier a été déclenché. |
keyCode |
un code numérique dépendant du système et de l'implémentation, caractérise la clé enfoncée |
shiftKey |
booléen, indique si la touche Majuscule était enfoncée quand l'événement clavier a été déclenché |
which |
un code numérique dépendant du système et de l'implémentation, caractérise la clé enfoncée |
IV-C-3. Code exemple▲
2.
3.
4.
5.
6.
7.
from
browser import
document as
doc
def
altKey
(
ev):
doc["traceAltKey"
].text =
'altKey :
%s
'
%
ev.altKey
# le champ de saisie a comme id "altKey"
doc['altKey'
].bind
(
'keypress'
, altKey)
2.
3.
4.
5.
6.
7.
8.
9.
from
browser import
document as
doc
def
charCode
(
ev):
trace =
doc["traceCharCode"
]
char =
chr(
ev.charCode)
trace.text =
'charCode :
%s
, '
%
ev.charCode
trace.text +=
'character :
%s
'
%
char
doc['charCode'
].bind
(
'keypress'
, charCode)
2.
3.
4.
5.
6.
7.
8.
from
browser import
document as
doc
def
ctrlKey
(
ev):
doc["traceCtrlKey"
].text =
'ctrlKey :
%s
'
%
ev.ctrlKey
ev.preventDefault
(
)
doc['ctrlKey'
].bind
(
'keypress'
, ctrlKey)
Notez que ev.preventDefault() est appelé pour éviter le comportement par défaut associé à certains raccourcis clavier qui utilisent la touche Ctrl
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
from
browser import
document as
doc
def
keyCode
(
ev):
trace =
doc["traceKeyCode"
]
trace.text =
'event
%s
'
%
ev.type
trace.text +=
', keyCode :
%s
'
%
ev.keyCode
ev.stopPropagation
(
)
doc['keyCodeKeydown'
].bind
(
'keydown'
, keyCode)
doc['keyCodeKeypress'
].bind
(
'keypress'
, keyCode)
doc['keyCodeKeyup'
].bind
(
'keyup'
, keyCode)
2.
3.
4.
5.
from
browser import
document as
doc
def
shiftKey
(
ev):
doc["traceShiftKey"
].text =
'shiftKey :
%s
'
%
ev.shiftKey
doc['shiftKey'
].bind
(
'keypress'
, shiftKey)
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
from
browser import
document as
doc
trace =
doc["traceWhich"
]
def
which
(
ev):
trace.html =
'event :
%s
<br>'
%
ev.type
trace.html +=
'which :
%s
<br>'
%
ev.which
if
ev.type ==
'keypress'
:
trace.html +=
'character :
%s
'
%
chr(
ev.which)
doc['whichKeydown'
].bind
(
'keydown'
, which)
doc['whichKeypress'
].bind
(
'keypress'
, which)
doc['whichKeyup'
].bind
(
'keyup'
, which)
IV-D. Focus▲
IV-D-1. Événements▲
Évenement |
Description |
blur |
un élément a perdu le focus |
focus |
un élément a reçu le focus |
IV-D-2. Code exemple▲
IV-E. Glisser/déposer▲
IV-E-1. Événements▲
Évenement |
Description |
drag |
Cet évènement est déclenché à la source du glisser-déposer, l'élément sur lequel l'évènement dragstart a été déclenché |
dragend |
La source du glisser-déposer recevra un évènement de ce type lorsque l'opération de glisser-déposer est terminée, qu'elle se soit bien déroulée ou non |
dragenter |
Déclenché lorsque le pointeur de la souris est déplacée pour la première fois au dessus d'un élément pendant le glisser-déposer. Un écouteur d'évènement pourrait alors indiquer si le dépôt des données courantes est autorisée ou non sur cette zone. Si aucun écouteur n'a été défini, ou si ce dernier n'entraîne aucune action, alors, le dépôt n'est par défaut, pas autorisé. C'est également l'évènement à prendre en charge pour donner des retours à l'utilisateur quand à la possibilité qu'il a déposer le contenu du glisser-déposer en affichant une surbrillance ou un marqueur d'insertion |
dragleave |
Cet évènement est déclenché quand la souris quite un élément durant un glisser-déposer. Les écouteurs évènement devraient retirer toute surbrillance ou marqueur d'insertion de cette zone |
dragover |
Cet évènement est déclenché lorsque la souris est déplacée au dessus d'un élément durant un glisser-déposer. La plupart du temps, cet évènement est utilisé pour les mêmes buts que l'évènement dragenter |
dragstart |
Déclenché sur un élément lorsque qu'un glisser-déposer est entrepris. L'utilisateur requiert la possibilité de glisser-déposer l'élément sur lequel cet évènement est déclenché |
drop |
L'évènement drop est déclenché sur l'élément sur lequel le dépôt a été effectué à la fin de l'opération de glisser déposer. Un écouteur d'évènement devrait être responsable de la récupération des données sources du glisser-déposer et de leur insertion sur la zone de dépôt. Cet évènement ne sera déclenché que si le dépôt est désiré. Il ne sera pas déclenché si l'utilisateur annule ce dernier en pressant, par exemple, sur la touche "Echap" de son clavier ou si le bouton de la souris a été relâché alors que le curseur était au-dessus d'une zone pour laquelle le glisser-déposer n'était pas autorisé |
IV-E-2. Attributs▲
Attribut |
Description |
dataTransfer |
un "magasin de données" utilisé pour transporter des informations pendant le processus de glisser-déposer |
Attribut
|
Description |
dropEffect |
Une chaine qui représente l'effect qui sera utilisé, il doit toujours être une des valeurs possibles de effectAllowed.
Affecter une autre valeur n'a aucun effet et ne modifie pas la valeur courante. |
effectAllowed |
Une chaine qui spécifie les effets autorisés pour le déplacement. On peut le définir dans l'événement dragstart pour indiquer les effets souhaités pour la source, et dans les événements dragenter et dragover pour insiquer les effets souhiatés pour la cible. La valeur n'est pas utilisée pour les autres événements.
Affecter une autre valeur n'a aucun effet et ne modifie pas la valeur courante. |
files |
La liste de tous les fichiers locaux disponibles pour le transfert de données. Si l'opération de déplacement n'implique pas de glisser-déposer de fichiers, cette propriété est une liste vide. Une tentative d'accès à un élément de cette liste avec un index non valide renvoie None. |
getData(type) |
Récupère la donnée pour un type donné, ou une chaine vide si la donnée pour ce type n'existe pas ou que l'attribut dataTransfer ne contient aucune donnée |
setData(type, valeur) |
Affecte une valeur à un type donné. S'il n'y a pas de données pour ce type, elle est ajoutée à la fin, de façon que le dernier élément de la liste des types sera le nouveau format. Si la donnée pour ce type existe déjà, la valeur courante est remplacée à la même position. Autrement dit, l'ordre de la liste des types n'est pas modifiée quand on change la valeur pour un type. |
types |
La liste des types de formats des données stockées pour le premier élément, dans l'ordre où les données ont été ajoutées. Si aucune donnée n'a été ajoutée, cette propriété est une liste vide. |
IV-E-3. Code exemple▲
V. Gestion des éléments HTML▲
V-A. Balises HTML gérées▲
V-A-1. HTML4▲
|
|
|
|
V-A-2. HTML5▲
|
|
|
|
V-B. Accéder à un élément▲
V-B-1. Par son id▲
2.
from
browser import
document
data =
document["data"
]
V-B-2. Par sa balise▲
2.
3.
from
browser import
html
# ...
links =
document[html.A]
V-B-3. Par son nom▲
2.
3.
from
browser import
html
# ...
tmp =
elt.get
(
name=
"Hello"
)
V-B-4. Par son sélecteur CSS▲
2.
3.
from
browser import
html
# ...
tmp =
elt.get
(
selector=
S)
V-C. Insertion d'un élément▲
V-C-1. A la suite▲
2.
3.
4.
5.
6.
7.
8.
from
browser import
document, html
element =
document["zone6"
]
nb =
0
def
change
(
event):
global
nb
element <=
html.B
(
" {}"
.format
(
nb))
nb +=
1
document["button6"
].bind
(
"click"
, change)
V-C-2. Avant un autre élément▲
2.
3.
4.
5.
6.
7.
8.
9.
from
browser import
document, html
ul =
document["zone61"
].get
(
selector=
"ul"
)[0
]
element =
ul.get
(
selector=
"li"
)[0
]
nb =
0
def
change
(
event):
global
nb
nb +=
1
ul.insertBefore
(
html.LI
(
f"element before
{nb}
"
), element)
document["button61"
].bind
(
"click"
, change)
V-C-3. Après un autre élément▲
2.
3.
4.
5.
6.
7.
8.
9.
from
browser import
document, html
ul =
document["zone62"
].get
(
selector=
"ul"
)[0
]
element =
ul.get
(
selector=
"li"
)[0
]
nb =
0
def
change
(
event):
global
nb
nb +=
1
ul.insertBefore
(
html.LI
(
f"element after
{nb}
"
), element.nextSibling)
document["button62"
].bind
(
"click"
, change)
V-C-4. Un tableau HTML▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
from
browser import
document as
doc
from
browser.html import
TABLE, TR, TH, TD
table =
TABLE
(
)
row =
TR
(
) # create a row
# add header cells
row <=
TH
(
"Pays"
)
row <=
TH
(
"Capitale"
)
table <=
row # add the row to the table
# add a row
row =
TR
(
)
row <=
TD
(
"Russie"
)+
TD
(
"Moscou"
)
table <=
row
# erase initial content
doc['zone'
].clear
(
)
# insert table in the element
doc['zone'
] <=
table
V-C-5. Insérer un menu déroulant▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
from
browser import
document, alert, html
def
show
(
event):
dropdown =
event.target
num =
dropdown.selectedIndex
alert
(
"Selected: {}"
.format
(
dropdown.options[num].value))
def
insert_dropdown
(
event):
document["zone12"
] <=
'Your choice : '
dropdown =
html.SELECT
(
html.OPTION
(
"Choice {}"
.format
(
i)) for
i in
range(
5
))
dropdown.bind
(
'change'
, show)
document["zone12"
] <=
dropdown
document['button12'
].bind
(
'click'
, insert_dropdown)
V-C-6. Insérer une image▲
2.
3.
4.
5.
6.
from
browser import
document, html
logo =
"https://www.python.org/static/community_logos/python-logo-master-v3-TM.png"
def
insert_image
(
event):
document["zone9"
].clear
(
)
document["zone9"
] <=
html.IMG
(
src=
logo, height=
50
)
document["button9"
].bind
(
"click"
, insert_image)
V-D. Modifier un élément▲
V-D-1. Modifier le texte▲
2.
3.
from
browser import
document
# ...
document["zone1"
].textContent =
"New content"
V-D-2. Modifier le style▲
2.
3.
4.
5.
6.
7.
8.
from
browser import
document
element =
document["zone2"
]
style =
element.style
color =
style.color
style.color =
"#cc8"
if
color ==
"blue"
else
"blue"
style.backgroundColor =
"gray"
if
color ==
"blue"
else
"#aad"
style.fontWeight =
"bold"
if
color ==
"blue"
else
"normal"
style.fontSize =
"18px"
if
color ==
"blue"
else
"14px"
V-D-3. Modifier la classe▲
2.
3.
4.
5.
6.
from
browser import
document
element =
document["zone_class"
]
element.classList.add
(
"down"
)
if
"down"
in
element.classList:
element.classList.remove
(
"down"
)
element.classList.add
(
"up"
)
V-D-4. Modifier la mise en forme HTML▲
2.
3.
4.
5.
6.
from
browser import
document, html
document['zone'
].clear
(
)
document['zone'
] <=
html.H1
(
"Introduction à Brython"
)
document['zone'
] <=
html.H4
(
html.I
(
"Python dans le navigateur"
))
document['zone'
] <=
html.B
(
"Salut !"
)
V-D-5. Ajouter un descendant à un élément▲
2.
3.
from
browser import
document, html
# ...
document['zone'
] <=
html.INPUT
(
Id=
"data"
)
V-D-6. Supprimer un élément▲
2.
zone =
document['zone'
]
del
zone
V-E. Opérations sur élément▲
V-E-1. Cacher/afficher un élément▲
2.
3.
4.
from
browser import
document
display =
document["zone3"
].style.display
if
display ==
‘inline' :
document["zone3"].style.display = "none"
Ici, nous pouvons constater que placer le style.display à "none" revient à le cacher.
V-E-2. Animer un élément▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
from
browser import
document, window
moving =
document["rot15"
]
x =
0
dx =
3
run =
None
def
change
(
event):
global
run
if
run is
None
:
# start animation
animloop
(
1
)
else
:
# stop animation
window.cancelAnimationFrame
(
run)
run =
None
def
render
(
):
global
x, dx
moving.style.transform =
"translate({}px,0)"
.format
(
x)
x +=
dx
if
x >
document["zone15"
].offsetWidth-
moving.offsetWidth:
dx =
-
dx
moving.html =
"◄"
# left triangle
elif
x <=
0
:
dx =
-
dx
moving.html =
"►"
# right triangle
def
animloop
(
t):
global
run
run =
window.requestAnimationFrame
(
animloop)
render
(
)
document['button15'
].bind
(
'click'
, change)
V-E-3. Effectuer une rotation sur un élément▲
2.
3.
4.
5.
6.
7.
8.
from
browser import
document, html
moving =
document["rot14"
]
angle =
10
def
change
(
event):
global
angle
moving.style.transform =
"rotate({}deg)"
.format
(
angle)
angle +=
10
document['button14'
].bind
(
'click'
, change)
V-E-4. Déplacer un élément avec une souris▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
from
browser import
document
class
ElementMove:
def
__init__
(
self, moving):
"""Make "moving" element movable with the mouse"""
self.moving =
moving
self.is_moving =
False
self.moving.bind
(
"mousedown"
, self.start)
self.moving.bind
(
"mousemove"
, self.move)
self.moving.bind
(
"mouseup"
, self.stop)
moving.style.cursor =
"move"
def
start
(
self, event):
"""When user clicks on the moving element, set boolean is_moving
to True and store mouse and moving element positions"""
self.is_moving =
True
self.mouse_pos =
[event.x, event.y]
self.elt_pos =
[self.moving.left, self.moving.top]
# prevent default behaviour to avoid selecting the moving element
event.preventDefault
(
)
def
move
(
self, event):
"""User moves the mouse"""
if
not
self.is_moving:
return
# set new moving element coordinates
self.moving.left =
self.elt_pos[0
] +
event.x -
self.mouse_pos[0
]
self.moving.top =
self.elt_pos[1
] +
event.y -
self.mouse_pos[1
]
def
stop
(
self, event):
"""When user releases the mouse button, stop moving the element"""
self.is_moving =
False
ElementMove
(
document["moving"
])
V-E-5. Itérer sur des enfants▲
2.
for
child in
element:
# ...
V-E-6. Récupérer les valeurs des champs d'un formulaire▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
from
browser import
document, html
def
show_values
(
event):
input =
document["input16"
].value
select =
document["select16"
]
option =
select.options[select.selectedIndex].value
text =
document["textarea16"
].value
document["zone16"
].clear
(
)
document["zone16"
] <=
(
"Value in INPUT field: {}"
.format
(
input),
html.BR
(
), "Selected option: {}"
.format
(
option),
html.BR
(
), "Value in TEXTAREA field: {}"
.format
(
text)
)
document['button16'
].bind
(
'click'
, show_values)
V-F. Attributs et méthodes des éléments▲
Voici un tableau récapitulant les possibilité offerte par Brython, relatif aux propriétés et aux méthodes des éléments de la page web.
V-F-1. Génériques▲
Nom |
Type |
Description |
Lecture |
Écriture |
abs_left |
Entier |
Position de l'élément par rapport au bord gauche de l'écran |
X |
|
abs_top |
Entier |
Position de l'élément par rapport au bord supérieur de l'écran |
X |
|
children |
Liste |
Les éléments "descendants" de l'élément |
X |
|
class_name |
Chaîne |
Le nom de la classe de l'élément (attribut class de la balise) |
X |
|
clear |
Méthode |
" elt.clear() " supprime tous les descendants de l'élément |
||
get |
Méthode |
Sélectionne des éléments |
||
height |
Entier |
Hauteur de l'élément en pixels |
X |
|
html |
Chaîne |
Le code HTML contenu dans l'élément |
X |
|
index |
Méthode |
" elt.index() " renvoie le rang (entier) de l'élément parmi les enfants de son parent |
||
inside |
Méthode |
" elt.inside(autre) " teste si " elt " est contenu dans l'élément " autre " |
||
left |
Entier |
La position de l'élément par rapport au bord gauche du premier parent positionné |
X |
|
parent |
Instance de DOMNode |
L'élément parent de l'élément (None pour document) |
X |
|
select |
Méthode |
" elt.select(css_selector) " renvoie les éléments correspondant au sélecteur CSS spécifié |
||
text |
Chaîne |
Le texte contenu dans l'élément |
X |
|
top |
Entier |
La position de l'élément par rapport au bord supérieur du premier parent positionné |
X |
|
width |
Entier |
Largeur de l'élément en pixels |
X |
V-G. Opérations complémentaires▲
V-G-1. Dessiner▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
from
browser import
document, html
import
math
canvas =
document["zone8"
]
ctx =
canvas.getContext
(
"2d"
)
x =
20
def
draw
(
event):
global
x
ctx.beginPath
(
)
ctx.arc
(
x, 25
, 15
, 0
, 2
*
math.pi)
x +=
15
ctx.stroke
(
)
document["button8"
].bind
(
"click"
, draw)
V-G-2. Utiliser le local storage▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
from
browser import
alert
from
browser.local_storage import
storage
import
json
a =
{'foo'
:1
,1515
:'Marignan'
}
storage["brython_test"
] =
json.dumps
(
a)
b =
json.loads
(
storage['brython_test'
])
alert
(
b['foo'
])
alert
(
b['1515'
])
V-G-3. Effectuer une requête AJAX▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
from
browser import
document, ajax
url =
"http://api.open-notify.org/iss-now.json"
msg =
"Position of the International Space Station at {}: {}"
def
complete
(
request):
import
json
import
datetime
data =
json.loads
(
request.responseText)
position =
data['iss_position'
]
ts =
data['timestamp'
]
now =
datetime.datetime.fromtimestamp
(
ts)
document["zone10"
].text =
msg.format
(
now, position)
def
change
(
event):
req =
ajax.ajax
(
)
req.open(
'GET'
, url, True
)
req.bind
(
'complete'
, complete)
document["zone10"
].text =
"waiting..."
req.send
(
)
document['button10'
].bind
(
'click'
, change)
V-G-4. Parser un fichier XML▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
from
browser import
document, window, html
parser =
window.DOMParser.new
(
)
def
show
(
node, container):
if
hasattr(
node, "tagName"
):
container <=
html.STRONG
(
node.tagName)
ul =
html.UL
(
)
container <=
ul
for
child in
node.childNodes:
show
(
child, ul)
elif
node.text.strip
(
):
container <=
html.LI
(
node.text)
def
show_xml
(
):
src =
open(
"cd-catalog.xml"
).read
(
)
tree =
parser.parseFromString
(
src, "application/xml"
)
root =
tree.firstChild
show
(
root, document["zone18"
])
document["button18"
].bind
(
"click"
, lambda
ev: show_xml
(
))
V-G-5. Parser un fichier JSON▲
Le format JSON étant natif en Python, puisqu'il correspond à un dictionnaire, je vous renvoie simplement vers un article dédié.
V-H. Interaction avec les objets javascripts▲
V-H-1. Date▲
2.
3.
4.
5.
6.
7.
8.
from
browser import
document, window
def
show_date
(
event):
date =
window.Date.new
(
)
document['zone11'
].text =
'{}-{:02}-{:02} at {:02}:{:02}:{:02}'
.format
(
date.getFullYear
(
), date.getMonth
(
)+
1
, date.getDate
(
),
date.getHours
(
), date.getMinutes
(
), date.getSeconds
(
))
document['button11'
].bind
(
'click'
, show_date)
V-H-2. REGEX et chaîne de caractères▲
2.
3.
4.
5.
from
browser import
document, window
def
change
(
event):
s =
window.String.new
(
"abracadabra"
)
document['zone17'
].text =
s.replace
(
window.RegExp.new
(
"a"
, "g"
), "i"
)
document['button17'
].bind
(
'click'
, change)
VI. Conclusion▲
Comme nous venons de le voir ensemble, Brython possède un vrai potentiel, et répond à des attentes réelles.
Toujours en cours de développement, et relativement jeune, il s'agit néanmoins d'un projet prometteur. Et s'il ne saura remplacer systématiquement javascript, sa facilité d'apprentissage, et de mise en œuvre, en font en tout cas, un outil idéal pour du prototypage rapide.
J'espère que cet article vous aura intéressé et attisé votre curiosité concernant ce framework.