23. JavaScript, AJAX y jQuery

JavaScript es un componente importante en muchos plugins WordPress. WordPress viene con una variedad de librerías JavaScript en el núcleo. Una de las más frecuentemente utilizadas es jQuery, porque es ligera y fácil de usar. Puedes emplear jQuery en tus plugins para manipular los objetos del DOM o para ejecutar acciones AJAX.

 

jQuery

Utilizar jQuery

Tu script jQuery corre en el navegador del usuario después de recibir tu página WordPress. Una declaración básica jQuery tiene dos partes: un selector que determina qué elemento HTML se le aplica el código, y una acción o evento que determina lo que hace el código o a qué reacciona. La declaración básica de evento se parece a esto:

Cuando un evento, como un click de ratón, ocurre en un elemento HTML seleccionado por el selector, la función que está definida dentro de los paréntesis del final se ejecuta.

Todos los ejemplos de código siguientes están basados en este contenido de página HTML. Se asume que aparece en la pantalla de administración de tu plugin, definida por el fichero miplugin_ajuste.php. Es una tabla simple con botones redondos a continuación de cada título.

En el apartado sobre AJAX, construiremos un intercambio AJAX que guarda la selección del usuario en usermeta y añade el número de artículos etiquetados con el título seleccionado. Una aplicación no muy práctica, pero que ilustra todos los pasos importantes. El código jQuery puede residir en un fichero externo o puede encontrarse en un bloque <script> dentro de la misma página. Pondremos el foco en la variación de fichero externo, porque el paso de valores desde PHP requiere especial atención. El mismo código puede aparecer en la página si te parece más fácil.

 

Selector y evento

El selector es el mismo que el de CSS: la clase o el id. Existen otras muchas formas, pero estos son los dos más frecuentemente usados. En nuestro ejemplo, nosotros utilizaremos la clase “.pref”. Hay también un montón de posibles eventos, el que utilizarás muy a menudo es ‘click’. En nuestro ejemplo utilizaremos ‘change’ para capturar la selección de un botón. Se consciente que los eventos jQuery a menudo tienen nombres diferentes de los mismos en JavaScript. Más lejos, después que añadimos en una función anónima vacía, nuestro ejemplo se parece a esto:

Este código ejecutará “do stuff” cuando un elemento de la clase “pref” cambia.

 

AJAX

¿Qué es AJAX?

AJAX es el acrónimo de Asynchronous JavaScript And XML. XML es un formato de intercambio de datos y UX es una abreviatura de los desarrolladores de softwar para User Experience. Ajax es una técnica de comunicaciones de Internet que permite a una página web de un navegador de un usuario solicitar información específica de un servidor, y mostrarla en la misma página sin necesidad de recargar la página entera. Ya puedes imaginar cómo esto mejora la experiencia del usuario.

Mientras XML es el formato tradicional de intercambio de datos utilizado, el intercambio actualmente puede ser en cualquier formato conveniente. Cuando se trabaja con código PHP, algunos desarrolladores prefieren JSON porque la estructura interna de datos creada por el flujos de datos transmitidos es más fácil de mostrar.

Para ver AJAX en acción, ve al área de administración de WordPress y añade una categoría o etiqueta. Observa que cuando clicas el botón ‘Añadir’, la página cambia pero no se recarga.

AJAX no requiere una acción de usuario para trabajar. Google Docs guarda automáticamente tu documento cada pocos minutos con AJAX sin que necesites iniciar una acción de guardado.

 

¿Porqué utilizar AJAX?

Obviamente, mejora la experiencia del usuario. En lugar de presentar una página aburrida y estática, AJAX te permite presentar una experiencia de usuario dinámica, adaptativa y amigable. Los usuarios pueden tener feedback inmediato de que algunas acciones que toman son correctas o erróneas. No se necesita enviar un formulario entero antes para encontrar que hay un error en un campo. Los campos importantes pueden ser validados tan pronto como se introduzcan los datos. O se pueden hacer sugerencias, como los tipos de usuarios.

