Skip to content

Commit b02c6bc

Browse files
committed
Replaced natural sort with a date aware algorithm.
1 parent 338f3dc commit b02c6bc

File tree

1 file changed

+56
-23
lines changed

1 file changed

+56
-23
lines changed

pivot.coffee

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -176,29 +176,62 @@ callWithJQuery ($) ->
176176
when "S" then zeroPad(date.getSeconds())
177177
else "%" + p
178178

179-
naturalSort = (as, bs) => #thanks http://stackoverflow.com/a/4373421/112871
180-
rx = /(\d+)|(\D+)/g
181-
rd = /\d/
182-
rz = /^0/
183-
if typeof as is "number" or typeof bs is "number"
184-
return 1 if isNaN(as)
185-
return -1 if isNaN(bs)
186-
return as - bs
187-
a = String(as).toLowerCase()
188-
b = String(bs).toLowerCase()
189-
return 0 if a is b
190-
return (if a > b then 1 else -1) unless rd.test(a) and rd.test(b)
191-
a = a.match(rx)
192-
b = b.match(rx)
193-
while a.length and b.length
194-
a1 = a.shift()
195-
b1 = b.shift()
196-
if a1 isnt b1
197-
if rd.test(a1) and rd.test(b1)
198-
return a1.replace(rz, ".0") - b1.replace(rz, ".0")
199-
else
200-
return (if a1 > b1 then 1 else -1)
201-
a.length - b.length
179+
#
180+
# * Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license
181+
# * Author: Jim Palmer (based on chunking idea from Dave Koelle)
182+
# * http://www.overset.com/2008/09/01/javascript-natural-sort-algorithm-with-unicode-support/
183+
#
184+
naturalSort = (a, b) ->
185+
re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/g
186+
sre = /(^[ ]*|[ ]*$)/g
187+
dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/
188+
hre = /^0x[0-9a-f]+$/i
189+
ore = /^0/
190+
i = (s) ->
191+
naturalSort.insensitive and ("" + s).toLowerCase() or "" + s
192+
193+
194+
# convert all to strings strip whitespace
195+
x = i(a).replace(sre, "") or ""
196+
y = i(b).replace(sre, "") or ""
197+
198+
# chunk/tokenize
199+
xN = x.replace(re, "\u0000$1\u0000").replace(/\0$/, "").replace(/^\0/, "").split("\u0000")
200+
yN = y.replace(re, "\u0000$1\u0000").replace(/\0$/, "").replace(/^\0/, "").split("\u0000")
201+
202+
# numeric, hex or date detection
203+
xD = parseInt(x.match(hre)) or (xN.length isnt 1 and x.match(dre) and Date.parse(x))
204+
yD = parseInt(y.match(hre)) or xD and y.match(dre) and Date.parse(y) or null
205+
oFxNcL = undefined
206+
oFyNcL = undefined
207+
208+
# first try and sort Hex codes or Dates
209+
if yD
210+
if xD < yD
211+
return -1
212+
else return 1 if xD > yD
213+
214+
# natural sorting through split numeric strings and default strings
215+
cLoc = 0
216+
numS = Math.max(xN.length, yN.length)
217+
218+
while cLoc < numS
219+
220+
# find floats not starting with '0', string or 0 if not defined (Clint Priest)
221+
oFxNcL = not (xN[cLoc] or "").match(ore) and parseFloat(xN[cLoc]) or xN[cLoc] or 0
222+
oFyNcL = not (yN[cLoc] or "").match(ore) and parseFloat(yN[cLoc]) or yN[cLoc] or 0
223+
224+
# handle numeric vs string comparison - number < string - (Kyle Adams)
225+
if isNaN(oFxNcL) isnt isNaN(oFyNcL)
226+
return (if (isNaN(oFxNcL)) then 1 else -1)
227+
228+
# rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
229+
else if typeof oFxNcL isnt typeof oFyNcL
230+
oFxNcL += ""
231+
oFyNcL += ""
232+
return -1 if oFxNcL < oFyNcL
233+
return 1 if oFxNcL > oFyNcL
234+
cLoc++
202235

203236
#expose these to the outside world
204237
$.pivotUtilities = {aggregatorTemplates, aggregators, renderers, derivers, locales,

0 commit comments

Comments
 (0)