Многократная сортировка в 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>