AJAX puede disminuir dramáticamente el montante de datos que fluyen hacia adelante y hacia atrás. Solo los datos pertinentes necesitan ser intercambiados de todo el contenido de la página, lo cual es lo que pasa cuando la página se recarga.

Específicamente relacionado con los plugins de WordPress, AJAX es de largo la mejor manera de iniciar un proceso independiente del contenido de WordPress. Si tienes programado PHP antes, puedes hacerlo enlazando simplemente a una página PHP nueva. El usuario inicia el proceso siguiendo el enlace. El problema con esto es que no puedes acceder a ninguna función de WordPress cuando enlazas a una página PHP externa. En el pasado, los desarrolladores accedían a las funciones de WordPress incluyendo el fichero del núcle wp-load.php en sus páginas PHP nuevas. El problema al hacer esto es que posiblemente no sepas el camino correcto a este fichero. La arquitectura de WordPress es ahora tan flexible que los diferentes elementos pueden ubicarse en sitios distintos. No puedes saber dónde está wp-load.php en relación a tu plugin, y tampoco puedes saber la dirección absoluta.

Lo que sí puedes saber es dónde enviar una solicitud AJAX, porque está definida en una variable JavaScript global. Tu script PHP AJAX es actualmente un gancho de acción, luego todas las funciones WordPress son automáticamente accesibles, a diferencia de un fichero PHP externo.

 

¿Cómo utilizo AJAX?

Si eres nuevo en WordPress pero tienes experiencia en AJAX en otros entornos, necesitarás aprender unas pocas cosas. La manera en que WordPress implementa AJAX es diferente de como lo has utilizado. Si todo es nuevo para tí, ningún problema. Aquí aprenderás lo básico. Una vez hayas desarrollado un intercambio básico AJAX, es fácil desarrollar a partir de ahí.

Hay dos componentes principales en cualquier intercambio AJAX en WordPress. El cliente JavaScript o jQuery, y el servidor PHP. Todos los intercambios AJAX siguen la siguiente secuencia de eventos:

  1. Algún tipo de evento de la página inicia una función JavaScript o jQuery. Esta función recoge algunos datos de la página y los envía vía requerimiento HTTP al servidor. Porque el manejo de consultas HTTP con JavaScript es torpe y jQuery es liado dentro de WordPress de cualquier forma, vamos a centrarnos sólo en código jQuery desde ahora.
  2. El servidor recibe la consulta y hace algo con los datos. Puede montar datos relaciones y devolverlos al navegador cliente en la forma de una respuesta HTTP. Esto no es un requerimiento, pero desde el acuerdo el usuario informó acerca de lo que quería, es muy raro no enviar algún tipo de respuesta.
  3. La función jQuery que envió la consulta inicial AJAX recibe la respuesta del servidor y hace algo con ella. Puede actualizar algo en la página y/o presentar un mensaje al usuario.

 

Utilizar AJAX con jQuery

Ahora vamos definir la porción “do stuff” del snippet del artículo anterior sobre jQuery. Utilizaremos el método $.post(), que toma tres parámetros: la URL para enviar la consulta POST, los datos a enviar, y una función de llamada de vuelta para manejar la respuesta del servidor. Antes de hacer esto, sin embargo, vamos a planificar un poco antes. Hacemos la siguiente asicanción para utilizar después en la función de llamada de vuelta (callback), cuyo propósito será más evidente en la sección Callback:

 

URL

Todos los requerimientos WordPress AJAX se deben enviar a wp-admin/admin-ajax.php. La correcta, completa URL necesita venir de PHP, jQuery no puede determinar este valor por si mismo, y tú no puedes indicar la dirección en el código jQuery y esperar que cualquiera use tu plugin en su web. Si la página es del área de administración, WordPress selecciona la URL correcta en la variable JavaScript global ajaxurl. Para una página del área pública, necesitas establecer la URL y pasarla a jQuery utilizando wp_localize_script(). Esta función se verá con más detalle más adelante. Por ahora, sólo saber que la URL que trabajará tanto para el front-end como para el back-end esta accesible como una propiedad de un objeto global que definirás en el segmento PHP. En jQuery se referencia como esto:

 

