Obtenga el orden de los elementos de la lista en una lista clasificable de jQuery después del recurso

8 minutos de lectura

Tengo una lista en mi sitio web. Estoy usando el tutorial clasificable de jQuery para que los usuarios puedan cambiar el orden de los elementos de la lista.

http://jqueryui.com/demos/sortable/

El truco es que me gustaría capturar el orden de los artículos inmediatamente después de un recurso y asignar los valores del pedido a los elementos de formulario ocultos que se pasarían a mi servidor a través de un envío de formulario donde podría usar un script php para guardar el nuevo pedido. de elementos en una base de datos.

Aquí está el código fuente de la demostración:

 <style>
    #sortable { list-style-type: none; margin: 0; padding: 0; width: 60%; }
    #sortable li { margin: 0 3px 3px 3px; padding: 0.4em; padding-left: 1.5em; font-size: 1.4em; height: 18px; }
    #sortable li span { position: absolute; margin-left: -1.3em; }
    </style>
    <script>
    $(function() {
        $( "#sortable" ).sortable();
        $( "#sortable" ).disableSelection();
    });
    </script>


<div class="demo">

<ul id="sortable">
    <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 1</li>
    <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 2</li>
    <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 3</li>
    <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 4</li>
    <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 5</li>
    <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 6</li>
    <li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 7</li>
</ul>

</div><!-- End demo -->

Y soy consciente de que también es posible asignar una función de devolución de llamada que se activa cuando se detiene la clasificación:

$( ".selector" ).sortable({
   stop: function(event, ui) { ... }
});

¡Gracias!

avatar de usuario
mattsven

Escribí una respuesta a esta pregunta hace 5 años, pero esa respuesta apestaba (y esta pregunta tiene casi 38,000 visitas), así que aquí hay una respuesta mejorada.

Hay esencialmente tres partes de esta pregunta que tienes que resolver. Veremos los tres.

Responder a los cambios en el orden de clasificación (Paso 1)

El primer problema que debemos resolver es reaccionar a los cambios en el orden de los elementos ordenados. Si revisamos el Widget Ordenable de jQuery UI documentaciónvemos que tiene un change event que se activa cada vez que cambia el orden de clasificación y es perfecto para nuestras necesidades.

Nota al margen: mi respuesta original utilizada stop en vez de change evento. change es mejor (al menos en este caso) porque informará todos los cambios en la clasificación, ya sea que el cambio haya sido interactivo (usuario) o programático, y solo si el orden realmente ha cambiado. Por otro lado, el sort El evento solo se activa cuando el usuario deja de ordenar (suelta el mouse o levanta el dedo).

Utilizando el sort evento, ahora podemos responder a los cambios en la clasificación. Lo siguiente inicializará un Sortable widget para nosotros, y nos permite configurar una función para que se llame cuando el sort incluso incendios:

var $sortableList = $("#your-list");

var sortEventHandler = function(event, ui){
    console.log("New sort order!");
};

$sortableList.sortable({
    stop: sortEventHandler
});

// You can also set the event handler on an already existing Sortable widget this way:

$sortableList.on("sortchange", sortEventHandler);

Una vez hecho esto, ahora estamos listos para dar el paso 2:

Recuperando los elementos ordenados (Paso 2)

Esta parte es bastante simple. Solo necesitamos obtener una matriz de los elementos en nuestra lista ordenada. Para hacer esto, solo podemos pedir a los hijos de los ul (lista) elemento, usando la función jQuery children():

var listElements = $sortableList.children();

console.log(listElements); // [ <li>, <li>, ... ]

Genial, pero necesitamos específicamente los valores del elemento:

var listValues = [];

listElement.forEach(function(element){
    listValues.push(element.innerHTML);
});

console.log(listValues); // [ "Item 1", "Item 2", ... ]

Usando .sortable("toArray") o .serialize() también son opciones.

¡Agradable! En el bit final.

Serialización y envío del nuevo pedido clasificado (Paso 3)

La serialización es “el proceso de traducir estructuras de datos o el estado del objeto a un formato que se puede almacenar (por ejemplo, en un archivo o búfer de memoria, o transmitir a través de un enlace de conexión de red)” (gracias Wikipedia!)

La forma en que lo haga depende mucho de sus necesidades específicas, por lo que solo analizaremos algunas de las formas en que podría hacerlo usando jQuery.

AJAX:

Si usamos AJAX, podemos enviar una solicitud al servidor con el nuevo pedido. jQuery manejará automáticamente la serialización listValues para nosotros:

$.post("your-server.com/save_order", { "items": listValues } );

O si prefieres JSON:

$.post("your-server.com/save_order", JSON.encode({ "items": listValues }) );

Forma

Crear un formulario:

<form action="your-server.com/save_order" method="POST">
    <input name="items" value="" />
</form>

Actualizar el item aporte:

var serializedValue = $.param(listValues);

$("#ourForm > input").val(JSON.encode(listValues));

Mándalo:

$("#ourForm").submit()

Respuesta antigua:

HTML:

<form action="save_order.php" method="POST" style="display: none;">
<input name="new_order" value="" type="hidden" />
</form>

JavaScript:

$(".selector").sortable({
    stop: function(event, ui) {
        var data = "";

        $("#sortable li").each(function(i, el){
            var p = $(el).text().toLowerCase().replace(" ", "_");
            data += p+"="+$(el).index()+",";
        });

        $("form > [name="new_order"]").val(data.slice(0, -1));
        $("form").submit();
    }
});

Y en save_order.php, puede analizar la variable POST “new_order” y obtener los pedidos del Artículo 1, Artículo 2, Artículo 3, etc.

  • ¿Puede explicar esta respuesta en lugar de simplemente pegar el código?

    – Phil

    21 de septiembre de 2016 a las 9:08

  • @ Phil_1984_ Reescribí esta respuesta. Avísame si te ayuda.

    – mattsven

    26/09/2016 a las 22:08


  • Gracias. Su “Paso 2” es la parte que me interesaba (y creo que el OP también). Inicialmente me pareció extraño que el orden de los elementos recién ordenados no estuviera disponible en ninguno de los eventos activados. los documentos oficiales continúe con las posiciones antiguas y nuevas, pero solo como valores de píxeles superiores e izquierdos inútiles. La biblioteca en sí manipula las posiciones de los elementos dentro del DOM por usted, por lo que hacer un simple selector de jquery en el controlador de eventos le dará el nuevo orden.

    – Phil

    27/09/2016 a las 22:37

  • hola @mattsven, soy nuevo en jquery… ¿puede proporcionar jsfiddel para esto porque tengo dificultades para entenderlo?

    – Divyesh Jesadiya

    25 de agosto de 2017 a las 9:02

  • ¿Con qué partes tienes problemas específicamente?

    – mattsven

    25/08/2017 a las 11:00

Intenta usar serialize para formatear una cadena para enviar a la secuencia de comandos de actualización de su base de datos.

http://jsfiddle.net/zFQ2j/

http://docs.jquery.com/UI/Sortable#method-serialize

Que esto ayude:

alert($( "#sortable" ).sortable( "toArray" ).toSource());

  • Necesitas tener un id atributo en su lis u otro atributo específico como alert($( "#sortable" ).sortable( "toArray", {attribute: 'data-item_number'} ).toSource()); para que esto funcione.

    – Lucas primos

    25 de marzo de 2015 a las 14:07

  • Respuesta relevante a elementos sin ID: stackoverflow.com/a/15382832/4907950

    – Justin

    31 de mayo de 2020 a las 21:06

avatar de usuario
Gediminas

mayo, 2018

Este ejemplo de Javascript le dará toda la lista de DIVS en #sortableContainer cada vez que se realiza la clasificación

