nhereveri
nhereveri

Reputation: 143

Change sibling class of parent

I have this code in HTML, and need to add styles to some ancestor siblings with CSS (may not be able). Therefore I use Javascript to add classes to the ancestors.

I read that you can not create a parent selector with CSS.

FROM THIS:


    <ul class="monitor">
      <li><span>Servidor 1</span>
        <ul>
          <li><span>Hardware</span>
            <ul>
              <li>CPU</li>
              <li>Memoria</li>
              <li>Disco</li>
            </ul>
          </li>
          <li><span>Airviro</span>
            <ul>
              <li class="warning">AVDBM</li>
              <li>COLDB</li>
            </ul>
          </li>
        </ul>
      </li>
      <li><span>Servidor 2</span>
        <ul>
          <li><span>Hardware</span>
            <ul>
              <li class="error">CPU</li>
              <li class="warning">Memoria</li>
              <li>Disco</li>
            </ul>
          </li>
          <li><span>Airviro</span>
            <ul>
              <li>AVDBM</li>
              <li>COLDB</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>

TO THIS:


    <ul class="monitor">
      <li><span class="warning">Servidor 1</span>
        <ul>
          <li><span>Hardware</span>
            <ul>
              <li>CPU</li>
              <li>Memoria</li>
              <li>Disco</li>
            </ul>
          </li>
          <li><span class="warning">Airviro</span>
            <ul>
              <li class="warning">AVDBM</li>
              <li>COLDB</li>
            </ul>
          </li>
        </ul>
      </li>
      <li><span class="error">Servidor 2</span>
        <ul>
          <li><span class="error">Hardware</span>
            <ul>
              <li class="error">CPU</li>
              <li class="warning">Memoria</li>
              <li>Disco</li>
            </ul>
          </li>
          <li><span>Airviro</span>
            <ul>
              <li>AVDBM</li>
              <li>COLDB</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>

Any elegant solution?

Upvotes: 1

Views: 431

Answers (2)

Carlo Moretti
Carlo Moretti

Reputation: 2250

First of all some consideration :

1.

add classes to some ancestor siblings with CSS

this doesn't mean anything, you don't add classes with CSS, you style them.

2.

I understand you wish to make a tree where, if a child element has the class .waring or .error then you want its parents to get the same class as well. This probably so you can make the text yellow/red for each tree step. So your problem is not just how to address al the parents and add them a class, but also how to style them properly

Here's what I came out with

YOUR ORIGINAL HTML

<ul class="monitor">
  <li><span>Servidor 1</span>
    <ul>
      <li><span>Hardware</span>
        <ul>
          <li>CPU</li>
          <li>Memoria</li>
          <li>Disco</li>
        </ul>
      </li>
      <li><span>Airviro</span>
        <ul>
          <li class="warning">AVDBM</li>
          <li>COLDB</li>
        </ul>
      </li>
    </ul>
  </li>
  <li><span>Servidor 2</span>
    <ul>
      <li><span>Hardware</span>
        <ul>
          <li class="error">CPU</li>
          <li class="warning">Memoria</li>
          <li>Disco</li>
        </ul>
      </li>
      <li><span>Airviro</span>
        <ul>
          <li>AVDBM</li>
          <li>COLDB</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

HERE SOME EXTRA CSS

.monitor{
    color:#00aa00;
}
.warning{
    color:#ffaa00;
}
.error{
    color:#ff0000;
}
// Notice the rule under here makes everything not warning or error green.
// Try the fiddle without this and you'll see why it's needed
li:not(.warning):not(.error){
    color:#00aa00;
}

FINALLY SOME JQUERY

// Select all items with warning class
$('.warning').each(function(){
    // for each item select all its parents which are li|ul
    $(this).parents('li, ul').each(function(){
        // for each parent clear all its classes
        $(this).removeClass()
        // then add the warning class
        $(this).addClass('warning')

    })
})
// same for erro AFTER WARNING as it is more relevant
// and should override the warning color
$('.error').each(function(){

    $(this).parents('li, ul').each(function(){

        $(this).removeClass()
        $(this).addClass('error')

    })
})

Hope this helps. HERE IS A WORKING FIDDLE

EDIT

Fallowing @Jeremy's comment the jQuery could become

// Select all items with warning class
$('.warning').each(function(){
    // for each item select all its parents which are li|ul
    $(this).parentsUntil('.monitor', 'li, ul').each(function(){
        // for each parent clear all its classes
        $(this).removeClass()
        // then add the warning class
        $(this).addClass('warning')

    })
})
// same for erro AFTER WARNING as it is more relevant
// and should override the warning color
$('.error').each(function(){

    $(this).parentsUntil('.monitor', 'li, ul').each(function(){

        $(this).removeClass()
        $(this).addClass('error')

    })
})

Notes :

  • picked 'li, ul' instead of 'span'
  • .parentsUntil('.monitor', 'li, ul'), the first element tells when to stop, the second element tells which items select.

HERE THE UPDATED FIDDLE

Upvotes: 2

Jeremy Goodell
Jeremy Goodell

Reputation: 18942

Something like this might work for you:

$(this).parentsUntil('span', '.monitor').addClass('warning');

This would find all the ancestors of type "span" up until the nearest element with the "monitor" class, and add the "warning" class to each.

It's hard to be certain that this will work for you without a little more information about the problem you're trying to solve though.

Upvotes: 1

Related Questions