Datos

Todos los datos que necesitan ser enviados al servidor se introducen en una matriz de datos. Además de cualquier dato necesario para nuestra aplicación, debes enviar un parámetro de acción. Para requerimientos que puedan modificar la base de datos, además debes enviar un ‘nonce’ (number once – número una vez) para que el servidor sepa del origen legítimo. Nuestra matriz de datos de ejemplo enviada al método .post() se parecerá a esto:

Cada componente se explica a continuación.

  • nonce

‘Nonce’ es una forma abreviada de “Number used ONCE” (número usado una vez). Es, esencialmente, un número hexadecimal de serie único asignado a cada instancia de cualquier formulario. El ‘nonce’ se establece con un script PHP y se pasa a jQuery en la misma forma que la URL, como una propiedad en un objeto global. En este caso se referencia como my_ajax_obj.nonce.

Es lo más fácil si codificas este valor ‘nonce’ a _ajax_nonce. Puedes utilizar una clave diferente si está coordinada con el código PHP verificador, pero es más fácil utilizar el valor por defecto y no preocuparse de coordinarlos. Esta es la manera que que la declaración de este par clave-valor aparece:

  • action

Todos los requerimientos WordPress AJAX deben incluir un argumento de acción en los datos. Este valor es una cadena arbitraria que se usa para construir una etiqueta de acción que utilizas para enganchar tu código de manipulación de AJAX. Es fácil para este valor se una breve descripción del propósito de la llamada AJAX. La clave para este valor es ‘action’. En este ejemplo, utilizamos “my_tag_count” como nuestro valor de acción. La declaración de este par clave-valor se parece a esto:

Cualquier otro dato que el servidor necesita para realizar su tarea se incluye también en esta matriz. Si hay muchos campos a transmitir, hay dos formatos comunes para combinar campos de datos en simples cadenas para mejor transimisión, XML y JSON. La utilización de estos formatos es opcional, pero cualquiera necesita estar coordinado con el script PHP en el lado servidor. Mas información de estos formatos en la siguiente sección de llamadas de vuelta.

En nuestro ejemplo, el servidor sólo necesita un valor, una simple cadena para el título del libro seleccionado, luego utilizamos la clave ‘title’. En jQuery, el objeto que ejecuta el evento está contenido siempre en la variable this. Por tanto, el valor del elemento seleccionado es this.value. Nuestra declaración de este par clave-valor es así:

  • Callback

El manejador de llamadas de vuelta es la función a ejecutar cuando llega una respuesta del servidor después de hacer el requerimiento. Una vez otra vez, generalmente vemos una función anónima aquí. La función se pasa en un parámetro, el servidor responde. La respuesta puede ser cualquier cosa, desde ‘sí’ o ‘no’ hasta una base de datos XML. Los datos en formato JSON también son útiles. La respuesta no se requiere siempre. Si no hay, entonces no se precisa una llamada de vuelta. En interés de la experiencia de usuario, siempre es una buena idea hacer saber al usuario que algo ha ocurrido, indicándoselo.

En nuestro ejemplo, sustituimos el actual texto a continuación del input radio con la respuesta del servidor, que incluye el número de artículos etiquetados por el título del libro. Aquí está nuestra función anónima de llamada de vuelta:

data contiene toda la respuesta del servidor. Más tarde asignamos a this2 el objeto que desencadena el evento de cambio (referenciado como this) con la línea var this2=this;. Esto es porque el alcance de las variables entre paréntesis sólo alcanza un nivel. Asignando this2 en el manejador de evento (la parte que inicialmente contenía /* do stuff */), somos capaces de utilizarla en la llamada de vuelta donde this estaría fuera de alcance.

La respuesta del servidor puede tomar cualquier forma. Cantidades significativas de datos deberán ser codificados dentro de flujos de datos para un manejo más sencillo. XML y JSON son dos esquemas de codificación habituales.

  • XML

