Vincent Teyssier
Vincent Teyssier

Reputation: 2217

Sorting a dynamically generated list by value of one of its elements

I dynamically generate a list of files in a folder displayed as follow :

<ul class="listDocs">
  <li class="docResult">
    <div class="file-icon"><i class="fa fa-file-word-o"></i></div>
    <div class="filename_container" id="file_2" data-file="./cases/xxx.doc" data-folder="">xxx.doc</div>
    <div class="file_download"><a href="./cases/xxx.doc" target="_blank"><i class="fa fa-download"></i></a></div>
    <div class="btn_remove_style file-remove fa fa-trash-o" data-file="./cases/xxx.doc"></div>
  </li>
  <li class="docResult">...

I would like to add buttons which would allow me to sort the files according various criteria. I try first to sort them by the text inside the div 'filename_container'. To do so I try the following but I don't manage to make it work :

function sortFilesByText () {
    var list = $('.listDocs');
    var listItems = list.find('filename_container').sort(function(a,b) {  
      return $(a).text() - $(b).text();
    });
    list.find('li').remove();
    list.append(listItems);
}

$(document).on('click', '#btn_sort_name', function () {
    sortFilesByText();
});

I understand that by doing so I only sort the <div> 'file_container' and therefore do not append the whole code inside one li, but I don't know how to do that....

Upvotes: 3

Views: 590

Answers (3)

synthet1c
synthet1c

Reputation: 6282

A native js way.

// get the results as a HTMLCollection
var
  list = document.querySelector('.listDocs'),
  results = document.querySelectorAll('.docResult');

console.log(results);

// use array sort to change the order of the HTMLCollection
var sliced = Array.prototype.slice.call(results, 0);

sliced.sort(sortByElementText('.filename_container'));

// remove the list items from the list
list.innerHTML = '';

// replace the list items in the correct order
sliced.reduce(function(list, item) {
  list.appendChild(item);
  return list;
}, list);

console.log( document.querySelectorAll('.docResult') );

// helper function to sort by a particular child element
function sortByElementText(selector) {
  return function(a, b) {
    var bContainer = b.querySelector(selector).innerText;
    var aContainer = a.querySelector(selector).innerText;
    return aContainer > bContainer;
  }
}
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>
<ul class="listDocs">
  <li class="docResult" id="result3">
    <div class="filename_container" id="file2" data-file="./cases/zzz.doc">zzz.doc</div>
  </li>
  <li class="docResult" id="result1">
    <div class="filename_container" id="file1" data-file="./cases/xxx.doc">xxx.doc</div>
  </li>
  <li class="docResult" id="result2">
    <div class="filename_container" id="file3" data-file="./cases/yyy.doc">yyy.doc</div>
  </li>
</ul>

Upvotes: 1

Andreas
Andreas

Reputation: 21881

Get the "filename" in the sort function

function sortFilesByText() {
    var list = $('.listDocs'),
        listItems = list.find("li").sort(function (a, b) {
            var fileA = $(a).find(".filename_container").text(),
                fileB = $(b).find(".filename_container").text();

            if (fileA == fileB) return 0;
            return (fileA > fileB) ? 1 : -1;
        });

    list.find('li').remove();
    list.append(listItems);
}

Upvotes: 2

Vanojx1
Vanojx1

Reputation: 5574

you re using the wrong selector ( also missing the . in class selector ) , try this:

function sortFilesByText () {
    var list = $('.listDocs');
    var listItems = list.find('.docResult').sort(function(a,b){  
      return $(a).find(".filename_container").text() - $(b).find(".filename_container").text(); });
    list.find('li').remove();
    list.append(listItems);
}

Upvotes: 0

Related Questions