Existe un momento crucial en la carrera de un desarrollador web: cuando un cliente solicita la implementación de un efecto de «scroll infinito» en determinado listado de la página. Esta solicitud es un hito que todo desarrollador o programador debe enfrentarse, ya que implica comprender conceptos fundamentales relacionados con la extracción de contenido de bases de datos.
En proyectos que involucran esta funcionalidad, surgen preguntas clave, tales como:
- ¿Quiero que se cargue automáticamente más contenido cuando llegue el scroll a un punto determinado de la página?
- ¿Voy a cargar los siguientes elementos haciendo click en un botón «cargar más»?
- ¿Cuántos elementos quiero cargar por vista?
- ¿Necesito poner un «spinner»?
- ¿Voy a poner un efecto «skeleton» a la estructura?
Vamos a tratar de solucionar algunas de estas preguntas.
¿Cómo empiezo a programar esto?
En este tutorial, exploraremos la opción de cargar más contenido al presionar un botón. Para lograrlo, es necesario tener un buen manejo de la clase de WordPress «WP_Query()» para extraer contenido de la base de datos. Además, es crucial comprender cómo funciona AJAX con JavaScript (jQuery) para activar la función de WordPress que añadirá nuevo contenido, y dominar el CSS para dar los estilos necesarios a la implementación.
De manera condicional, crearemos un botón utilizando PHP y HTML, el cual verificará a través de WP_Query
si hay más de una página que mostrar. En caso de que solo haya una página disponible, el botón desaparecerá automáticamente. Esto crea un efecto para el usuario que indica que ha llegado al final de los contenidos. Para lograr esto, utilizaremos la variable max_num_pages
. Este efecto contribuye a una experiencia de usuario positiva.
Puedes ver un ejemplo de un botón, no es el definitivo pero para que entiendas cual es nuestro activador desde donde comienza toda la magia.
<?php
global $wp_query;
// No mostraremos el botón cargar más si no hay mas elementos que cargar.
if( 1 < $wp_query->max_num_pages ) {
echo '<div class="ie_loadmore">Cargar más</div>'; // Puedes utilizar un elemento <a>.
}
?>
Lo primero que debemos hacer es crear un archivo .js, en nuestro caso llamado myloadmore.js, y luego definir una función en el archivo functions.php del tema hijo donde vamos a encolar el archivo que contendrá el código JavaScript que necesitamos.
En esta función es importante indicar que vamos a utilizar la librería jQuery integrada en WordPress. Pasaremos algunas variables de PHP para poder utilizar su contenido en el archivo JavaScript:
ajax_url: Esta variable guarda la URL de la ruta del archivo admin-ajax.php, lo cual es muy útil para ejecutar nuestras funciones Ajax.
posts: La función json_encode
transforma el contenido de las noticias de PHP a un formato JSON para JavaScript.
current_page: Almacena el número de página actual.
max_page: Calcula el número de páginas que va a tener el listado que hemos indicado, en nuestro caso, de noticias.
En este punto, es importante darse cuenta o comprender la importancia de conectar un archivo PHP con un archivo JavaScript. Esto nos permite pasar contenidos para manipularlos y activar funciones de PHP desde funciones de JavaScript.
Puedes colocar el siguiente código en el functions.pho o plugin de personalizaciones. Modifica variables o textos que se adapten a tu proyecto.
function ie_cargar_scripts_cargar_mas_noticias() {
// En la mayoría de los casos ya está incluido en la página y esta línea se puede eliminar
wp_enqueue_script('jquery');
// registramos nuestro script principal pero no lo encolamos aún
wp_register_script( 'my_loadmore', get_stylesheet_directory_uri() . '/myloadmore.js', array('jquery') );
// ahora la parte más interesante
// tenemos que pasar parámetros al script myloadmore.js pero solo podemos obtener los valores de los parámetros en PHP
// puedes definir variables directamente en tu HTML pero he decidido que la manera más adecuada es wp_localize_script()
wp_localize_script( 'my_loadmore', 'ie_loadmore_noticias_params', array(
'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php', // AJAX de WordPress
'posts' => json_encode( $more_posts_grid_noticias->query_vars ), // todo sobre tu bucle está aquí
'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1,
'max_page' => $more_posts_grid_noticias->max_num_pages
) );
wp_enqueue_script( 'my_loadmore' );
}
add_action( 'wp_enqueue_scripts', 'ie_cargar_scripts_cargar_mas_noticias' );
¿Buscar un programador web para hacer un periódico o revista online en WordPress?
Me especializo en desarrollar sitios webs avanzados y dinámico, programando todo tipo de soluciones personalizadas para proyectos web no noticias, anuncios, cursos…
Query o Consulta
La estructura con el listado de noticias la vamos a obtener haciendo una consulta con la clase WP_Query() de WordPress, a la que le indicaremos todo tipo de argumentos necesarios para perfeccionar el resultado. Extraeremos los datos exactos con el contenido que necesitamos para montar un grid de noticias.
La primera función «ie_cargar_mas_noticias_seccion_grid» la vamos a meter en un shortcode
de WordPress para luego utilizarla donde queramos dentro del nuestras plantillas o páginas del sitio.
Como puedes ver es un loop que nos va a devolver 8 noticias que he maquetado con HTML y algunas funciones de WordPress. Puedes investigar que hace cada una de ella, te pueden servir para tus proyectos igualmente.
Esta estructura HTML lleva el botón definitivo de cargar más.
La segunda función «ie_cargar_mas_noticias_ajax_handler» es la que se activa cuando se acciona el botón de cargar más (Mediante Javascript como hemos comentado que tenemos conectados estos archivos de php y js) entonces esta función obtiene siempre la siguiente página de la página actual y añade 8 elementos nuevos al grid que ya tenemos integrado.
Está función se ejecuta sobre los hooks especialmente desarrollados para ejecutar contenido Ajax en WordPress. «wp_ajax_loadmore_noticias» «wp_ajax_nopriv_loadmore_noticias»
Utiliza el siguiente código en el archivo functions.php o plugin de personalizaciones. Modifica argumentos, clases, parámetros, estructura HTML a tu gusto.
<?php
function ie_cargar_mas_noticias_seccion_grid( $atts) {
extract( shortcode_atts( array(
'category' => 'noticias'
), $atts ) );
ob_start();
global $wp_query;
$args = array(
'post_type' => 'post',
'paged' => $paged,
'posts_per_page' => 8,
);
if ( ! empty( $category ) ) {
$args['category_name'] = $category;
}
$more_posts_grid_noticias = new WP_Query( $args ); ?>
<?php if ( $more_posts_grid_noticias->have_posts() ) : ?>
<!-- paginación aquí -->
<!-- el bucle -->
<?php while ( $more_posts_grid_noticias->have_posts() ) : $more_posts_grid_noticias->the_post(); ?>
<div class="articulo__secciones articulo__secciones__grid">
<a href="<?php the_permalink(); ?>">
<div class="seccion__1__contenido">
<h3 class="articulo__secciones__titulo"><?php the_title(); ?></h3>
<div class="seccion__1__contenido__texto"><?php echo wp_strip_all_tags( get_the_content() ); ?></div>
</div>
<div class="seccion__imagen"><?php the_post_thumbnail() ?></div>
</a>
</div>
<?php endwhile; ?>
<?php
// no mostrar el botón si no hay suficientes publicaciones
if ( $more_posts_grid_noticias->max_num_pages > 1 ) { ?>
<div class="hr-theme-slash-2 ie_loadmore_noticias">
<div class="hr-line"></div>
<div class="hr-icon">
<svg width="24px" height="15px" viewBox="0 0 24 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Path</title>
<g id="disseny" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="ie-el-articulo-seccion" transform="translate(-948.000000, -1295.000000)" fill="#D8D8D8" fill-rule="nonzero">
<polygon id="Path" points="960 1309.15 948 1297.15 950.15 1295 960 1304.85 969.85 1295 972 1297.15"></polygon>
</g>
</g>
</svg>
</div>
<div class="hr-line"></div>
</div>
<?php } ?>
<?php wp_reset_postdata(); ?>
<?php else : ?>
<p><?php _e( 'Lo siento, no se encontraron publicaciones que coincidan con tus criterios.' ); ?></p>
<?php endif; ?>
<?php
$output = ob_get_clean();
return $output;
}
add_shortcode( 'cargar-mas-noticias-grid', 'ie_cargar_mas_noticias_seccion_grid' );
function ie_cargar_mas_noticias_ajax_handler(){
global $wp_query;
// preparamos nuestros argumentos para la consulta
$args = json_decode( stripslashes( $_POST['query'] ), true );
$args['paged'] = $_POST['page'] + 1; // necesitamos cargar la siguiente página
$args['post_status'] = 'publish';
$args['posts_per_page'] = '8';
$args['category_name'] = 'noticias';
// siempre es mejor usar WP_Query, pero no aquí
query_posts( $args );
if( have_posts() ) :
// ejecutamos el bucle
while( have_posts() ): the_post(); ?>
<div class="articulo__secciones articulo__secciones__grid">
<a href="<?php the_permalink(); ?>">
<div class="seccion__1__contenido">
<h3 class="articulo__secciones__titulo"><?php the_title(); ?></h3>
<div class="seccion__1__contenido__texto"><?php echo wp_strip_all_tags( get_the_content() ); ?></div>
</div>
<div class="seccion__imagen"><?php the_post_thumbnail() ?></div>
</a>
</div>
<?php endwhile;
endif;
die; // aquí salimos del script y ni siquiera es necesario wp_reset_query()!
}
add_action('wp_ajax_loadmore_noticias', 'ie_cargar_mas_noticias_ajax_handler'); // wp_ajax_{action}
add_action('wp_ajax_nopriv_loadmore_noticias', 'ie_cargar_mas_noticias_ajax_handler'); // wp_ajax_nopriv_{action}
Javascript
Ya solo nos queda poner este fragmento de código en el archivo myloadmore.js que hemos creado al principio. Este será el encargado de ejecutar Ajax y de mover la data
de un sitio a otro sin necesidad de recargar la página mediante el método post
de ajax.
Algo interesante que puedes hacer es poner en beforeSend o bien añadir un spinner de carga o un texto si has añadido un botón con texto. En mi caso como solo es una flecha no le he puesto nada.
jQuery(function($){ // Utiliza código jQuery dentro de esta función para evitar el error "$ is not defined"
$('.ie_loadmore_noticias').click(function(){
var button = $(this),
data = {
'action': 'loadmore_noticias',
'page' : ie_loadmore_noticias_params.current_page
};
$.ajax({ // También puedes utilizar $.post aquí
url : ie_loadmore_noticias_params.ajaxurl, // Controlador de AJAX
data : data,
type : 'POST',
beforeSend : function ( xhr ) {
// Cambia el texto del botón, también puedes añadir una imagen de precarga
},
success : function( data ){
if( data ) {
button.before(data); // Inserta nuevas entradas
ie_loadmore_noticias_params.current_page++;
if ( ie_loadmore_noticias_params.current_page == ie_loadmore_noticias_params.max_page )
button.remove(); // Si es la última página, elimina el botón
// También puedes activar el evento "post-load" aquí si usas un plugin que lo requiera
// $( document.body ).trigger( 'post-load' );
} else {
button.remove(); // Si no hay datos, elimina también el botón
}
}
});
});
});
CSS
Ya solo queda que remates la maquetación utilizando técnicas avanzadas de CSS. Te dejo algunas interesantes que te pueden ayudar:
- CSS Grid
- Flexbox
- text-wrap (balance y pretty)
- aspect-ratio (Para evitar saltos en la carga de contenidos)
- transition
- view-transitions (muy avanzado)
Pros y contras del uso del scroll infinito
VENTAJAS
- Mejora la experiencia de usuario al ofrecer una navegación fluida.
- Aumenta el tiempo de permanencia de un usuario en la web.
- Podemos retrasar la carga de grandes cantidades de contenidos, sin sobrecargar la web.
- Ofrecer un efecto «red social».
INCONVENIENTES
- Puede afectar en el rendimiento si no se programa bien la carga adicional de contenidos.
- Problemas en la indexación de estos elementos adiciones que estarán ocultos.
¿Cuándo podemos utilizar un buen scroll infinito?
- Cargar nuevas entradas de un blog.
- Tienda online para mostrar más productos en general o por categorías.
- Cargar proyectos anteriores en un portafolios profesional.
- En un directorio de empresas o profesionales. Desatacando por ejemplo los mejor valorados o los que pagan por estar en primeras posiciones.
- Periódico o revista online para cargar noticias antiguas.
Espero que puedas aprovechar algo de la información que he compartido. Si estas probando este método y te sale, por favor házmelo saber, si por el contrario no te ha funcionado, coméntamelo para poder ayudarte.
¡Muchas Gracias!