0

Problem:

  1. Whenever user clicks on column's header in table, a classname .active from all the same table tr th span.sorting shoud have been removed.
  2. Add a classname .active to the child of currently clicked target element.

Structure:

<table>
    <tr>
        <th>
            <span class="sorting"></span>
        </th>
        <th>
            <span class="sorting"></span>
        </th>
        <th>
            <span class="sorting active"></span>
        </th>
    </tr>
</table>

Solution (already done):

  1. don't know
  2. To add a class to a child of clicked column: trigger.target.children[0].classList.add('active')

What is the best way to remove all active classes from <span class="sorting"> whenever I click on the <th> element and assign an active class to currently clicked block?

No jQuery, please.

aspirinemaga
  • 3,753
  • 10
  • 52
  • 95

6 Answers6

3

You can use querySelectorAll to fetch elements and Array.from to transform the output to array.

Array.from( document.querySelectorAll( "th .sorting" ) );

Now iterate them and remove the class using classList APIs

Array.from( document.querySelectorAll( "th .sorting" ) ).forEach( function( ele ){
  ele.classList.remove( "active" );
});

finally to the current element you can add the class to currentTarget of the event

event.currentTarget.classList.add( "active" );

Demo

var elements = Array.from( document.querySelectorAll( "th .sorting" ));

elements.forEach( function(ele){
   ele.addEventListener( "click", function(){
      elements.forEach( function( ele ){
         ele.classList.remove( "active" );
      });
      ele.classList.add( "active" );
   });
});
.active
{
  background-color: #f00;
}
<table>
  <tr>
    <th>
      <span class="sorting">A</span>
    </th>
    <th>
      <span class="sorting">B</span>
    </th>
    <th>
      <span class="sorting active">C</span>
    </th>
  </tr>
</table>
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
  • One question - why you didn't used DOM HTMLCollection, but querySelector instead ? Thank you for your anwer. – aspirinemaga Dec 27 '17 at 11:35
  • 1
    `querySelectorAll` https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll returns NodeList only.. Check this to see the difference between NodeList and HTMLCollection https://stackoverflow.com/questions/15763358/difference-between-htmlcollection-nodelists-and-arrays-of-objects – gurvinder372 Dec 27 '17 at 11:37
1

Remove all the class active on click of a .sorting element, then add on the currentTarget

let elements = Array.from(document.getElementsByClassName('sorting'));
elements.forEach(e => {
  e.addEventListener('click', s => {
    elements.forEach(el => el.classList.remove('active'));
    s.currentTarget.classList.add('active');
  });
})
<table>
  <tr>
    <th>
      <span class="sorting"></span>
    </th>
    <th>
      <span class="sorting"></span>
    </th>
    <th>
      <span class="sorting active"></span>
    </th>
  </tr>
</table>
baao
  • 71,625
  • 17
  • 143
  • 203
1

var allTh = document.querySelectorAll("#tbl thead tr th");
for(var i = 0; i < allTh.length; i++){
  allTh[i].addEventListener("click",function(e){
      removeAllActiveClasses();
      e.target.classList.add("active");
  });
}

function removeAllActiveClasses(){
  var allActiveClassElement = document.querySelectorAll(".active");
  for(var i = 0; i < allActiveClassElement.length; i++){
    allActiveClassElement[i].classList.remove("active");
  }
}
.active{
  color : blue;
}
<table id="tbl">
    <thead>
      <tr>
          <th>
              <span class="sorting">Col 1</span>
              
          </th>
          <th>
              <span class="sorting">Col 2</span>
              
          </th>
          <th>
              <span class="sorting active">Col 3</span>
          </th>
      </tr>
    </thead>
</table>
Lalit
  • 1,354
  • 1
  • 8
  • 13
1
document.querySelectorAll(".active.sorting").forEach(e=>e.classList.remove("active"))
event.currentTarget.classList.add(".active")

we have forEach function on value returned from querySelector, so we can iterate over that domArray, then the second code line is to be placed in context on event listener

Akshay Vijay Jain
  • 13,461
  • 8
  • 60
  • 73
  • 1
    While this code snippet may be the solution, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion – Rahul Gupta Dec 27 '17 at 10:21
1

Working directly on HTMLCollection should also be a possible way to go:

var elements = document.getElementsByClassName('sorting');
for(i=0;i<elements.length;i++) {
    elements[i].className -= ' active';
}
Julius Dzidzevičius
  • 10,775
  • 11
  • 36
  • 81
0

You can try the below code

var elems = Array.from(document.getElementsByClassName("sorting"));
//console.log(elems)
elems.forEach(e => e.addEventListener('click', function(event) {
  elems.forEach(e => e.classList.remove("active"))
  event.currentTarget.classList.add("active");
}));
body {
  font: 13px verdana
}

span.active {
  color: red;
}

span {
  display: block;
  margin: 0 10px;
  cursor: pointer
}
<table>
  <tr>
    <th>
      <span class="sorting">One</span>
    </th>
    <th>
      <span class="sorting">Two</span>
    </th>
    <th>
      <span class="sorting active">Three</span>
    </th>
  </tr>
</table>
Bhuwan
  • 16,525
  • 5
  • 34
  • 57
  • why is there an `addEventListener` ? It works without it, but why you have included it ? does it have some specific purpose ? – aspirinemaga Dec 27 '17 at 11:32
  • You are trying to change the class on `click` event, so you have to add a EventListener for click @aspirinemaga – Bhuwan Dec 27 '17 at 13:06