2009-10-29 35 views
11

Tengo una lista larga de UL que necesito dividir en listas más pequeñas que contienen aproximadamente 20 elementos cada una.jQuery dividir lista larga de ul en listas más pequeñas

Estaba pensando que podría utilizar algo así como

$(function() { 
    $("ul li:nth-child(20n)").after("</ul><ul>"); 
}); 

pero ese no es el caso. ¿Alguna idea de cómo usar jQuery de una manera que use CPU mínima?

+1

Hay una biblioteca que hace eso - https://github.com/yairEO/listBreaker – vsync

Respuesta

19

Crearía fragmentos de documentos con su lis eliminado y luego los volveré a agregar a la ubicación que desee. En este caso, les reappended al cuerpo:

$(function(){ 
    var $bigList = $('#bigList'), group; 
    while((group = $bigList.find('li:lt(20)').remove()).length){ 
    $('<ul/>').append(group).appendTo('body'); 
    } 
}); 

demostración en vivo se encuentra en: http://jsbin.com/ejigu/33

+2

Sólo por carrera he intentado hacer esto con expresiones regulares en cambio: http://jsbin.com/acupof/2/edit#javascript,live ... No puedo decir que sea más elegante. :) –

+1

Por pura velocidad, la solución de expresiones regulares podría ser mejor. Si cambió mi respuesta para usar 'detach' en lugar de' remove', mantendría los eventos que se hayan adjuntado a los elementos o subelementos. Eso sería útil en algunas situaciones. Aunque con largas listas, probablemente deberías delegar de todos modos. <3z –

+0

¿Quién es un mal asno? Paul Irish, eso es quién :) ... ¡muy bien hecho! – Oneezy

7

Nada tan simple (que yo sepa, al menos) desafortunadamente. Tratar esto como una alternativa:

$(function() { 
    $("ul").each(function() { 
    var list = $(this); 
    var size = 3; 
    var current_size = 0; 
    list.children().each(function() { 
    console.log(current_size + ": " + $(this).text()); 
     if (++current_size > size) { 
     var new_list = $("<ul></ul>").insertAfter(list); 
     list = new_list; 
     current_size = 1; 
     } 
     list.append(this); 
    }); 
    }); 
}); 

Se podría, sin duda, convertir esto en una función que toma el tamaño del fragmento como un argumento, pero lo dejo como ejercicio para el lector.

3

Aquí está un ejemplo de trabajo, basta con cambiar el mod 5 a mod 20.

<html> 
<script type="text/javascript" src="jquery-1.3.2.js"></script> 

<script type="text/javascript"> 

function onLoad(){ 
    var itemindex = 0; 
    var Jlistobj = null; 
    $('#list li').each(function() 
    { 
     if (itemindex % 5 == 0) 
     { 
     Jlistobj = $("<ul></ul>"); 
     } 
     Jlistobj.append($(this)); 
     $('#out_div').append(Jlistobj); 
     itemindex++; 
    }); 
} 

</script> 
<body onLoad="onLoad()"> 

<ul id="list"> 
<li>item1</li> 
<li>item2</li> 
<li>item3</li> 
<li>item4</li> 
<li>item5</li> 
<li>item6</li> 
<li>item7</li> 
<li>item8</li> 
<li>item9</li> 
<li>item10</li> 
<li>item11</li> 
<li>item12</li> 
<li>item13</li> 
<li>item14</li> 
<li>item15</li> 
<li>item16</li> 
<li>item17</li> 
<li>item18</li> 
<li>item19</li> 
<li>item20</li> 
</ul> 

<div id="out_div"></div> 

</body> 

</html> 
0

Aquí es otra opción - No he perfilado ninguno de los anteriores, así que ve con lo que sea más rápido, por supuesto. Supone que el ul en cuestión tiene el id de #list.

 var listItemsPerList = 10; 
    var listItems = $("ul > li").length; 

    for (var i = 0; i < Math.round(listItems/listItemsPerList); i++) { 
     var startingItem = i * listItemsPerList; 
     var endingItem = (i + 1) * listItemsPerList; 
     if (endingItem > listItems) { endingItem = listItems }; 
     $("ul > li").slice(startingItem, endingItem).wrapAll("<ul></ul>"); 
    } 

    $("ul#list").replaceWith($("ul#list").children()); 
0

puede intentar algo como esto:

$("ul").each(function(k,v)){ 
    split_list(v); 
} 

function split_list(list){ 
    var li_num = $(list).find("li").length; 
    if(li_num > 20){ 
     var new_list = $("<ul></ul>"); 
     $(list).after(new_list); 
     new_list.append($(list).find("li:gt(20)")); 
     if(new_list.find("li").length > 20){ 
      split_list(new_list); 
     } 
    } 
} 

LE: Creo que se puede refinar aún más mediante la búsqueda por adelantado cuántos nueva lista será createt, crear esas listas y mover bloques de ~ 20 li en las nuevas listas creadas por lo que se moverán solo una vez.

2

función:

$.fn.splitUp=function(splitBy,wrapper) { 
    $all= $(this).find('>*'); 
    var fragment=Math.ceil($all.length/splitBy); 
    for(i=0; i< fragment; i++) 
     $all.slice(splitBy*i,splitBy*(i+1)).wrapAll(wrapper); 
    return $(this); 
} 

uso:

$('ul#slides').splitUp(4,'&lt;li class=splitUp&gt;&lt;ul&gt;') 

o:

$('div#slides').splitUp(3,'&lt;div/&gt;') 
+0

Si lo haces recursivo, es incluso más corto –

1

éste divide el menú para piezas de aproximadamente la misma longitud función Splitmenu (menu_id, piezas) {

 var $menu = $(menu_id), group; 
     var splitItem = 0, totItemLen = 0, cumlen = 0; 

     $($menu).find('li').each(function(){ totItemLen = totItemLen + $(this).width(); }); 

     $($menu).find('li').each(function(i){ 
      cumlen = cumlen + $(this).width(); 
      if (totItemLen/pieces < cumlen && splitItem == 0) splitItem = i; 
     }); 

     while((group = $($menu).find('li:lt(' + splitItem + ')').remove()).length){ 
       $('<ul/>').attr('class',$($menu).attr('class')).append(group).appendTo($($menu).parent()); 
      } 

     $($menu).remove(); 
    } 
    splitMenu('#menu-footermenu', 2); 
1

Sólo otra versión como un plugin de jQuery:

jQuery.fn.splitList = function(num) { 
    var sublist; 
    while((sublist = this.find('li:gt('+(num-1)+')').remove()).length){ 
    this.after($('<ul/>').append(sublist)); 
    } 
}; 
0

Aquí está una extensión del prototipo jQuery ($ .fn) objeto proporcionar un nuevo método que puede ser encadenado a la función jQuery().

Necesitaba funcionalidad donde necesitaba agregar un elemento entre la lista que dividía. Eso se ha agregado como un parámetro opcional.

Un ejemplo está disponible en http://jsfiddle.net/roeburg/5F2hW/

El uso de la función es de esta manera:

$("ul").customSplitList(5); 

La función se define de la siguiente manera:

// Function definition 
(function ($) { 
    // Function is defined here ... 
    $.fn.customSplitList = function (indexToSplit, elementToAddInBetween) { 
     // Holds a reference to the element(list) 
     var that = this; 
     var subList, newList, listLength; 

     // Only continue if the element is a derivitive of a list 
     if ($(that) && ($(that).is("ul") || $(that).is("ol"))) { 

      // Additionally check if the length & the split index is valid 
      listLength = $(that).children().length; 

      if ($.isNumeric(indexToSplit) && indexToSplit > 0 && indexToSplit < listLength) { 
       // Based on list type, create a new empty list 
       newList = $($(that).clone(true)).empty(); 

       while ((subList = this.find('li:gt(' + (indexToSplit - 1) + ')').remove()).length) { 
        newList.append(subList); 
       } 

       if (elementToAddInBetween && $(elementToAddInBetween)) { 
        that.after(newList); 
        newList.before(elementToAddInBetween); 
       } else { 
        that.after(newList); 
       } 
      } 
     } 
    }; 

})(jQuery); 

Espero que esto ayude.

0

Algo como esto:

var lis = $("ul > li"); 
for(var i = 0; i < lis.length; i+=20) { 
    lis.slice(i, i+20).wrapAll("<ul></li>"); 
} 
$("ul > ul").unwrap(); 

Working Demo

Cuestiones relacionadas