Locale sorting
Closed this issue · 2 comments
boily commented
Hi,
item names with accents are not sorted correctly.
["école", "professeur"] sort in wrong way.
I have tried to replace with
return a.v.localeCompare(b.v) > 0 ? reverse : b.v.localeCompare(a.v) > 0 ? -reverse : 0;
in the mapped.sort function and it works fine.
thanks
Roger
BorisMoore commented
Hi Roger,
localeCompare is unfortunately much slower than regular comparison operators, so it would not be a good idea to replace the default sort using your suggested code above.
The recommended approach is to use a custom sort function with localeCompare.
The code below is for a new sample which I will add to the jsviews.com site, showing the use of localeCompare in a custom sort function:
<!DOCTYPE html>
<!-- To run the current sample code in your own environment, copy this to an html page. -->
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://www.jsviews.com/download/jsrender.min.js"></script>
<link href="https://www.jsviews.com/samples/samples.css" rel="stylesheet" />
</head>
<body>
<script id="myTmpl" type="text/x-jsrender">
<div class="left">
<label>Localized sort of French words</label>
<ul>
{{for words sort=~locale}} {{!-- Sort using a custom helper function with localeCompare() --}}
<li>{{:}}</li>
{{/for}}
</ul>
</div>
<div class="left">
<label>Multilevel sort</label>
<ul>
{{for people sort=~multilevel}} {{!-- Sort using a custom helper function for multi-level sorting --}}
<li>{{:name}}: ({{:details.role}}) – age {{:details.age}}</li>
{{/for}}
</ul>
</div>
</script>
<div id="page"></div>
<script>
// Custom sort functions
function localeSort(a, b) {
// Return 1, -1 or 0 to specify relative position of `a` and `b` in the sort order
// Localized sort
return a.localeCompare(b) > 0 ? 1 : b.localeCompare(a) > 0 ? -1 : 0;
}
function multilevelSort(a, b) {
// Return 1, -1 or 0 to specify relative position of `a` and `b` in the sort order
// Sort by role, then by age (descending) then by name
return level(a.details.role.toLowerCase(), b.details.role.toLowerCase()) // by role
|| level(b.details.age, a.details.age) // by age
|| level(a.name.toLowerCase(), b.name.toLowerCase()); // by name
}
// Helper function for multi-level sort
function level(aField, bField) {
return aField > bField ? 1 : aField < bField ? -1 : 0;
}
$.views.helpers({
locale: localeSort,
multilevel: multilevelSort
});
var myTmpl = $.templates("#myTmpl"),
data = {
words:
["maître", "âme", "école", "amour", "absolu",
"maison", "vôtre", "être", "effort"],
people:
[
{name: "Bill", details: {age: 22, role: "Lead"}},
{name: "Anne", details: {age: 32, role: "Assistant"}},
{name: "Emma", details: {age: 19.1, role: "Team member"}},
{name: "Jeff", details: {age: 33.5, role: "Lead"}},
{name: "Xavier", details: {age: 32, role: "Team member"}},
{name: "Julia", details: {age: 18, role: "Assistant"}},
{name: "Bill", details: {age: 32, role: "Team member"}}
]
},
html = myTmpl.render(data);
$("#page").html(html);
</script>
</body>
</html>
boily commented
Thanks a lot Boris, very useful.