martes, 2 de septiembre de 2014
Symfony - Día 18: AJAX
Anteriormente en Jobeet
Ayer, hemos implementado un poderoso motor de búsqueda para Jobeet, gracias a la biblioteca Zend Lucene.
Hoy, para aumentar la capacidad de respuesta del motor de búsqueda, vamos a aprovechar AJAX para convertir el motor de búsqueda en uno más vivo.
Como el formulario debe trabajar con y sin JavaScript activado, la función de búsqueda en vivo se llevará a cabo utilizando unobtrusive JavaScript. Usando unobtrusive JavaScript también permite una mejor separación de las capas en el código del cliente entre HTML, CSS, y el comportamiento JavaScript.
Instalación de jQuery
En vez de reinventar la rueda y la gestión de las muchas diferencias entre los navegadores, vamos a utilizar una biblioteca JavaScript, jQuery. El framework Symfony es agnóstica y puede trabajar con cualquier biblioteca JavaScript.
Incluyendo jQuery
Como vamos a necesitar jQuery en todas las páginas, actualiza el layout para incluirlo en el
<head>
. Tenga cuidado de insertar la función use_javascript()
antes de llamar alinclude_javascripts()
:<!-- apps/frontend/templates/layout.php --> <?php use_javascript('jquery-1.2.6.min.js') ?> <?php include_javascripts() ?> </head>
Podríamos haber incluido jQuery directamente con un tag
<script>
, pero utilizando el helperuse_javascript()
nos aseguramos que el mismo JavaScript no se incluirá dos veces.
Por razones de rendimiento, podrías también mover el helper
include_javascripts()
justo antes de la etiqueta de cierre </body>
.Agregando comportamientos
Implementar un buscador vivo implica que cada vez que el usuario escribe una letra en el cuadro de búsqueda, se hace una llamada al servidor; a continuación, el servidor devolverá la información necesaria para actualizar la areas seleccionadas de la página sin actualizar toda la página.
En lugar de añadir el comportamiento con atributos
on*()
del HTML, el principio fundamental detrás de jQuery es agregar comportamientos al DOM después de que la página está completamente cargada. De esta forma, si desactivas el soporte de JavaScript en tu navegador, ningún comportamiento es registrado, y el formulario sigue funcionando como antes.
El primer paso es interceptar cuando un usuario introduce una tecla en el cuadro de búsqueda:
$('#search_keywords').keyup(function(key) { if (this.value.length >= 3 || this.value == '') { // do something } });
No añadas el código por ahora, ya que vamos a modificar todo en gran medida. El código JavaScript final se añadirá al layout en la siguiente sección.
Cada vez que el usuario introduce una tecla, jQuery executa la función anónima que se definió en el código anterior, pero sólo si el usuario ha escrito más de 3 caracteres o si se elimina todo, de la etiqueta input.
Hacer una llamada AJAX al servidor es tan sencillo como utilizar el método
load()
sobre el elemento DOM:$('#search_keywords').keyup(function(key) { if (this.value.length >= 3 || this.value == '') { $('#jobs').load( $(this).parents('form').attr('action'), { query: this.value + '*' } ); } });
Para gestionar las llamadas AJAX, la misma acción "normal y corriente" es ejecutada. Los cambios necesarios en la acción se harán en la siguiente sección.
Por último, pero no por ello menos importante, si JavaScript está habilitado, y queremos a quitar el botón de búsqueda:
$('.search input[type="submit"]').hide();
Respuesta al Usuario
Cuando haces una llamada AJAX, la página no se actualiza inmediatamente. El navegador esperará la respuesta del servidor antes de actualizar la página. En el ínterin, es necesario proporcionar respuesta visual al usuario para informarle de que algo está ejecutandose.
Una convención es mostrar un icono de cargador durante la llamada AJAX. Actualiza el layout para añadir la imagen del cargador y ocultarla por defecto:
<!-- apps/frontend/templates/layout.php --> <div class="search"> <h2>Ask for a job</h2> <form action="<?php echo url_for('job_search') ?>" method="get"> <input type="text" name="query" value="<?php echo $sf_request->getParameter('query') ?>" id="search_keywords" /> <input type="submit" value="search" /> <img id="loader" src="/legacy/images/loader.gif" style="vertical-align: middle; display: none" /> <div class="help"> Enter some keywords (city, country, position, ...) </div> </form> </div>
El cargador por defecto esta optimizado para el actual layout de Jobeet. Si deseas crear el tuyo, encontrarás una gran cantidad de gratuitos servicios en línea como http://www.ajaxload.info/.
Ahora que tienes todas las piezas necesarias para que el código HTML funcione, crea un archivo
search.js
que tenga el siguiente código JavaScript que escribiremos:// web/js/search.js $(document).ready(function() { $('.search input[type="submit"]').hide(); $('#search_keywords').keyup(function(key) { if (this.value.length >= 3 || this.value == '') { $('#loader').show(); $('#jobs').load( $(this).parents('form').attr('action'), { query: this.value + '*' }, function() { $('#loader').hide(); } ); } }); });
También necesitas actualizar el layout para incluir este nuevo archivo:
<!-- apps/frontend/templates/layout.php --> <?php use_javascript('search.js') ?>
JavaScript como una Acción
Aunque el JavaScript que hemos escrito para el motor de busqueda es estático, a veces, necesitas llamar algún código PHP (para usar el helper
url_for()
por ejemplo).
JavaScript es solo otro formato como HTML, y como vimos algunos días atrás, Symfony hace la adminitración de formatos muy fácil. Ya que el archivo JavaScript tendrá un comportamiento por página, puedes hasta tener la misma URL como para la página del archivo JavaScript, pero que termina con
.js
. por ejemplo, si quieres crear un archivo para el motor de busqueda, puedes modificar la rutajob_search
como sigue y crear una platilla searchSuccess.js.php
:job_search: url: /search.:sf_format param: { module: job, action: search, sf_format: html } requirements: sf_format: (?:html|js)
AJAX en una Acción
Si JavaScript está habilitado, jQuery interceptará todas las teclas mecanografiadas en el cuadro de búsqueda, y llamará a la acción
search
. Si no, la misma acción search
es también llamada cuando el usuario envía el formulario presionando la tecla "enter" o haciendo clic en el botón "search".
Así, la acción
search
ahora debe determinar si la llamada se realiza a través de AJAX o no. Cuando una petición se hace con una llamada AJAX, el método isXmlHttpRequest()
dará true
.
El método
isXmlHttpRequest()
funciona con todas las principales bibliotecas JavaScript como Prototype, Mootools, o jQuery.// apps/frontend/modules/job/actions/actions.class.php public function executeSearch(sfWebRequest $request) { $this->forwardUnless($query = $request->getParameter('query'), 'job', 'index'); $this->jobs = Doctrine_Core::getTable('JobeetJob')->getForLuceneQuery($query); if ($request->isXmlHttpRequest()) { return $this->renderPartial('job/list', array('jobs' => $this->jobs)); } }
Como jQuery no recarga la página, sino sólo reemplaza el elemto DOM
#jobs
con el contenido de la respuesta, la página no debe ser redecorada por la layout. Como se trata de una necesidad común, el layout está desactivado por defecto cuando se presenta una petición AJAX.
Además, en lugar de devolver la plantilla completa, sólo tenemos que devolver el contenido del partial
job/list
. El método renderPartial()
usado en la acción devuelve el partial como la respuesta en lugar de la totalidad de la plantilla.
Si el usuario elimina todos los caracteres en el cuadro de búsqueda, o si la búsqueda no devuelve ningún resultado, tenemos que mostrar un mensaje en lugar de una página en blanco. Vamos a utilizar el método
renderText()
para mostrar una simple cadena de prueba:// apps/frontend/modules/job/actions/actions.class.php public function executeSearch(sfWebRequest $request) { $this->forwardUnless($query = $request->getParameter('query'), 'job', 'index'); $this->jobs = Doctrine_Core::getTable('JobeetJob')->getForLuceneQuery($query); if ($request->isXmlHttpRequest()) { if ('*' == $query || !$this->jobs) { return $this->renderText('No results.'); } return $this->renderPartial('job/list', array('jobs' => $this->jobs)); } }
También puedes devolver un componente utilizando el método
renderComponent()
.Probando AJAX
Como el navegador Symfony no puede simular JavaScript, necesitas ayudarlo cuando pruebas llamadas AJAX. Esto principalmente significa que es necesario añadir manualmente la cabecera jQuery y que todas las demás grandes bibliotecas JavaScript envían con la petición:
// test/functional/frontend/jobActionsTest.php $browser->setHttpHeader('X_REQUESTED_WITH', 'XMLHttpRequest'); $browser-> info('5 - Live search')-> get('/search?query=sens*')-> with('response')->begin()-> checkElement('table tr', 2)-> end() ;
El método
setHttpHeader()
pone un header HTTP para la siguiente petición formulada con el navegador.Nos vemos mañana
Ayer, hemos utilizado la biblioteca de Zend Lucene para implementar el motor de búsqueda. Hoy, usamos jQuery para para hacerlo más dinámico. El framework Symfony proporciona todas las herramientas fundamentales para construir aplicaciones MVC con facilidad, y también juega bien con otros componentes. Como siempre, tratar de usar la mejor herramienta para el trabajo.
Mañana, vamos a ver cómo se hace la internacionalización de la página web Jobeet.
Suscribirse a:
Enviar comentarios
(
Atom
)
Sígueme en las Redes Sociales
Donaciones
Datos personales
Entradas populares
-
En este apartado vamos a explicar como ejercutar archivos PHP a través del terminal de Ubuntu. Lo primero que tendríamos que hacer es inst...
-
En este blog voy a comentar un tema que se utilizan en casi todas las páginas web que existen, y es el tema de la paginación. La paginaci...
-
Este post trata de la integración de la librería PHPExcel en Codeigniter, aunque se podría aplicar a cualquier librería, como por ejemplo mP...
-
Ejemplo para añadir o sumar un número determinado de hora/s, minuto/s, segundo/s a una fecha en php. Con la función strtotime se puede ...
-
Este tema es uno de los temas primordiales sobre el framework Codeigniter, ya que en alguna ocación nos hemos visto obligados a recoger dato...
© Espacio Daycry - Espacio de programación 2013 . Powered by Bootstrap , Blogger templates and RWD Testing Tool
No hay comentarios :
Publicar un comentario