Scroll infinito como el de Facebook utilizando jQuery, PHP y MySQL

En este tutorial vamos a implementar un scroll infinito como el de Facebook utilizando jQuery, PHP y MySQL. Lo que en realidad haremos es hacer una solicitud al servidor vía ajax para si el usuario desea ver más datos. Este script es muy útil si estamos implementando una red social, donde la paginación tradicional esta fuera de lugar, por ejemplo.

Es posible implementar el scroll infinito de dos maneras:

  • Una forma de hacerlo es realizando una petición ajax al servidor y recibiendo la respuesta con los datos en formato JSON. Después tendremos que hacer todo el proceso en el lado del cliente.
  • La segunda forma de hacerlo es realizando una petición ajax al servidor para obtener los datos de la base de datos. Esos datos estarán formateados en HTML según el diseño de la página, y se devolverán de ese modo al lado del cliente. Después con los datos HTML devueltos, los mostraremos en la página.

En el segundo método hacemos todo el proceso desde el propio servidor. Si crees que el número de visitantes va a aumentar en tu sitio, hacer todo el proceso en el lado del servidor es mala idea. Aumenta el coste de operación de los servicios, así que lo mejor es hacer la mayor parte del proceso en el lado del cliente, reduciendo así los costes operativos de tu negocio.

Crea el fichero index.php y añádele el siguiente código HTML

Créate un directorio llamado infinite-scroll en la carpeta htdocs del directorio raíz de tu servidor. Después crea la siguiente lista de carpetas (css, js) en el directorio llamado infinite-scroll. Más tarde, descárgate bootstrap y los archivos de jQuery, y añádelos en sus respectivos directorios css y js. Ahora crea un archivo llamado index.html y no te olvides de incluir dentro de él la llamada a los distintos archivos css y js.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Infinite Scroll</title>
	<!-- Bootstrap -->
	<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,300,200' rel='stylesheet' type='text/css'>	
	<link href="css/bootstrap.min.css" rel="stylesheet">
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
	<link href="css/style.css" rel="stylesheet">

	<!-- Script -->
	<script src="js/jquery.min.js"></script>
	<script src="js/bootstrap.min.js"></script>
	<script src="js/script.js"> </script>
</head>
<body>

Petición ajax del scroll infinito

Cuando la altura total del documento sea igual a la altura de la ventana más la altura total del scroll, automáticamente se realizará la petición ajax para obtener datos del servidor.

Como véis impido hacer múltiples peticiones Ajax al mismo tiempo con los mismos parámetros. Cada vez que hacemos una petición Ajax tenemos que pasarle un mínimo de dos parámetros que son los límites de las consultas MySQL (en qué registro debe empezar y el número de registros que quiero que se muestren.). Albergo esos dos valores en los campos ocultos HTML como puedes ver en el código de más abajo.

<input type="hidden" id="first" value="<?php echo FIRST; ?>" />
<input type="hidden" id="limit" value="<?php echo LIMIT; ?>" >

Mientras realizo la petición ajax, obtengo el valor de los dos campos ocultos...

first = $('#first').val();
limit = $('#limit').val();

...y se los paso al servidor.

data: {
     start : first,
     limit : limit
}

Cuando obtengas la respuesta del servidor, tendremos que incrementar el valor límite para obtener el siguiente conjunto de valores desde el servidor.

first = parseInt($('#first').val());
limit = parseInt($('#limit').val());
$('#first').val( first+limit );

Aquí tienes el script completo de la petición de ajax.

flag = true;
$(window).scroll(function() {
	if($(window).scrollTop() + $(window).height() == $(document).height()){
		first = $('#first').val();
		limit = $('#limit').val();
		no_data = true;
		if(flag && no_data){
			flag = false;
			$('#loader').show();
			$.ajax({
				url : 'ajax.php',
				dataType: "json",
				method: 'post',
				data: {
				   start : first,
				   limit : limit
				},
				success: function( data ) {
					flag = true;
					$('#loader').hide();
					if(data.count > 0 ){
						first = parseInt($('#first').val());
						limit = parseInt($('#limit').val());
						$('#first').val( first+limit );
						$('#timeline-conatiner').append( '<li class="year">'+year+'</li>');
						$.each(data.content, function(key, value ){
							html = '<li class="event">';
							html += '<h3 class="heading">'+value.name+'</h3>';
							html += '<span class="month"><i class="fa fa-calendar"></i>'+value.name+'</span><p>&nbsp;</p>';
							html += '<p><a href="'+value.demo+'" target="_blank">Demo </a></p>';
							html += '<p><a href="'+value.tutorial+'" target="_blank">Tutorial </a></p>';
							
							if(value.media_type == 'video' && value.media !=''){
								html += '<div class="embed-responsive embed-responsive-16by9">';
								html += '<iframe frameborder="0" allowfullscreen="allowfullscreen" src="'+value.media+'" class="embed-responsive-item"></iframe>';
								html += '</div>';
							}
							if(value.media_type == 'image' && value.media !='' ){
								html += '<div class="text-center">';
								html += '<img class="img-responsive img-thumbnail" src="'+value.media+'">';
								html += '</div>';
							}
							html += '<p>'+value.description+'</p>';
							html += '</li>';
							$('#timeline-conatiner').append( html );
						});
						year--;
					}else{
						alert('No more data to show');
						no_data = false;
					}
				},
				error: function( data ){
					flag = true;
					$('#loader').hide();
					no_data = false;
					alert('Something went wrong, Please contact admin');
				}
			});
		}
		
		
	}
});	
	

Te habrás fijado en que los datos vienen formateados en JSON, es por eso que utilizo el comando $.each() de jQuery y después formo el HTML y lo asigno al timeline del diseño.

Gestionar la petición ajax del scroll infinito desde el lado del servidor

Crea la tabla timeline utilizando los siguientes comandos SQL

CREATE TABLE IF NOT EXISTS `timeline` (
`id` int(11) NOT NULL,
  `name` varchar(250) NOT NULL,
  `description` text NOT NULL,
  `media` varchar(250) NOT NULL,
  `media_type` enum('video','image') NOT NULL,
  `demo` varchar(300) NOT NULL,
  `tutorial` varchar(300) NOT NULL,
  `created` datetime NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=370 DEFAULT CHARSET=latin1;

Ahora vamos a crear el archivo config.php, que será el fichero encargado de albergar los datos de conexión a la base de datos.

define( 'BASE_PATH', 'http://localhost/timeline/');
define('DB_HOST', 'localhost');
define('DB_NAME', 'timeline');
define('DB_USERNAME','root');
define('DB_PASSWORD',''); 

$con = mysqli_connect(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);
if( mysqli_connect_error()) echo "Failed to connect to MySQL: " . mysqli_connect_error();


define('FIRST', 4);
define('LIMIT', 4);

Una vez tengamos el fichero config.php, crearemos uno nuevo llamado ajax.php que será el encargado de gestionar las peticiones ajax y de enviar la respuesta al cliente. Aquí tienes el código completo del archivo ajax.php

require_once 'config.php';

if( isset( $_POST['start'] ) && isset( $_POST['limit'] ) && !empty( $_POST['start'] ) && !empty( $_POST['limit'] ) ){
	$start = $_POST['start'];
	$limit = $_POST['limit'];
	$query = "SELECT * FROM timeline limit $start, $limit";
	$result = mysqli_query($con, $query) or die('Error: ' . mysqli_error($con));
	$data = array();
	$rowcount = mysqli_num_rows($result);
	$data['count'] = $rowcount;
	while($row = mysqli_fetch_assoc($result)) {
		$data['content'][] = $row;
	}
	mysqli_close($con);
	echo json_encode($data);exit;	
}

¿Cómo se implementaría el segundo método?

Aquí tienes el script de jQuery que realiza la petición ajax al servidor. Después simplemente inserta la respuesta del servidor directamente en el diseño del timeline.

flag = true;
$(window).scroll(function() {
	if($(window).scrollTop() + $(window).height() == $(document).height()){
		first = $('#first').val();
		limit = $('#limit').val();
		no_data = true;
		if(flag && no_data){
			flag = false;
			$('#loader').show();
			$.ajax({
				url : 'ajax_html.php',
				method: 'post',
				data: {
				   start : first,
				   limit : limit
				},
				success: function( data ) {
					flag = true;
					$('#loader').hide();
					if(data !=''){
						
						first = parseInt($('#first').val());
						limit = parseInt($('#limit').val());
						$('#first').val( first+limit );
						$('#timeline-conatiner').append( '<li class="year">'+year+'</li>');
						
						$('#timeline-conatiner').append( data );
						year--;
					}else{
						alert('No more data to show');
						no_data = false;
					}
				},
				error: function( data ){
					flag = true;
					$('#loader').hide();
					no_data = false;
					alert('Something went wrong, Please contact admin');
				}
			});
		}
		
		
	}
});	

Como puedes ver, el script no hace realmente nada, solo inserta la respuesta del servidor.

Aquí tienes el script de PHP que es el encargado de dar forma (formato HTML) a lo que se envía al lado del cliente. Dicha respuesta, posteriormente, se inserta directamente en el diseño.

require_once 'config.php';

if( isset( $_POST['start'] ) && isset( $_POST['limit'] ) && !empty( $_POST['start'] ) && !empty( $_POST['limit'] ) ){
	$start = $_POST['start'];
	$limit = $_POST['limit'];
	$query = "SELECT * FROM timeline limit $start, $limit";
	$result = mysqli_query($con, $query) or die('Error: ' . mysqli_error($con));
	$data = array();
	$rowcount = mysqli_num_rows($result);
	$data['count'] = $rowcount;
	$html = '';
	while($row = mysqli_fetch_assoc($result)) {
		$html .= '<li class="event">';
		$html .= '<h3 class="heading">'.$row['name'].'</h3>';
		$html .= '<span class="month"><i class="fa fa-calendar"></i>'.$row['name'].'</span><p>&nbsp;</p>';
		$html .= '<p><a href="'.$row['demo'].'" target="_blank">Demo </a></p>';
		$html .= '<p><a href="'.$row['tutorial'].'" target="_blank">Tutorial </a></p>';
			
		if($row['media_type'] == 'video' && $row['media'] !=''){
			$html .= '<div class="embed-responsive embed-responsive-16by9">';
			$html .= '<iframe frameborder="0" allowfullscreen="allowfullscreen" src="'.$row['media'].'" class="embed-responsive-item"></iframe>';
			$html .= '</div>';
		}
		if($row['media_type'] == 'image' && $row['media'] !='' ){
			$html .= '<div class="text-center">';
			$html .= '<img class="img-responsive img-thumbnail" src="'.$row['media'].'">';
			$html .= '</div>';
		}
		$html .= '<p>'.$row['description'].'</p>';
		$html .= '</li>';
	}
	mysqli_close($con);
	echo $html;exit;	
}

Fuente: smarttutorials.net

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP