Colin Lightfoot
Colin Lightfoot

Reputation: 549

Sort Checkboxes by Label

So I have these checkboxes with crazy IDs because reasons that I can't change. For example:

<td>
    <span title=BBB class="ms-RadioText">
        <input id = Checkbox1 type=checkbox/>
        <label for="Checkbox1">BBB</label>
    </span>
    <span title=AAA class="ms-RadioText">
        <input id = Checkbox2 type=checkbox/>
        <label for="Checkbox2">AAA</label>
    </span>
</td>

And, of course, they appear non-alphabetically. How do I sort this alphabetically using native JavaScript, JQuery, or CSS, as I am not allowed to alter the order of the checkboxes in HTML?

Upvotes: 0

Views: 240

Answers (3)

Tom O.
Tom O.

Reputation: 5941

You could take advantage of the DOM API to grab the span elements from the parent, re-order them, and append a document fragment back to the original parent element. Something like below:

const orderEls = () => {
  //Get an array of the elements we want to sort
  const spanEls = Array.from(document.querySelectorAll('span'));

  //Generate a doc fragment containing the ordered els
  const frag = spanEls
    .sort((a, b) => a.title > b.title ? 1 : -1)
    .reduce((accum, spanEl) => {
      accum.appendChild(spanEl);
      return accum;
    }, document.createDocumentFragment());

  //Append the ordered els to the parent
  document.querySelector('td').appendChild(frag)
};

orderEls();
<table>
  <tr>
    <td>
      <span title="BBB" class="ms-RadioText">
        <input id="Checkbox1" type="checkbox" />
        <label for="Checkbox1">BBB</label>
    </span>
      <span title="AAA" class="ms-RadioText">
        <input id="Checkbox2" type="checkbox"/>
        <label for="Checkbox2">AAA</label>
    </span>
    </td>
  </tr>
</table>

Upvotes: 1

mshockman
mshockman

Reputation: 123

With vanilla JavaScript you can sort your checkboxes with the following function.

function sortCheckboxesByLabel(parentElement) {
    var children = Array.prototype.slice.call(parentElement.children), // Convert to true array.
        fragment = document.createDocumentFragment();

    // Sort alphabetically.
    children.sort((item1, item2) => item1.querySelector('label').innerText > item2.querySelector('label').innerText ? 1 : -1);

    // Add to fragment.
    for(var i = 0; i < children.length; i++) {
        fragment.appendChild(children[i]);
    }

    // Append back to document.
    parentElement.appendChild(fragment);
}

It takes their parent element as it’s only parameter. It converts the parent elements children to an array and then sorts the array alphabetically. It then appends those items into a document fragment and finally back to the parent element.

Upvotes: 1

epascarello
epascarello

Reputation: 207537

jQuery sort and read the title attribute

$('td').each(function() {
  var td = $(this)
  td.find('span').sort(function(a, b) {
    return a.title.localeCompare(b.title)
  }).appendTo(td)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
  <tr>
    <td>
      <span title=BBB class="ms-RadioText">
        <input id="Checkbox1" type="checkbox"/>
        <label for="Checkbox1">BBB</label>
    </span>
      <span title=AAA class="ms-RadioText">
        <input id="Checkbox2" type="checkbox"/>
        <label for="Checkbox2">AAA</label>
    </span>
    </td>
  </tr>
  <tr>
    <td>
      <span title=FFF class="ms-RadioText">
        <input id="Checkbox1b" type="checkbox"/>
        <label for="Checkbox1b">FFF</label>
    </span>
      <span title=ZZZ class="ms-RadioText">
        <input id="Checkbox2b" type="checkbox"/>
        <label for="Checkbox2b">ZZZ</label>
    </span>
      <span title=EEE class="ms-RadioText">
        <input id="Checkbox3b" type="checkbox"/>
        <label for="Checkbox3b">EEE</label>
    </span>
    </td>
  </tr>

</table>

Without jQuery

document.querySelectorAll('td').forEach(function(td) {
  const spans = td.querySelectorAll('span')
  const ordered = Array.from(spans).sort( function (a,b) {
    return a.title.localeCompare(b.title)
  })
  var frag = ordered.reduce(function (frag, span){
    frag.appendChild(span)
    return frag
  }, document.createDocumentFragment())
  td.appendChild(frag)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
  <tr>
    <td>
      <span title=BBB class="ms-RadioText">
        <input id="Checkbox1" type="checkbox"/>
        <label for="Checkbox1">BBB</label>
    </span>
      <span title=AAA class="ms-RadioText">
        <input id="Checkbox2" type="checkbox"/>
        <label for="Checkbox2">AAA</label>
    </span>
    </td>
  </tr>
  <tr>
    <td>
      <span title=FFF class="ms-RadioText">
        <input id="Checkbox1b" type="checkbox"/>
        <label for="Checkbox1b">FFF</label>
    </span>
      <span title=ZZZ class="ms-RadioText">
        <input id="Checkbox2b" type="checkbox"/>
        <label for="Checkbox2b">ZZZ</label>
    </span>
      <span title=EEE class="ms-RadioText">
        <input id="Checkbox3b" type="checkbox"/>
        <label for="Checkbox3b">EEE</label>
    </span>
    </td>
  </tr>

</table>

Upvotes: 4

Related Questions