Change the parental class of the parent

advertisements

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?


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