Curso de Brython en Español - Acceso y manipulación del DOM


Introducción

En este capítulo aprendenrás a acceder y manipular las etiquetas html desde código brython.

En esta sección trabajaremos con el siguiente documento html:

<!--index.html-->

<!DOCTYPE html>

<html lang="es">

<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ACCESO / MANIPULACIÓN DOM</title>
    <script src="https://cdn.jsdelivr.net/npm/brython@3/brython.min.js"></script>
</head>

<body onload="brython()">

    <h1 id="titulo">Título del Documento</h1>

    <h2 id="subtitulo">Subtítulo del Documento</h2>

    <ul id="lista"></ul>

    <script type="text/python">#codigo-python</script>

</body>

</html>

Escribiremos el código python donde pone #codigo-python. Si lo prefieres puedes enlazar con un archivo externo tal y como hicimos en el capítulo anterior.

¡¡ Comenzemos !!


Acceder a los elementos del DOM

Fíjate en index.html. Hay una serie de etiquetas a las que he asignado un atributo id. Puedes acceder a estas etiquetas así:

from browser import document

titulo = document['titulo']
subtitulo = document['subtitulo']
lista = document['lista']

Por ejemplo, para mostrar el texto del título en un alert:

from browser import document, alert

titulo = document['titulo'] # También puedes usar document.getElementById('titulo')

alert(f'El título es "{titulo.text}"') # También puedes usar titulo.textContent

La variable titulo hace referencia a la etiqueta h1 con id="titulo". Puedes acceder a cualquiera de sus atributos. Otra forma de hacer lo mismo sería utilizando document.getElementById, que es la forma habitual de hacerlo en javascript. Del mismo modo, puedes utilizar indistintamente .text o .textContent para obtener el texto del elemento.

Puedes acceder a cualquier elemento del documento que tenga su atributo id definido:

from browser import document, alert

titulo = document['titulo']
subtitulo = document['subtitulo']

for i in titulo, subtitulo:
    alert(f'El {i.id} es "{i.text}"')

En este caso mostramos un alert para titulo y otro para subtitulo. En ambos casos obtenemos sus atributos .id y .text para crear la alerta adecuada.

Esto está bien, pero te resultará mas interesante manipular el texto de los elementos desde python.


Manipular los elementos del DOM

Vamos a modificar el título y subtítulo de las etiquetas html / elementos del DOM. Por ejemplo, si queremos que la etiqueta h1 con id="titulo" muestre el texto "Mi lista de la compra":

from browser import document

titulo = document['titulo']

titulo.text = 'Mi lista de la compra'

Tan sencillo como asignar un nuevo valor a la propiedad titulo.text. Ya que estamos modifiquemos también el subtítulo:

from browser import document

titulo = document['titulo']
subtitulo = document['subtitulo']

titulo.text = 'Mi lista de la compra'
subtitulo.text = 'Toma nota de mi lista de la compra:'

En index.html tenemos una etiqueta ul con id="lista". La lista está vacía, pero vamos a rellenarla ahora mismo.

En este caso, en lugar de modificar el valor de la propiedad .text vamos a utilizar la propiedad .html para que el texto asignado sea interpretado como código html:

from browser import document

titulo = document['titulo']
subtitulo = document['subtitulo']
lista = document['lista']

titulo.text = 'Mi lista de la compra'
subtitulo.text = 'Toma nota de mi lista de la compra:'

lista.html = '<li>Pan</li><li>Huevos</li><li>Jamón</li><li>Cebolla</li>' # También puedes usar lista.innerHTML

En brython, la razón por la que puedes utilizar .text o .textContent para acceder al texto, y .html o .innerHTML, es la primera forma es mas pythonica. En javascript solamente existen .textContent e .innerHTML para acceder al texto y html respectivamente.

Ahora que hemos añadido una serie de elementos li a la lista ¿cómo acceder a ellos?. Podrías asignar un atributo id a cada uno de ellos. Por ejemplo, vamos a acceder al primer li y vamos a cambiar su texto:

from browser import document

titulo = document['titulo']
subtitulo = document['subtitulo']
lista = document['lista']

titulo.text = 'Mi lista de la compra'
subtitulo.text = 'Toma nota de mi lista de la compra:'

lista.html = '''
    <li id="pan">Pan</li>
    <li>Huevos</li>
    <li>Jamón</li>
    <li>Cebolla</li>
'''

document['pan'].text += ' Tostado'

Sin embargo no es necesario asignar un id siempre. Puedes acceder a los hijos de un elemento según su posición. Por ejemplo:

from browser import document

titulo = document['titulo']
subtitulo = document['subtitulo']
lista = document['lista']

titulo.text = 'Mi lista de la compra'
subtitulo.text = 'Toma nota de mi lista de la compra:'

lista.html = '''
    <li>Pan</li>
    <li>Huevos</li>
    <li>Jamón</li>
    <li>Cebolla</li>
'''

lista.children[0].text += ' Tostado'
lista.children[-1].text += ' Caramelizada'

En brython, todos los elementos html tienen un atributo children que es una lista posicional de los elementos que contiene.

También puedes iterar sobre el ul para acceder a cada uno de sus hijos:

from browser import document

titulo = document['titulo']
subtitulo = document['subtitulo']
lista = document['lista']

titulo.text = 'Mi lista de la compra'
subtitulo.text = 'Toma nota de mi lista de la compra:'

lista.html = '''
    <li>Pan</li>
    <li>Huevos</li>
    <li>Jamón</li>
    <li>Cebolla</li>
'''

for i in lista:
    i.text = i.text.upper()

for i in lista.children:
    i.text += ', delicioso!'

Ahora todos los elementos de la lista aparecen en mayúsculas y son deliciosos!!

Fíjate en que, para iterar sobre los hijos de un elemento, puedes iterar directamente sobre el elemento padre: for i in lista o sobre su atributo children: for i in lista.children. El resultado es el mismo.


Otras formas de acceder a elementos del DOM


En esta sección utlizaremos el siguiente archivo html.

<!-- otras formas de acceder a elementos del DOM -->

<!DOCTYPE html>

<html lang="es">

<head>
    <meta charset="utf-8"/>
    <title>OTRAS FORMAS ACCESO DOM</title>
    <script src="https://cdn.jsdelivr.net/npm/brython@3/brython.min.js"></script>
</head>

<body onload="brython()">

    <p>Párrafo 1</p>
    <p>Párrafo 2</p>
    <p>Párrafo 3</p>

    <div id="contenedor">
    	<p>Párrafo en contenedor 1</p>
    	<p>Párrafo en contenedor 2</p>
    	<p>Párrafo en contenedor 3</p>
    </div>

    <script type="text/python">#codigo-python</script>

</body>

</html>

Acceder al div con id="contenedor"

from browser import document, alert

contenedor = document['contenedor']

alert(f'El contenedor tiene {len(contenedor.children)} elementos')

Se obtendría el mismo resultado con:

Acceder a todos los párrafos

from browser import document

parrafos = document.select('p')

for p in parrafos:
    p.style.color = 'red'

Se obtendría el mismo resultado con:

Acceder sólo a los párrafos dentro del div

from browser import document

parrafos = document.select('#contenedor > p')

for p in parrafos:
    p.style.color = 'red'

Se obtendría el mismo resultado con:

Acceder sólo a los párrafos fuera del div

from browser import document

parrafos = document.select('p:not(#contenedor > p)')

for p in parrafos:
    p.style.color = 'red'

Otra forma sería la siguiente:

from browser import document

parrafos = document.select('p')
contenedor = document['contenedor']

parrafos_fuera = [p for p in parrafos if p.parent != contenedor]

for p in parrafos_fuera:
    p.style.color = 'red'

Puedes usar .parent o .parentNode para referirte al padre del elemento. La segunda forma es como se haría en javascript.


En el próximo capítulo veremos cómo crear elementos html dinámicamente desde código python para añadirlos al documento, pero de momento no he tenido tiempo de escribir mas. Espero hacerlo pronto!!