From 173059f6d00faa06dab9188efb2d7536f15861e4 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 18 Feb 2014 12:29:05 +0100 Subject: Fixed file list sorting Now using a natural sort algorithm that is more consistent between JS and PHP (although not perfect in some corner cases) - added OC.Util.naturalSortComparator that uses the same algo that was used for the user list - changed user list and files list to use OC.Util.naturalSortComparator - removed toLowerCase() and changed the comparator to use String.localeCompare() - added unit tests - added OC_NaturalSort that is used by OCP\Util::naturalSortCompare() --- core/js/js.js | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'core/js/js.js') diff --git a/core/js/js.js b/core/js/js.js index 60f9cc11a58..b6bfa01d0d5 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -1365,8 +1365,56 @@ OC.Util = { // FIXME: likely to break when crossing DST // would be better to use a library like momentJS return new Date(date.getFullYear(), date.getMonth(), date.getDate()); + }, + + _chunkify: function(t) { + // Adapted from http://my.opera.com/GreyWyvern/blog/show.dml/1671288 + var tz = [], x = 0, y = -1, n = 0, code, c; + + while (x < t.length) { + c = t.charAt(x); + var m = (c === '.' || (c >= '0' && c <= '9')); + if (m !== n) { + // next chunk + y++; + tz[y] = ''; + n = m; + } + tz[y] += c; + x++; + } + return tz; + }, + /** + * Compare two strings to provide a natural sort + * @param a first string to compare + * @param b second string to compare + * @return -1 if b comes before a, 1 if a comes before b + * or 0 if the strings are identical + */ + naturalSortCompare: function(a, b) { + var aa = OC.Util._chunkify(a); + var bb = OC.Util._chunkify(b); + + for (x = 0; aa[x] && bb[x]; x++) { + if (aa[x] !== bb[x]) { + var aNum = Number(aa[x]), bNum = Number(bb[x]); + // note: == is correct here + if (aNum == aa[x] && bNum == bb[x]) { + return aNum - bNum; + } else { + // Forcing 'en' locale to match the server-side locale which is + // always 'en'. + // + // Note: This setting isn't supported by all browsers but for the ones + // that do there will be more consistency between client-server sorting + return aa[x].localeCompare(bb[x], 'en'); + } + } + } + return aa.length - bb.length; } -}; +} /** * Utility class for the history API, -- cgit v1.2.3