XML es el formato de intercambio de datos clásico de AJAX.  Continúa siendo un formato de intercambio viable, aunque es difícil su manejo con funciones PHP nativas. Algunos programadores PHP prefieren el formato de intercambio JSON por esta razón.

  • JSON

JSON es a menudo preferido por su peso ligero y facilidad de uso. Actualmente puedes analizar JSON utilizando eval(), pero no lo hagas. El empleo de eval() conlleva significantes riesgos de seguridad. En su lugar, utiliza un analizador dedicado, que además es más rápido. Utiliza la instancia global el analizador de objetos JSON. Para asegurarte que está habilitado, asegúrate que está ‘enqueue’ con otros scripts en la página. Más información en la sección de PHP.

  • Otros

Mientras que el formato de datos está coordinado con el manejador PHP, puede ser cualquier formato que quieras, como delimitado con comas, con tabs, o cualquier tipo de estructura que a ti te funcione.

  • Resumen del lado cliente

Ahora que hemos añadido nuestra llamada de vuelta como el parámetro final para la función $.post(), hemos completado nuestro script jQuery AJAX. Todas las piezas puestas juntas quedan así:

Este script puede bien estar en un bloque en la página o bien contenido en su propio fichero. Este fichero puede residir en cualquier lugar de internet, pero muchos desarrolladores de plugins lo colocan en un subdirectorio /js/ del mismo directorio del plugin. Para este ejemplo llamamos el fichero myjquery.js.

 

PHP del lado servidor y anidación de script (enqueuing)

Hay dos partes del PHP de lado servidor que se necesitan para implementar la comunicación AJAX. Primero, necesitamos anidar el script jQuery en la página web y localizar cualesquiera valores PHP que el script jQuery necesite. Segundo, el manejo actual del requerimiento AJAX.

 

Anidar script

Esta sección cubre los dos mayores caprichos de AJAX en WordPress con que tropiezan desarrolladores experimentados nuevos en WordPress. Un es la necesidad de anidar los scripts para conseguir que los meta enlaces aparezcan correctamente en las secciones headers de la página. El otro es que todos los requerimientos AJAX necesitan ser enviados a través de wp-admin/admin-ajax.php. No envíes nunca requerimientos directamente a tus páginas del plugin.

 

Anidar

Utiliza la función wp_enqueue_script() para hacer que WordPress inserte un meta link a tu script en la sección página. Nunca código difícil como enlaces en la plantilla header. Como desarrollador de plugins, no tienes acceso directo a la plantilla header, pero cabe mencionar esta regla de todas formas.

La función enqueue tiene tres parámetros. El primero es una etiqueta arbitraria o  de manejo que se utiliza para referir a tu script en otras funciones. El segundo es la dirección completa URL a tu fichero script. Para portabilidad, utiliza plugins_url() para construir la misma URL. Si estás anidando el script para algo además de un plugin, utiliza algunas funciones relacionadas para crear un URL adecuado. El tercer parámetro es una matriz de cualquier etiqueta de script de la cual depende tu script. Teniendo en cuenta que estamos utilizando jQuery para enviar un requerimiento AJAX, necesitarás, como mínimo, listar ‘jquery’) en la matriz. Siempre utiliza una matriz sobretodo si es para una dependencia simple. La llamada de anidado para nuestro ejemplo se parece a esto:

Los scripts no se pueden anidar directamente desde el código de tu plugin cuando se carga. Los scripts se deben anidar en uno de los ganchos de acción – el cual depende de en qué tipo de página el script necesita ser vinculado. Para páginas de administración, utiliza admin_enqueue_scripts. Para páginas del front-end, utiliza wp_enqueue_scripts, excepto para la página de login, en cuyo caso debes utilizar login_enqueue_scripts.

