jQuery: Gruppierung Ähnlicher Elemente

Mit jQuery bin ich versucht zu gruppieren ähnlicher Elemente in einer Liste. Hier ist, was ich versuche zu tun. Eine Liste wie die folgende:

<ul>
    <li class="foo">Item #1</li>
    <li class="foo">Item #2</li>
    <li class="foo">Item #3</li>
    <li class="bar">Item #4</li>
    <li class="bar">Item #5</li>
    <li class="foo">Item #6</li>
    <li class="foo">Item #7</li>
    <li class="bar">Item #8</li>
</ul>

Ich möchte am Ende mit den folgenden:

<ul>
    <li class="foo">Item #1 <a>2 More Like This</a>
        <ul>
            <li class="foo">Item #2</li>
            <li class="foo">Item #3</li>
        </ul>
    </li>
    <li class="bar">Item #4</li>
    <li class="bar">Item #5</li>
    <li class="foo">Item #6 <a>1 More Like This</a>
        <ul>
            <li class="foo">Item #7</li>
        </ul>
    </li>
    <li class="bar">Item #8</li>
</ul>

Kurz gesagt, sobald 2 oder mehr Elemente mit class="foo", sollten Sie gruppiert werden, bis das erreichen einer nicht-Klasse="foo" Element. Ich kann dann einen link ein-oder ausblenden werden die gruppierten Elemente.

  • Ausgewählte Antwort
    user113716
    3. Oktober 2010

    Hier ist eine Möglichkeit:

    Beispiel: http://jsbin.com/ipiki3/3/

    $('ul > li.foo')
        .filter(function() {
            var $th = $(this);
            return $th.next('li.foo').length && !$th.prev('li.foo').length;
        })
        .each(function() {
            var $th = $(this);
            var len= $th.append('<a href="#"> more like this</a>')
                        .nextUntil(':not(li.foo)').wrapAll('<ul>').length;
            $th.next('ul').appendTo(this);
            $th.children('a').prepend(len);
        });
    

    EDIT: Fixed ein Fehler mit den len - variable, und fügte hinzu, ein Beispiel.


    Erklärung: Was passiert mit der .filter() ist, dass es zur Verengung der li.foo Elemente nach unten, um die erste in einer Gruppe (mindestens eine li.foo nach, und keiner vor).

    Dann mit der .each() wird der <a>, kriegt die nächsten Elemente bis es erreicht ist, der sich nicht li.foo, umhüllt diese mit einem <ul> und gibt zurück, wie viele es waren, mithilfe des length Eigenschaft.

    Dann durchqueren wir über die neue <ul> und hängen Sie an die erste li.foo in der Gruppe.

    Endlich kommen wir voran, die Menge, die wir gespeichert in length Eigenschaft auf <a> element.

1 Antworten

  • jcubic
    3. Oktober 2010

    Ich komme mit dieser:

    $(document).ready(function() {
        var groups = {}
        $('ul li').each(function() {
            var self = $(this);
            var class_name = self.attr('class');
            if (class_name) {
                if (typeof groups[class_name] == 'undefined') {
                    groups[class_name] = [];
                }
                groups[class_name].push(self);
            }
        });
        var ul = $('ul');
        ul.empty();
        for (var class_name in groups) {
            var array = groups[class_name];
            ul.append('<li class="' + class_name + '">' + $(array[0]).html() + 
                '<a>More Like this</a><ul></ul>');
            $(array.splice(1)).each(function() {
                ul.find('li.' + class_name + ' ul').append(this);
            });
        }
    });