2010-09-10 17 views
8

No tengo ningún problema para obtener una lista de elementos y ordenarlos alfabéticamente, pero tengo dificultades para entender cómo hacerlo con un módulo.Ordenando una lista alfabéticamente con un módulo

### ### ACTUALIZACIÓN

Aquí está el código de trabajo 'a mi manera', sin embargo, me gusta la reutilización de la respuesta proporcionada a continuación más, así que he aceptado esa respuesta.

<script type="text/javascript"> 
$(document).ready(function() { 
    $('.sectionList2').each(function() { 
     var oldList = $('li a', this), 
      columns = 4, 
      newList = []; 
     for(var start = 0; start < columns; start++){ 
      for(var i = start; i < oldList.length; i += columns){ 
       newList.push('<li><a href="' + oldList[i].href + '">' + $(oldList[i]).text() + '</a></li>'); 
      } 
     } 
     $(this).html(newList.join('')); 
    }); 
}); 
</script> 

Por ejemplo. Supongamos que tengo la siguiente lista desordenada:

<ul> 
    <li><a href="~">Boots</a></li> 
    <li><a href="~">Eyewear</a></li> 
    <li><a href="~">Gloves</a></li> 
    <li><a href="~">Heated Gear</a></li> 
    <li><a href="~">Helmet Accessories</a></li> 
    <li><a href="~">Helmets</a></li> 
    <li><a href="~">Jackets</a></li> 
    <li><a href="~">Mechanic's Wear</a></li> 
    <li><a href="~">Pants</a></li> 
    <li><a href="~">Protection</a></li> 
    <li><a href="~">Rainwear</a></li> 
    <li><a href="~">Random Apparel</a></li> 
    <li><a href="~">Riding Suits</a></li> 
    <li><a href="~">Riding Underwear</a></li> 
    <li><a href="~">Socks</a></li> 
    <li><a href="~">Vests</a></li> 
</ul> 

Tengo esta lista configurada para mostrar en 4 columnas con cada li flotada a la derecha. Visualmente esto hace que sea difícil encontrar elementos en listas más grandes. La salida que necesito es la siguiente:

<ul> 
    <li><a href="~">Boots</a></li> 
    <li><a href="~">Helmet Accessories</a></li> 
    <li><a href="~">Pants</a></li> 
    <li><a href="~">Riding Suits</a></li> 
    <li><a href="~">Eyewear</a></li> 
    <li><a href="~">Helmets</a></li> 
    <li><a href="~">Protection</a></li> 
    <li><a href="~">Riding Underwear</a></li> 
    <li><a href="~">Gloves</a></li> 
    <li><a href="~">Jackets</a></li> 
    <li><a href="~">Rainwear</a></li> 
    <li><a href="~">Socks</a></li> 
    <li><a href="~">Heated Gear</a></li> 
    <li><a href="~">Mechanic's Wear</a></li> 
    <li><a href="~">Random Apparel</a></li> 
    <li><a href="~">Vests</a></li> 
</ul> 

Lo que estoy buscando es una función que me puede pasar a mi gama de elementos de la lista y obtener mi matriz devuelta, ordenadas alfabéticamente, con un módulo de elección; en este caso 4.

Cualquier ayuda sería apreciada ya que no puedo encontrar documentación sobre el tema.

+0

Podría publicar el código que ya tiene? –

+0

Y, asumiendo que está desarrollando esto desde un servidor, ¿por qué no lo hace en el servidor? – Chubas

+1

En realidad, hay una solución CSS para esto, con 'column-count' –

Respuesta

2
  1. Alfabetiza tu lista. Esto ya se hace, en su caso, pero si no:

    function alphabetizeElements(a, b) 
    { 
        var aText = $(a).text(); 
        var bText = $(b).text(); 
        return aText > bText ? 1 : aText < bText ? -1 : 0; 
    } 
    var alphabetizedList = $("#myList li").sort(alphabetizeElements); 
    
  2. almacenar el índice alfabético de cada elemento:

    $.each(alphabetizedList, function(i) 
    { 
        $(this).data("alphaIndex", i); 
    }); 
    
  3. Ordenar la lista ordenada alfabéticamente por el módulo primero, luego el índice:

    function listColumnSortFn(columns) 
    { 
        return function(a, b) 
        { 
         var aIndex = $(a).data("alphaIndex"); 
         var bIndex = $(b).data("alphaIndex"); 
         return ((aIndex % columns) - (bIndex % columns)) || (aIndex - bIndex); 
        } 
    } 
    var columnSortedList = alphabetizedList.sort(listColumnSortFn(4)); 
    
  4. Reemplazar los elementos de la lista con los elementos ordenados:

    $("#myList li").remove(); 
    $("#myList").append(columnSortedList); 
    

Aquí está toda la cosa, todos juntos:

function sortList(columns) 
{ 
    var alphabetizedList = $("#myList li").sort(alphabetizeElements); 
    $.each(alphabetizedList, function(i) 
    { 
     $(this).data("alphaIndex", i); 
    }); 
    var columnSortedList = alphabetizedList.sort(listColumnSortFn(columns)); 
    $("#myList li").remove(); 
    $("#myList").append(columnSortedList); 
} 
function alphabetizeElements(a, b) 
{ 
    var aText = $(a).text(); 
    var bText = $(b).text(); 
    return aText > bText ? 1 : aText < bText ? -1 : 0; 
} 
function listColumnSortFn(columns) 
{ 
    return function(a, b) 
    { 
     var aIndex = $(a).data("alphaIndex"); 
     var bIndex = $(b).data("alphaIndex"); 
     return ((aIndex % columns) - (bIndex % columns)) || (aIndex - bIndex); 
    } 
} 
$(function() 
{ 
    sortList(4); 
}); 
0
var columnify = function (a,n) { 
    var result = []; 
    for (var i = 0, lastIndex = a.length - 1; i < lastIndex; i++) 
     result.push(a[i * n % (lastIndex)]); 
    result[lastIndex] = a[lastIndex]; 
    return result; 
} 