<div id="sortableContainer">
   <div id="Element1" class="sortIt">Item 1</div>
   <div id="Element2" class="sortIt">Item 2</div>
   <div id="Element3" class="sortIt">Item 3</div>
   <div id="Element4" class="sortIt">Item 4</div>
</div>

JS:

$( function() {
  $( "#sortableContainer" ).sortable({

    stop: function(event, ui) {

      var itemOrder = $('#sortableContainer').sortable("toArray");

      for (var i = 0; i < itemOrder.length; i++) {
        console.log("Position: " + i + " ID: " + itemOrder[i]);
      }

    }
  });

});

DEMO y Créditos:
http://www.tutorialspark.com/jqueryUI/jQuery_UI_Sortable_Getting_Order_of_Sortable.php

Fácil de resolver:

jQuery_2( function() {
 var url="<?php echo base_url(); ?>planner/Planner/edit_status/";
 jQuery_2('ul[id^="sort"]').sortable({
     connectWith: ".sortable",
     /*receive: function (e, ui) {
         var status_id = jQuery_2(ui.item).parent(".sortable").data("status-id");
         var task_id = jQuery_2(ui.item).data("task-id");
         jQuery_2.ajax({
             url: url,
             method: 'POST',
             data: { status_id: status_id, task_id: task_id, },
             success: function(response){ }
         });
    },*/
    update: function(e, ui) {
        var status_id = jQuery_2(ui.item).parent(".sortable").data("status-id");
        var task_id = jQuery_2(ui.item).data("task-id");
        var order_id = jQuery_2(ui.item).index();
        jQuery_2.ajax({
            url: url,
            method: 'POST',
            data: { status_id: status_id, task_id: task_id, order_id: order_id, },
            success: function(response){ }
        });
    }

 }).disableSelection();
 } );

var order_id = jQuery_2(ui.item).index(); // Obtener orden

avatar de usuario
Gana Ramas

Y tu puedes:

jQuery_2( function() {
 var url="<?php echo base_url(); ?>planner/Planner/edit_status/";
 jQuery_2('ul[id^="sort"]').sortable({
     connectWith: ".sortable",
     /*receive: function (e, ui) {
         var status_id = jQuery_2(ui.item).parent(".sortable").data("status-id");
         var task_id = jQuery_2(ui.item).data("task-id");
         jQuery_2.ajax({
             url: url,
             method: 'POST',
             data: { status_id: status_id, task_id: task_id, },
             success: function(response){ }
         });
    },*/
    update: function(e, ui) {
        var status_id = jQuery_2(ui.item).parent(".sortable").data("status-id");
        var task_id = jQuery_2(ui.item).data("task-id");
        //var order_id = jQuery_2(ui.item).index();
        var order_id = [];

        $("#sort"+status_id+" li").each(function(index) {
            order_id.push($(this).attr('data-task-id'));
        });

        jQuery_2.ajax({
            url: url,
            method: 'POST',
            data: { status_id: status_id, task_id: task_id, order_id: order_id, },
            success: function(response){ }
        });
    }

 }).disableSelection();
 } );

avatar de usuario
usuario1495495

Así es como lo hice Usar el controlador de eventos para capturar el evento de clasificación y luego obtener los valores ordenados a través de la función ToArray y recorrer los valores y asignarlos a la matriz. Esta matriz luego puede pasar a la publicación Ajax

    var $sortableList = $("#sortable");

var sortEventHandler = function(event, ui){
    var sortedIDs = $( "#sortable" ).sortable( "toArray" );
                var listValues = [];
                for (var i = 0; i < sortedIDs.length; i++) {

                listValues.push(sortedIDs[i]);
      }
            console.log(listValues);
};

$sortableList.sortable({
    stop: sortEventHandler
});

$sortableList.on("sortchange", sortEventHandler);

¿Ha sido útil esta solución?