Многократная сортировка в List.js

Я использую List.js для отображения, поиска, фильтрации, много содержимого в произвольном порядке.

Мой ряд сделан так

<div class="content-row">
    <div class="order_id" style="display:none;">{{$item['order']}}</div>
    <div class="order_category" style="display:none;">99999</div>
    <div class="order_source" style="display:none;">99999</div>
    <div class="order_page" style="display:none;">99999</div>
    <div class="content_date" style="display:none;">2016-11-08 11:00:00</div>
    <div class="dd-handle row-container"> I am a row </div>
</div>

Я пытаюсь упорядочить свой список контента по нескольким порядкам: первый порядок по order_categoryзатем order_sourceзатем content_dateи, наконец, order_page,

В Firefox я пытался упорядочить список от менее важного к более важному порядку, и это, кажется, работает, но это не сработало в Chrome:

// Options
var options = {
    valueNames: ['content_id', 'content_date', 'order_id', 'order_category', 'order_source', 'order_page']
};
// Get list Html
var listElement = $("#main_list");
// Init list obj
var listInstance = new List(listElement[0], options);

# ....

// This works in Firefox but not in Chrome!

// Order by page
listInstance.sort('order_page', {
    order: "asc"
});
// then order by date
listInstance.sort('content_date', {
    order: "desc"
});
// then order by list
listInstance.sort('order_source', {
    order: "asc"
});
// finally order by category
listInstance.sort('order_category', {
    order: "asc"
});

# ....

Я знаю, что List.js сейчас не поддерживает множественную сортировку, но я читал, что поддерживает пользовательскую функцию сортировки. Может ли кто-нибудь научить / показать мне, как построить собственную функцию сортировки?


Редактировать:

Благодаря @Dekel я создаю свой собственный метод, который использует List.js с пользовательской функцией сортировки с 4 уровнями сортировки. Хорошо работает с одним типом сортировки (ASC или же DESC) указано в List.js. Я сообщаю свой код:

/**
 * Sort a List.js list by 4 level of sort
 *
 * @param  {Object} list        [List.js instance]
 * @param  {String} first       [First field to sort]
 * @param  {String} second      [Second field to sort]
 * @param  {String} third       [Third field to sort]
 * @param  {String} fourth      [Fourth field to sort]
 * @param  {String} sort        [sort type: asc || desc]
 * @return {}                   []
 */
var sortList = function(list, first, second, third, fourth, sort) {

    // If list not defined
    if (Utility.empty(list)) {
        console.error("ListManager: can't sort, list is undefined!");
        // Error no list!
        return false;
    }

    // If first order id not defined
    if (Utility.empty(first)) {
        // Set default
        first = "name";
    }

    // If second order id not defined
    if (Utility.empty(second)) {
        // Set default
        second = "born";
    }

    // If third order id not defined
    if (Utility.empty(third)) {
        // Set default
        third = "color";
    }

    // If fourth order id not defined
    if (Utility.empty(fourth)) {
        // Set default
        fourth = "lastName";
    }

    // Check order is not defined
    if (Utility.empty(sort)) {
        // Set default order type to desc 
        sort = "desc";
    }

    // Make list order compatible with list.js fields
    first = "order_" + first;
    second = "order_" + second;
    third = "order_" + third;
    fourth = "order_" + fourth;

    console.log("List Sort: ", first, second, third, fourth);

    // Call sort method of List.js
    list.sort('', {order: sort,
        sortFunction:
            function(a, b) {
                // Compare values with field requested
                return _compareIntegerStringDate(a, b, first)
                    || _compareIntegerStringDate(a, b, second)
                    || _compareIntegerStringDate(a, b, third)
                    || _compareIntegerStringDate(a, b, fourth);
            }
        }
    );
}


/**
 * Compare list.js items value based on filed request.
 * Get correct comparison between integers, strings, or dates.
 *
 * @param  {Object}  a           [List.js item instance]
 * @param  {Object}  b           [List.js item instance]
 * @param  {String}  field       [Field to compare]
 * @return {Integer}             [-X || 0 || +X]
 */
var _compareIntegerStringDate = function(a, b, field) {
    if (Utility.isInt(a.values()[field])) {
        // Compare integer
        return  b.values()[field] - a.values()[field];
    }
    else if(Utility.isDate(a.values()[field], "YYYY-MM-DD HH:mm:ss")){
        // Compare Date
        return Date.parse(b.values()[field]) - Date.parse(a.values()[field]);
    }
    else {
        // Compare strings
        return a.values()[field].localeCompare(b.values()[field]);
    }
}

Но если я попытаюсь указать тип сортировки (ASC или же DESC) для каждого значения это не работает. Я сообщаю, что мой код обновлен с этим улучшением:

/**
 * Sort a List.js list by 4 level of sort
 *
 * @param  {Object} list        [List.js instance]
 * @param  {String} first       [First field to sort]
 * @param  {String} second      [Second field to sort]
 * @param  {String} third       [Third field to sort]
 * @param  {String} fourth      [Fourth field to sort]
 * @param  {String} firstOrder  [Order type: asc || desc]
 * @param  {String} secondOrder [Order type: asc || desc]
 * @param  {String} thirdOrder  [Order type: asc || desc]
 * @param  {String} fourthOrder [Order type: asc || desc]
 * @return {}              []
 */