El gancho admin_enqueue_scripts pasa el nombre de fichero de la página actual a tu llamada de vuelta. Utiliza esta información para sólo anidar tu script en páginas donde sea necesario. La versión front-end no pasa nada. En tal caso, utiliza etiquetas de plantilla tales como is_home()is_single(), etc, para asegurarte que sólo anidas tu script cuando es necesario. Este es el código completo de anidación de nuestro ejemplo:

¿Porqué utilizamos una función con nombre aquí, pero utilizamos una función anónima con jQuery? Porque los paréntesis sólo son soportados recientemente por PHP. jQuery los ha soportado desde hace algún tiempo. Como algunas personas pueden todavía utilizar versiones antiguas de PHP, nosotros siempre utilizamos funciones nombradas para máxima compatibilidad. Si tienen una versión reciente de PHP y estás desarrollando sólo para tu propia instalación, hazlo como quieras.

  • Registra vs. anidar

Verás ejemplos en otros tutoriales que emplean wp_register_script(). Su uso es correcto, pero opcional. Lo que no es opcional es wp_enqueue_script(). Esta función debe llamarse con el fin de que tu fichero de script sea adecuadamente vinculado en la página web. Entonces, ¿porqué registrar scripts? Ello crea una etiqueta útil o manejable con la cual puedes fácilmente referenciar el script en tantas partes de tu código como necesites. Si sólo necesitas el script cargado y no hay más referencias a él en ningún otro lugar en tu código, no necesitas registrarlo.

 

Nonce

Necesitas crear un ‘nonce’ para que el requerimiento jQuery AJAX pueda ser validado como un requerimiento legitimado, en lugar de un requerimiento potencialmente dañino de algún actor malo desconocido. Sólo tu script PHP y tu script jQuery conocerán dicho valor. Cuando el requerimiento es recibido, puedes verificar si es el mismo valor creado aquí. Así es como crear un ‘nonce’ para nuestro ejemplo:

El parámetro title_example puede ser cualquier cadena arbitraria. Se sugiere que la cadena esté relacionada con aquello para lo que se utiliza el ‘nonce’, pero puede ser cualquier cosa que se te ocurra.

 

Localizar

Como viste en la sección jQuery, los datos creados por PHP para utilizar con jQuery se pasan en un objeto global llamado my_ajax_obj. En nuestro ejemplo, este dato era un ‘nonce’ y la URL completa a admin-ajax.php. El proceso de asignar las propiedades de los objetos y crear el objeto global jQuery se llama localizar. Este es el código de localización utilizado en nuestro ejemplo el cual utiliza wp_localize_script().

Observa cómo nuestro manejador de script ajax-script se utiliza ya que el objeto global es asignado al script correcto. El objeto es global en nuestro script, no para todos los scripts. La localización también se puede llamar desde el mismo gancho que se utiliza para anidar scripts. Lo mismo sirve para crear un ‘nonce’, difícil que una función particular pueda ser llamada virtualmente desde cualquier sitio. Todo ello combinado junto en una simple llamada de vuelta de un gancho se parece a esto:

 

Acción AJAX

La otra gran parte del código PHP del lado servidor es el manejador actual AJAX que recibe los datos mediante POST, hace algo con ellos, y entonces envía una respuesta adecuada de vuelta al navegador. Esto se hace en la forma de un gancho de acción de WordPress. Qué etiqueta de gancho utilices depende de si el usuario está logeado o no y qué valor tu script jQuery pasó como ‘action: value’.

NOTA: $_GET, $_POST y $_COOKIE vs $_REQUEST

Probablemente has usado una o más de las super globales PHP tales como $_GET o $_POST para devolver valores de formularios o cookies (utilizando $_COOKIE). Quizás prefieres más $_REQUEST en su lugar, o lo has visto utilizar. Es una especie de fresco – sin tener en cuenta el método de requerimiento, POST o GET – tendrá los valores del formulario. Trabaja mejor para páginas que utilizan ambos métodos. Además de todo, también tiene valores de cookies. En este respecto radica su trágico defecto. En el caso de un conflicto de nombres, el valor de cookie sobre-escribirá cualquier valor de formulario. Así es ridículamente fácil para un mal actor crear una cookie falsa en su navegador, la cual sobre-escribirá cualquier valor de formulario que estés esperando del requerimiento. $_REQUEST es una ruta fácil para hackers para inyectar datos arbitrarios en tus formularios. Para estar más seguros, pega a las variables específicas y evita las generalidades.

