Reordenar imágenes mediante drag and drop con jQuery, Ajax, PHP y MySQL

Todos conocéis la acción de drag and drop, que traducido al castellano sería algo así como arrastrar y soltar. Es una característica que suelen tener ciertas páginas webs para dotar a sus interfaces de un entorno amigable pensado en la comodidad del usuario. Con jQuery UI es muy sencillo añadir la funcionalidad de drag&drop a un elemento DOM. En este tutorial veremos como utilizar esta acción para ordenar los elementos de un listado.

Si queremos controlar el orden en el que se muestran las imágenes dentro de un listado de imágenes, dicho orden debe almacenarse en la base de datos. En este tutorial veremos una forma de ordenar imágenes mucho más interactiva mediante la acción de drag&drop. Es decir, mediante jQuery el usuario podrá mover las imágenes en función del orden que les quiera dar, y después almacenaremos ese nuevo orden en la base de datos MySQL. Esto es muy útil para gestionar galerías de imágenes, listados de usuarios...

Antes de empezar, echa un vistazo a la estructura de carpetas y archivos que utilizaremos para ordenar imágenes mediante drag and drop con jQuery, Ajax, PHP y MySQL.

db.php
orderUpdate.php
index.php
style.css
images/

Creación de la base de datos

Para almacenar la información imágenes que se vayan subiendo con el número de orden en el que se muestran, necesitamos una tabla MySQL en nuestra base de datos. El siguiente código SQL crea una tabla llamada images con los campos necesarios.

CREATE TABLE `images` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `img_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `img_order` int(5) NOT NULL DEFAULT '0',
 `created` datetime NOT NULL,
 `modified` datetime NOT NULL,
 `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Clase DB (db.php)

La clase DB gestiona todo lo relativo con la base de datos. Para ello tendrás que especificarle el host, usuario, contraseña y nombre de tu base de datos. La clase DB contiene dos métodos para leer y actualizar las imágenes:

  • getRows(): función que lee todas las imágenes de la base de datos
  • updateOrder(): función que actualiza el orden de las imágenes en la base de datos
<?php
class DB{
    //database configuration
    private $dbHost     = "localhost";
    private $dbUsername = "root";
    private $dbPassword = "";
    private $dbName     = "programacionnet";
    private $imgTbl     = 'images';
    
    function __construct(){
        if(!isset($this->db)){
            // Connect to the database
            $conn = new mysqli($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbName);
            if($conn->connect_error){
                die("Failed to connect with MySQL: " . $conn->connect_error);
            }else{
                $this->db = $conn;
            }
        }
    }
    
    function getRows(){
        $query = $this->db->query("SELECT * FROM ".$this->imgTbl." ORDER BY img_order ASC");
        if($query->num_rows > 0){
            while($row = $query->fetch_assoc()){
                $result[] = $row;
            }
        }else{
            $result = FALSE;
        }
        return $result;
    }
    
    function updateOrder($id_array){
        $count = 1;
        foreach ($id_array as $id){
            $update = $this->db->query("UPDATE ".$this->imgTbl." SET img_order = $count WHERE id = $id");
            $count ++;    
        }
        return TRUE;
    }
}
?>

Actualizar el orden de las imágenes (orderUpdate.php)

El archivo order_update.php recibe el orden actual de las imágenes del fichero index.php a través de Ajax. Rompemos la cadena de Ids en un array y se lo pasamos a la clase DB para actualizar el orden de las imágenes.

<?php
//include database class
include_once 'db.php';
$db = new DB();

//get images id and generate ids array
$idArray = explode(",",$_POST['ids']);

//update images order
$db->updateOrder($idArray);
?>

Reordenar imágenes mediante Drag and Drop (index.php)

El archivo index.php muestra las imágenes y permite al usuario reordenarlas mediante drag&drop.

Javascript

Antes que nada, debemos incluir las librerías de jQuery y de jQuery UI.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