var products = ["Boots", 
"Eyewear", 
"Gloves", 
"Heated Gear", 
"Helmet Accessories", 
"Helmets", 
"Jackets", 
"Mechanic's Wear", 
"Pants", 
"Protection", 
"Rainwear", 
"Random Apparel", 
"Riding Suits", 
"Riding Underwear", 
"Socks", 
"Vests",] 

columnify(products, 4) 
["Boots", "Helmet Accessories", "Pants", "Riding Suits", "Eyewear", "Helmets", "Protection", "Riding Underwear", "Gloves", "Jackets", "Rainwear", "Socks", "Heated Gear", "Mechanic's Wear", "Random Apparel", "Vests"] 

Aplicar esa función a la lista ya ordenados, y luego se volverá una lista de cadenas en el orden (casi) que desee. A continuación, agregue la lista que se devolvió para la lista desordenada en el DOM.

Además, no lo he probado con nada más que esa lista. Así que haría eso si fuera tú. Por lo que veo, solo funciona si la longitud de la lista es un múltiplo de n. No es una gran solución, pero es tarde para mí y no puedo molestarme en encontrar algo mejor.

EDIT: solucionado el problema con el último elemento

+0

la teoría es bastante buena pero la implementación no es correcta. Pasar en una matriz de 17 elementos con n = 4 produce 0 4 8 12 cuatro veces con una final de 16 en la quinta fila. – ErikE

+0

@Emtucidifor: Sí. Como dije, no funciona cuando n% lenght! = 0. –

0

A ver si esto va a funcionar: http://jsfiddle.net/6xm9m/2

var newList = new Array(); 
var listItem = $('#list > li'); 
var mod = 4; 
var colCount = Math.ceil(listItem.length/mod); 

listItem.each(function(index) { 
    var newIndex = ((index % colCount) * mod) + Math.floor(index/colCount); 
    // $(this).text(newIndex); 

    newList[newIndex] = this; 
}); 

$('#list').empty(); 

for(var i = 0; i < newList.length; i++){ 
    $('#list').append(newList[i]); 
} 

necesita mejoras, probablemente, pero no estoy muy seguro de lo bien que esto funciona en absoluto.

0

Aquí tienes. El código es sorprendentemente simple una vez que lo resuelves. Me doy cuenta de que estás usando jQuery pero no estoy lo suficientemente familiarizado con él para usar sus funciones. Esto es lo suficientemente simple como para que tal vez no sea necesario.

function pivotArray(arr, columns) { 
    var l = arr.length, out = [], ind = 0, i = 0; 
    for (; i < l; i += 1) { 
     out[ind] = arr[i]; 
     ind += columns; 
     if (ind >= l) { 
     ind = ind % columns + 1; 
     } 
    } 
    return out; 
} 

y aquí está la prueba para demostrar que funciona (probado en Firefox 3.6.9, IE 6, Chrome 1.0.154.36):

<html> 
<head> 
<style type="text/css"> 
a.panelnum { 
    display:block; 
    float:left; 
    width:40px; 
    height:40px; 
    border:1px solid black; 
    text-align:center; 
    vertical-align:middle; 
    text-decoration:none; 
    font-size:2em; 
} 
</style> 
</head> 
<body onload="doit(17, 4);"> 
<div id="output" style="border:1px solid blue;"> 
</div> 
<script type="text/javascript"> 

function pivotArray(arr, columns) { 
    var l = arr.length, out = [], ind = 0, i = 0; 
    for (; i < l; i += 1) { 
     out[ind] = arr[i]; 
     ind += columns; 
     if (ind >= l) { 
     ind = ind % columns + 1; 
     } 
    } 
    return out; 
} 

function doit(size, columns) { 
    document.getElementById('output').innerHTML = 'starting'; 
    var l = size; 
    var inp = []; 
    for (var i = 0; i < l; i += 1) { 
     inp[i] = i; 
    } 
    var result = pivotArray(inp, columns); 
    var str = ''; 
    for (i = 0; i < l; i += 1) { 
     str += '<a class="panelnum">' + result[i] + '</a>'; 
    } 
    var d = document.getElementById('output') 
    d.innerHTML = '<p>Some pre text</p>' + str + '<p style="clear:both;">and some post text</p>'; 
    d.style.width = (columns * d.childNodes[1].offsetWidth + 2) + 'px'; 
} 
</script> 
</body> 
</html> 

Una cosa más: Podría ser útil sólo hay que mover los elementos alrededor en el lugar. Casi tenía un guión, pero mi guión estaba corriendo hacia atrás (como si las carrozas fueran de arriba hacia abajo primero). Si tengo tiempo, trabajaré en él y publicaré el código.

P.S. ¿Alguien quiere darme consejos sobre por qué tuve que agregar 2 al cálculo de ancho para IE6? Espera ... son las fronteras del div ¿no?

Cuestiones relacionadas