Desde que nuestro intercambio AJAX es para la página de ajustes del plugin, el usuario debe estar logeado. Si en la sección jQuery, ‘action: value’ es ‘my_tag_count’. Esto significa que nuestro gancho de acción será wp_ajax_my_tag_count. Si nuestro intercambio AJAX iba a ser utilizado por usuarios que no estaban logeados, el gancho de acción será wp_ajax_nopriv_my_tag_count. El código básico utilizado para enganchar la acción es como esto:

La primera cosa que el manejador AJAX realizará será verificar el ‘nonce’ enviado por jQuery con check_ajax_referer(), que será el mismo valor que se localizó cuando se anidó el script.

El parámetro provisto debe ser idéntico al parámetro provisto anteriormente a wp_create_nonce(). La función simplemente muere si el ‘nonce’ no es chequeado. Si era un ‘nonce’ correcto, ahora que ha sido utilizado, el valor ya no volverá a ser válido. Deberás entonces generar uno nuevo y enviarlo al script de llamada de vuelta para que pueda ser utilizado en el próximo requerimiento. Pero desde que los ‘nonces’ de WordPress son válidos para 24 horas, no necesitarás nada más que chequearlo.

 

Datos

Con el ‘nonce’ fuera del camino, nuestro manejador puede negociar con los datos enviados por el script jQuery contenidos en $_POST[‘title’]. Podemos guardar la selección del usuario en user meta mediante update_user_meta().

Luego escribimos una consulta para tomar el contador de artículos para la etiqueta de título seleccionada.

Finalmente, podemos enviar la respuesta al script jQuery. Existen diferentes maneras de transmitir datos. Veamos algunas de las opciones antes de elegir la específica de nuestro ejemplo.

  • XML

El soporte de PHP para XML deja mucho que desear. Afortunadamente, WordPress provee la clase WP_Ajax_Response para hacer la tarea más fácil. La clase WP_Ajax_Response generará una respuesta con formato XML, selecciona el tipo de contenido correcto para la cabecera, devuelve la respuesta xml, y entonces muere – asegurando una respuesta XML apropiada.

  • JSON

Este formato es ligero y fácil de usar, y WordPress provee la función wp_send_json para codificar tu respuesta, imprimirla, y morir – efectivamente reemplazando WP_Ajax_Response. WordPress también provee las funciones wp_send_json_successwp_send_json_error, las cuales permiten las llamadas de vuelta apropiadas done()fail() activar en JavaScript.

  • Otros

En una aplicación del mundo real, debes tener en cuenta la posibilidad de que la acción pueda fallar por cualquier razón – por ejemplo, el servidor de bases de datos puede estar caído. La respuesta debe contemplar esta contingencia, y el script jQuery al recibir dicha respuesta debe actuar adecuadamente, quizá sugiriendo al usuario que lo intente más tarde.

 

Die (muerte)

Cuando el manejador ha terminado todas sus tareas, necesita morir. Si estás utilizando las funciones WP_Ajax_Responsewp_send_json, esto se hace automáticamente. Si no, simplemente utiliza la función de WordPress wp_die().

 

Resumen del manejador AJAX

El manejador AJAX completo para nuestro ejemplo sería así:

 

Resumen final

Aquí están los snippets del código de ejemplo del actual capítulo, ensamblados en dos páginas de código completas: una para jQuery y la otra para PHP.

 

PHP

Este código reside en una de las páginas de tu plugin.

 

jQuery

Este código está en el fichero js/myjquery.js perteneciente al directorio de tu plugin.

Y después de guardar la preferencia, el contador de artículos resultante se añade al título seleccionado.

 

Más información

 

Una respuesta a “23. JavaScript, AJAX y jQuery”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *