diff --git a/core/modules/wiki.js b/core/modules/wiki.js index ce660100c..e92cccf33 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -365,49 +365,108 @@ Sort an array of tiddler titles by a specified field */ exports.sortTiddlers = function(titles,sortField,isDescending,isCaseSensitive,isNumeric,isAlphaNumeric) { var self = this; - titles.sort(function(a,b) { - var x,y, - compareNumbers = function(x,y) { - var result = - isNaN(x) && !isNaN(y) ? (isDescending ? -1 : 1) : - !isNaN(x) && isNaN(y) ? (isDescending ? 1 : -1) : - (isDescending ? y - x : x - y); - return result; - }; - if(sortField !== "title") { - var tiddlerA = self.getTiddler(a), - tiddlerB = self.getTiddler(b); - if(tiddlerA) { - a = tiddlerA.fields[sortField] || ""; + if(sortField === "title") { + if(!isNumeric && !isAlphaNumeric) { + if(isCaseSensitive) { + if(isDescending) { + titles.sort(function(a,b) { + return b.localeCompare(a); + }); + } else { + titles.sort(function(a,b) { + return a.localeCompare(b); + }); + } } else { - a = ""; + if(isDescending) { + titles.sort(function(a,b) { + return b.toLowerCase().localeCompare(a.toLowerCase()); + }); + } else { + titles.sort(function(a,b) { + return a.toLowerCase().localeCompare(b.toLowerCase()); + }); + } } - if(tiddlerB) { - b = tiddlerB.fields[sortField] || ""; - } else { - b = ""; - } - } - x = Number(a); - y = Number(b); - if(isNumeric && (!isNaN(x) || !isNaN(y))) { - return compareNumbers(x,y); - } else if($tw.utils.isDate(a) && $tw.utils.isDate(b)) { - return isDescending ? b - a : a - b; - } else if(isAlphaNumeric) { - a = String(a); - b = String(b); - return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"}); } else { + titles.sort(function(a,b) { + var x,y; + if(isNumeric) { + x = Number(a); + y = Number(b); + if(isNaN(x)) { + if(isNaN(y)) { + return 0; + } else { + return isDescending ? -1 : 1; + } + } else { + if(isNaN(y)) { + return isDescending ? 1 : -1; + } else { + return isDescending ? y - x : x - y; + } + } + } + if(isAlphaNumeric) { + return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"}); + } + if(!isCaseSensitive) { + a = a.toLowerCase(); + b = b.toLowerCase(); + } + return isDescending ? b.localeCompare(a) : a.localeCompare(b); + }); + } + } else { + titles.sort(function(a,b) { + var x,y; + if(sortField !== "title") { + var tiddlerA = self.getTiddler(a), + tiddlerB = self.getTiddler(b); + if(tiddlerA) { + a = tiddlerA.fields[sortField] || ""; + } else { + a = ""; + } + if(tiddlerB) { + b = tiddlerB.fields[sortField] || ""; + } else { + b = ""; + } + } + if(isNumeric) { + x = Number(a); + y = Number(b); + if(isNaN(x)) { + if(isNaN(y)) { + return 0; + } else { + return isDescending ? -1 : 1; + } + } else { + if(isNaN(y)) { + return isDescending ? 1 : -1; + } else { + return isDescending ? y - x : x - y; + } + } + } + if(Object.prototype.toString.call(a) === "[object Date]" && Object.prototype.toString.call(b) === "[object Date]") { + return isDescending ? b - a : a - b; + } a = String(a); b = String(b); + if(isAlphaNumeric) { + return isDescending ? b.localeCompare(a,undefined,{numeric: true,sensitivity: "base"}) : a.localeCompare(b,undefined,{numeric: true,sensitivity: "base"}); + } if(!isCaseSensitive) { a = a.toLowerCase(); b = b.toLowerCase(); } return isDescending ? b.localeCompare(a) : a.localeCompare(b); - } - }); + }); + } }; /* diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index 9bd289440..8e8063001 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -265,6 +265,8 @@ function runTests(wiki) { it("should handle the sort and sortcs operators", function() { expect(wiki.filterTiddlers("[sort[title]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne"); expect(wiki.filterTiddlers("[!sort[title]]").join(",")).toBe("TiddlerOne,Tiddler Three,one,hasList,has filter,filter regexp test,a fourth tiddler,$:/TiddlerTwo,$:/ShadowPlugin"); + expect(wiki.filterTiddlers("[sort[modified]]").join(",")).toBe("$:/ShadowPlugin,a fourth tiddler,one,hasList,has filter,filter regexp test,$:/TiddlerTwo,TiddlerOne,Tiddler Three"); + expect(wiki.filterTiddlers("[!sort[modified]]").join(",")).toBe("Tiddler Three,TiddlerOne,$:/TiddlerTwo,$:/ShadowPlugin,a fourth tiddler,one,hasList,has filter,filter regexp test"); // Temporarily commenting out the following two lines because of platform differences for localeCompare between the browser and Node.js // expect(wiki.filterTiddlers("[sortcs[title]]").join(",")).toBe("$:/TiddlerTwo,Tiddler Three,TiddlerOne,a fourth tiddler,one"); // expect(wiki.filterTiddlers("[!sortcs[title]]").join(",")).toBe("one,a fourth tiddler,TiddlerOne,Tiddler Three,$:/TiddlerTwo"); @@ -745,6 +747,7 @@ function runTests(wiki) { it("should handle the sortan operator sorting on date fields", function() { expect(wiki.filterTiddlers("TiddlerOne $:/TiddlerTwo [[Tiddler Three]] +[sortan[modified]]").join(",")).toBe("$:/TiddlerTwo,TiddlerOne,Tiddler Three"); + expect(wiki.filterTiddlers("hasList TiddlerOne $:/TiddlerTwo [[Tiddler Three]] +[sortan[modified]]").join(",")).toBe("hasList,$:/TiddlerTwo,TiddlerOne,Tiddler Three"); }); it("should handle the slugify operator", function() {