El siguiente código jQuery los utilizamos para habilitar las características sortable() e implementar la funcionalidad drag&drop. Cuando el usuario envíe la solicitud de guardado, el actual orden de las imágenes se enviará a orderUpdate.php utilizando Ajax para actualizarlo.

<script>
$(document).ready(function(){
    $('.reorder_link').on('click',function(){
        $("ul.reorder-photos-list").sortable({ tolerance: 'pointer' });
        $('.reorder_link').html('save reordering');
        $('.reorder_link').attr("id","save_reorder");
        $('#reorder-helper').slideDown('slow');
        $('.image_link').attr("href","javascript:void(0);");
        $('.image_link').css("cursor","move");
        $("#save_reorder").click(function( e ){
            if( !$("#save_reorder i").length ){
                $(this).html('').prepend('<img src="images/refresh-animated.gif"/>');
                $("ul.reorder-photos-list").sortable('destroy');
                $("#reorder-helper").html( "Reordering Photos - This could take a moment. Please don't navigate away from this page." ).removeClass('light_box').addClass('notice notice_error');
    
                var h = [];
                $("ul.reorder-photos-list li").each(function() {  h.push($(this).attr('id').substr(9));  });
                
                $.ajax({
                    type: "POST",
                    url: "orderUpdate.php",
                    data: {ids: " " + h + ""},
                    success: function(){
                        window.location.reload();
                    }
                }); 
                return false;
            }   
            e.preventDefault();     
        });
    });
});
</script>

PHP y HTML

Inicialmente, todas las imágenes se extraen de la base de datos utilizando PHP y clase DB. Una vez se clique el enlace de Reorder, la función de drag&drop se habilitará.

<?php
//include database class
include_once 'db.php';
$db = new DB();
?>
<div>
    <a href="javascript:void(0);" class="btn outlined mleft_no reorder_link" id="save_reorder">reorder photos</a>
    <div id="reorder-helper" class="light_box" style="display:none;">1. Drag photos to reorder.<br>2. Click 'Save Reordering' when finished.</div>
    <div class="gallery">
        <ul class="reorder_ul reorder-photos-list">
        <?php 
            //Fetch all images from database
            $images = $db->getRows();
            if(!empty($images)){
                foreach($images as $row){
        ?>
            <li id="image_li_<?php echo $row['id']; ?>" class="ui-sortable-handle"><a href="javascript:void(0);" style="float:none;" class="image_link"><img src="images/<?php echo $row['img_name']; ?>" alt=""></a></li>
        <?php } } ?>
        </ul>
    </div>
</div>

style.css

Este archivo contiene el código CSS que utilizaremos para personalizar la galería de imágenes y los enlaces.

.reorder_link {
    color: #3675B4;
    border: solid 2px #3675B4;
    border-radius: 3px;
    text-transform: uppercase;
    background: #fff;
    font-size: 18px;
    padding: 10px 20px;
    margin: 15px 15px 15px 0px;
    font-weight: bold;
    text-decoration: none;
    transition: all 0.35s;
    -moz-transition: all 0.35s;
    -webkit-transition: all 0.35s;
    -o-transition: all 0.35s;
    white-space: nowrap;
}
.reorder_link:hover {
    color: #fff;
    border: solid 2px #3675B4;
    background: #3675B4;
    box-shadow: none;
}
#reorder-helper{margin: 18px 10px;padding: 10px;}
.light_box {
    background: #efefef;
    padding: 20px;
    margin: 10px 0;
    text-align: center;
    font-size: 1.2em;
}

.gallery{ width:100%; float:left; margin-top:100px;}
.gallery ul{ margin:0; padding:0; list-style-type:none;}
.gallery ul li{ padding:7px; border:2px solid #ccc; float:left; margin:10px 7px; background:none; width:auto; height:auto;}
.gallery img{ width:250px;}

/* NOTICE */
.notice, .notice a{ color: #fff !important; }
.notice { z-index: 8888; }
.notice a { font-weight: bold; }
.notice_error { background: #E46360; }
.notice_success { background: #657E3F; }

Fuente: codexworld.com

COMPARTE ESTE ARTÍCULO

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