var sortList = function(list,
    first, second, third, fourth,
    firstOrder, secondOrder, thirdOrder, fourthOrder,
) {
    console.log("ListManager sort:", list, first, second, third, fourth);
    // If list not defined
    if (Utility.empty(list)) {
        console.error("ListManager: can't sort, list is undefined!");
        // Error no list!
        return false;
    }

    // If first order id not defined
    if (Utility.empty(first)) {
        // Set default
        first = "name";
    }

    // If second order id not defined
    if (Utility.empty(second)) {
        // Set default
        second = "born";
    }

    // If third order id not defined
    if (Utility.empty(third)) {
        // Set default
        third = "color";
    }

    // If fourth order id not defined
    if (Utility.empty(fourth)) {
        // Set default
        fourth = "lastName";
    }

    // Check order if asc or desc
    if (Utility.empty(firstOrder)) {
        // Set order
        firstOrder = "desc";
    }

    // Check order if asc or desc
    if (Utility.empty(secondOrder)) {
        // Set order
        secondOrder = "desc";
    }

    // Check order if asc or desc
    if (Utility.empty(thirdOrder)) {
        // Set order
        thirdOrder = "desc";
    }

    // Check order if asc or desc
    if (Utility.empty(fourthOrder)) {
        // Set order
        fourthOrder = "desc";
    }

    // Make list compatible
    first = "order_" + first;
    second = "order_" + second;
    third = "order_" + third;
    fourth = "order_" + fourth;
    // Make ascending descending compatible
    firstAsc = firstOrder === "asc" ? true : false;
    secondAsc = secondOrder === "asc" ? true : false;
    thirdAsc = thirdOrder === "asc" ? true : false;
    fourthAsc = fourthOrder === "asc" ? true : false;

    console.log("List Sort: ", first, second, third, fourth);
    console.log("List Asc: ", firstAsc, secondAsc, thirdAsc, fourthAsc);

    // Call sort method of List.js
    list.sort('', {order: '',
        sortFunction:
            function(a, b) {
                // Compare values with field requested
                return _compareIntegerStringDate(a, b, first, firstAsc)
                    || _compareIntegerStringDate(a, b, second, secondAsc)
                    || _compareIntegerStringDate(a, b, third, thirdAsc)
                    || _compareIntegerStringDate(a, b, fourth, fourthAsc);
            }
        }
    );
}

/**
 * Compare list.js items value based on filed request.
 * Get correct comparison between integers, strings, or dates.
 *
 * @param  {Object}  a           [List.js item instance]
 * @param  {Object}  b           [List.js item instance]
 * @param  {String}  field       [Field to compare]
 * @param  {Boolean} isAscending [Determinate if is ascending order]
 * @return {Integer}             [-X || 0 || +X]
 */
var _compareIntegerStringDate = function(a, b, field, isAscending) {
    console.log(field + " isAscending " + isAscending);
    if (Utility.isInt(a.values()[field])) {
        // Compare integer
        return isAscending
            ? a.values()[field] - b.values()[field]
            : b.values()[field] - a.values()[field];
    }
    else if(Utility.isDate(a.values()[field], "YYYY-MM-DD HH:mm:ss")){
        // Compare Date
        return isAscending
            ? Date.parse(a.values()[field]) - Date.parse(b.values()[field])
            : Date.parse(b.values()[field]) - Date.parse(a.values()[field]);
    }
    else {
        // Compare strings
        return isAscending
            ? b.values()[field].localeCompare(a.values()[field])
            : a.values()[field].localeCompare(b.values()[field]);
    }
}

Любые предложения, чтобы это исправить?

Большое спасибо!

1 ответ

Поддержка List.js писать свои собственные sort функция:

list.sort('name', {sortFunction: function() { ... })

По сути, функция sort получает два параметра - два элемента из списка и сравнивает их. Если первый элемент должен быть первым, функция должна вернуть -1. Если второй элемент должен быть первым, функция должна вернуть 1. Если они равны, функция должна вернуть 0.

List.js библиотека дает вам все имена-значения внутри a.values(), так что вы можете использовать их для сравнения.

В следующем примере я создал список с именами и годами и sort Функция сортировки по имени (asc) и году (desc).

var options = {
  valueNames: [ 'name', 'born' ]
};

var usersList = new List('users', options);
usersList.sort('', {order: "desc", sortFunction: 
                    function(a, b) {
                      if (Math.abs(b.values().name.localeCompare(a.values().name)) == 1) {
                        return b.values().name.localeCompare(a.values().name)
                      } else {
                        return a.values().born - b.values().born;
                      }
                    }
                   })
<script src="//cdnjs.cloudflare.com/ajax/libs/list.js/1.3.0/list.min.js"></script>

<div id="users">

  <input class="search" placeholder="Search" />
  <button class="sort" data-sort="name">
    Sort
  </button>

  <ul class="list">
    <li>
      <h3 class="name">AAA</h3>
      <p class="born">1986</p>
    </li>
    <li>
      <h3 class="name">AAB</h3>
      <p class="born">1985</p>
    </li>
    <li>
      <h3 class="name">AAC</h3>
      <p class="born">1986</p>
    </li>
    <li>
      <h3 class="name">AAB</h3>
      <p class="born">1983</p>
    </li>
  </ul>

</div>

Другие вопросы по тегам