Caso de uso del glosario¶
Objetivo¶
Queremos proporcionar una herramienta para administrar una lista de términos y sus definiciones:
Cada vez que uno de estos términos aparezca en una página de nuestro sitio, será envuelto en una etiqueta <abbr>, cuyo título será la definición, por lo que cuando pasamos un término, obtenemos un pequeña mensaje emergente que indica su definición:
Estructura de la aplicación¶
rapido/
glossary/
blocks/
all.html
all.py
all.yaml
term.html
term.py
term.yaml
glossary.js
rules.xml
El archivo rules.xml¶
<after css:theme-children="body">
<script src="/tutorial/++theme++test/rapido/glossary/glossary.js"></script>
</after>
Esta regla inserta en todas nuestras páginas un archivo javascript a cargo de reemplazar las palabras coincidentes con etiquetas <abbr>
.
El bloque term
¶
Este bloque es un formulario que permite crear/editar/eliminar un término del glosario. Contiene dos elementos de campo y tres acciones.
term.html
<p><label>Term</label> {term}</p> <p><label>Definition</label> {definition}</p> {_save} {_delete} {close}
term.yaml
target: ajax elements: term: TEXT definition: TEXT close: type: ACTION label: Close _save: type: ACTION label: Save _delete: type: ACTION label: Delete
term.py
def close(context): return context.app.get_block('all').url def on_save(context): return context.app.get_block('all').url def on_delete(context): return context.app.get_block('all').url
Si hacemos clic en cualquier acción en este bloque, queremos ser redirigidos a la página de administración principal. Lo hacemos devolviendo la URL de all
bloques (cuando una acción devuelve una cadena, se utiliza como una dirección URL de redirección).
El bloque all
¶
Este bloque lista todos los términos existentes en una tabla. Cuando hacemos clic en un término, lo abrimos en el bloque term
en modo de edición, y un botón permite abrir un bloque term
en blanco para crear un nuevo término.
all.html
<table class="listing"><tr><th>Term</th><th>Definition</th></tr> {list} </table> {new_term}
all.yaml
target: ajax view: id: glossary with_theme: true elements: list: BASIC new_term: type: ACTION label: Add term
La configuración
view
permite renderizar el bloqueall
como la vista de Plone llamada@@glossary
, por lo que podemos llamar a http://localhost:8080/Plone/@@glossary para verlo.all.py
def list(context): html = u"" for record in context.app.records(): html += """<tr><td><a href="%s/edit" target="ajax">%s</a></td><td>%s</td></tr>""" % ( record.url, record['term'], record['definition'], ) return html def new_term(context): return context.app.get_block('term').url
La función list
crea una fila de tabla para cada registro existente, mostrando el valor del término y el valor de la definición. El enlace que ponemos en el término se dirige a la URL de registro (más /edit para abrirlo en modo de edición) y hemos añadido target=»ajax» por lo que la página resultante no se muestra como una página completa, se acaba de cargar en la actual bloque en modo AJAX.
El Javascript¶
glossary.js
require(['jquery'], function($) { if($('.template-edit').length > 0) { return } $.getJSON('/tutorial/@@rapido/glossary/records', function(data) { var keys = []; var values = {}; for(var i=0; i<data.length; i++) { term = data[i].items.term; definition = data[i].items.definition; keys.push(term); values[term] = definition; } var re = RegExp("(\\W)(" + keys.join("|") + ")(\\W)", "g"); function replaceNodeText() { if (this.nodeType === 3) { var parent = $(this).parent(); var html = parent.html(); if(html) { var newvalue = html.replace(re, function(){ var term = arguments[2], before = arguments[1], after = arguments[3]; term = '<abbr title="'+values[term]+'">'+term+'</abbr>'; return before + term + after; }); parent.html(newvalue); } } else { $(this).contents().each(replaceNodeText); } } $("#content-core").contents().each(replaceNodeText); }); });
Lo primero que hacemos es comprobar si estamos en modo de edición, y si lo estamos, nos detendremos, ya que no queremos manipular el HTML que está siendo editado en TinyMCE o en cualquier campo de entrada.
Luego cargamos los términos del glosario con la siguiente llamada JSON: /tutorial/@@rapido/glossary/records
Usando el término valores que hemos cargado, construimos una expresión regular capaz de emparejar esos términos en cualquier texto.
Luego iteramos en los elementos principales del contenido de la página (#content-core
), y cada vez que encontramos un nodo de texto, usamos nuestra expresión regular para reemplazar las palabras coincidentes con una etiqueta <abbr>
donde el atributo title
es la definición asociada.