web-dev-qa-db-fra.com

Sélecteur CSS pour cibler uniquement les enfants immédiats et non d'autres descendants identiques

J'ai une liste triable imbriquée qui peut avoir des éléments ajoutés ou supprimés dynamiquement et peut être imbriquée à n niveaux. Lors de l'imbrication, un nouvel élément ul est injecté dans l'élément li sélectionné pour être le parent. L'état initial de la liste ressemble à ceci:

<ul id="parent">
    <li id="One"><a href="" class="listLink"><span class="position">1</span>One</a></li>
    <li id="Two"><a href="" class="listLink"><span class="position">2</span>Two</a></li>
    <li id="Three"><a href="" class="listLink"><span class="position">3</span>Three</a>
        <ul>
            <li id="A"><a href="" class="listLink"><span class="position">1</span>A</a></li>
            <li id="B"><a href="" class="listLink"><span class="position">2</span>B</a></li>
            <li id="C"><a href="" class="listLink"><span class="position">3</span>C</a></li>
            <li id="D"><a href="" class="listLink"><span class="position">4</span>D</a></li>
            <li id="E"><a href="" class="listLink"><span class="position">5</span>E</a></li>
            <li id="F"><a href="" class="listLink"><span class="position">6</span>F</a></li>                    
        </ul>
    </li>   
    <li id="Four"><a href="" class="listLink"><span class="position">4</span>Four</a></li>
    <li id="Five"><a href="" class="listLink"><span class="position">5</span>Five</a></li>
    <li id="Six"><a href="" class="listLink"><span class="position">6</span>Six</a></li>                    
</ul>

J'utilise MooTools pour faire le tri, etc., et cela fonctionne bien, mais j'ai du mal à réinitialiser correctement le texte de position lors du tri. Chaque sélecteur CSS que j'essaie d'utiliser comprend également tous des enfants plutôt que simplement les éléments li qui appartiennent à la liste et non ceux appartenant aux sous-listes. Supposons qu'à l'exception de id, position et text, chaque élément li dans toutes les listes est identique à tous les autres. Existe-t-il un sélecteur pour obtenir uniquement les enfants immédiats? Y a-t-il une autre façon de procéder?

J'ai essayé des sélecteurs d'enfants comme ceux mentionnés:

  • ul > li Sélectionne tous les éléments li qui sont un enfant d'un ul, pas seulement les enfants immédiats
  • #parent > li Fait la même chose que ci-dessus.

Voici la fonction que j'exécute actuellement lorsqu'un élément est déposé, qui ne gère pas le tri, qui fonctionne bien, juste la mise à jour de la position. Notez qu'il s'agit également de la syntaxe MooTools:

var drop = function(el){
    el.getParents('ul').reverse().each(function(item){
        var posCount = 1;
        item.getElements('li a span[class=position]').each(function(pos){
            pos.set('text', posCount);
            posCount++;
        });
    });
}

Actuellement, la modification de l'ordre des articles au niveau principal renumérote tout 1-12, même les sous-listes. La modification de n'importe quel élément d'une sous-liste donnera les numéros corrects pour cette liste, mais provoquera le comptage incorrect de tous les éléments li dans la numérotation par les listes parent.

J'ai l'impression que c'est un vilain hack, mais ça marche:

var drop = function(){
    var ulCount = 1;
    $$('ul').each(function(item){
        if(item.get('id') != 'parent') { 
            item.set('id', 'id-'+ulCount);
        }
        var elId = item.get('id');
        var posCount = 1;
        $(document).getElements('#'+elId+'>li>a>span[class=position]').each(function(pos){
            pos.set('text', posCount);
            posCount++;
        });
        ulCount++;
    });
}
61
VirtuosiMedia
ul > li

ne fait que les enfants immédiats. Ainsi, par exemple, pour ne faire que les éléments de liste de niveau supérieur que vous pourriez utiliser:

#parent > li

Remarque: cela n'est pas pris en charge sur IE6.

La solution de contournement courante pour la compatibilité descendante est de faire quelque chose comme ceci:

#parent li { /* style appropriately */ }
#parent li li { /* back to normal */ }

C'est plus fastidieux car vous devez appliquer des styles, puis les désactiver (et vous ne savez pas nécessairement quelles sont les anciennes valeurs), mais c'est la seule solution de contournement CSS pur compatible avec IE6.

Edit: Ok vous avez un problème spécifique à MooTools. GetElements () renvoie tous les descendants, pas seulement les enfants immédiats. Essayez en utilisant getChildren () .

var drop = function(el){
    el.getParents('ul').reverse().each(function(item){
        var posCount = 1;
        item.getChildren("li").getElements("a span[class=position]").each(function(pos){
                pos.set('text', posCount);
                posCount++;
        });
    });
}

ou quelque chose comme ça.

94
cletus

La question d'origine n'a pas reçu de réponse. : l'enfant unique ne fonctionne que si l'enfant unique n'a pas d'enfants descendants. Le post original suggérait que l'inclusion des enfants descendants était due à ul> li alors qu'elle est en fait due à un bug dans: only-child. Paradoxalement: le premier enfant sélectionne le premier enfant d'une liste avec les enfants descendants, comme le fait le dernier enfant, mais: seul l'enfant ne le fait pas. J'ai vérifié cela dans Firefox, Opera et Chrome. Voici un exemple:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8">
<style>
.list>ul>li:only-child {color:red}
.list>ul>li:first-child {color:green}
.list>ul>li:last-child {color:blue}
</style>
</head>
<body>
<div class="list">
<ul><li>Item one</li><ul>
<l>Subitem one</li>
<li>Subitem two</li></ul></li><!--<li>Item two</li>
<li>Item three</li>-->
</ul></div>
</body></html>

Pour activer: les règles premier enfant et: dernier enfant décommentent les deux derniers éléments. L'implémentation de la norme Selectors Level est donc incohérente dans les principaux navigateurs. La règle: premier enfant ne doit pas être activée lorsqu'il existe une règle: seul enfant et qu'un enfant unique a des descendants. Dans l'exemple, l'enfant unique doit être rouge mais vert.

0
user3483642