1
+ const arrayify = require ( 'array-back' )
1
2
const t = require ( 'typical' )
2
3
3
4
/**
@@ -89,17 +90,63 @@ module.exports = sortBy
89
90
* }
90
91
* ```
91
92
*/
92
- function sortBy ( recordset , sortBy , computedProperties ) {
93
- return recordset . sort ( compare ( sortBy , computedProperties ) )
93
+ // @TODO : Incorporate sharedCompProps into sanity checks
94
+ function sortBy ( recordset , sortBy , sortTypes , sharedCompProps ) {
95
+ // Ensure arguments are of the expected type
96
+ recordset = arrayify ( recordset )
97
+ sortBy = arrayify ( sortBy )
98
+ sortTypes = arrayify ( sortTypes )
99
+
100
+ // Perform sanity checks early.
101
+ let isPrimitiveSort = recordset . some ( record => t . isPrimitive ( record ) )
102
+ if ( isPrimitiveSort ) {
103
+ // Any 'sortBy' arguments invalidate the sort, because they will not be
104
+ // applicable on a primitive array.
105
+ if ( sortBy . length !== 0 ) {
106
+ return recordset
107
+ }
108
+ } else {
109
+ // At least one 'sortBy' argument must be provided, so that the recordset
110
+ // can be sorted according to that property.
111
+ if ( sortBy . length === 0 ) {
112
+ return recordset
113
+ }
114
+ }
115
+
116
+ // Ensure the arguments are correctly provided. Hydrate or prune as
117
+ // required.
118
+ if ( ( sortBy . length === 0 ) && ( sortTypes . length === 0 ) ) {
119
+ sortTypes . push ( 'asc' )
120
+ } else if ( sortBy . length > sortTypes . length ) {
121
+ // Not enough sortTypes have been provided. Fully hydrate the sortTypes
122
+ // array, using 'asc' by default.
123
+ let noOfMissingSortTypes = sortBy . length - sortTypes . length
124
+ for ( let i = 0 ; i < noOfMissingSortTypes ; i ++ ) {
125
+ sortTypes . push ( 'asc' )
126
+ }
127
+ } else if ( sortBy . length < sortTypes . length ) {
128
+ // Too many sortTypes have been provided. Prune the redundant ones
129
+ // at the end of the sortType array.
130
+ sortTypes . splice ( - 1 , noOfExcessSortTypes )
131
+ }
132
+
133
+ if ( isPrimitiveSort ) {
134
+ return recordset . sort ( comparePrim ( sortBy , sortTypes ) )
135
+ } else {
136
+ return recordset . sort ( compare ( sortBy , sortTypes , sharedCompProps ) )
137
+ }
138
+ }
139
+
140
+ function comparePrim ( sortBy , sortTypes ) {
141
+ console . log ( 'comparePrim() NOT YET IMPLEMENTED' )
94
142
}
95
143
96
- // @TODO : Question - do we support crap data in? E.g. testing for 't.isArrayLike',
97
- // @TODO : rather than just assuming the data in is correct?
98
- function compare ( sortBy , computedProperties ) {
99
- let sorts = Object . entries ( sortBy )
100
- let propSort = sorts . shift ( )
101
- let property = t . isArrayLike ( propSort ) && propSort [ 0 ] || undefined
102
- let sort = t . isArrayLike ( propSort ) && propSort [ 1 ] || 'asc'
144
+ function compare ( sortBy , sortTypes , sharedCompProps ) {
145
+ let sorts = sortBy . slice ( 0 )
146
+ let property = sorts . shift ( )
147
+
148
+ let types = sortTypes . slice ( 0 )
149
+ let sort = types . shift ( )
103
150
104
151
return function sorter ( a , b ) {
105
152
let x
@@ -108,47 +155,40 @@ function compare (sortBy, computedProperties) {
108
155
let recurse
109
156
let currentSort = sort
110
157
111
- if ( t . isDefined ( computedProperties ) && computedProperties . hasOwnProperty ( property ) ) {
112
- x = computedProperties [ property ] ( a )
113
- y = computedProperties [ property ] ( b )
114
- } else {
158
+ if ( t . isFunction ( sort ) ) {
159
+ // Apply a calculated property sort
160
+ x = sort ( a )
161
+ y = sort ( b )
162
+ // Perform an asc sort by default, then invert later if a desc has been
163
+ // requested for the current property.
164
+ results = getAscOrder ( x , y )
165
+ } else if ( t . isArrayLike ( sort ) ) {
166
+ // Apply custom ordering
115
167
x = a [ property ]
116
168
y = b [ property ]
117
- }
118
-
119
- if ( t . isArrayLike ( sort ) ) {
120
- // Custom sort the current property.
121
169
result = sort . indexOf ( y ) - sort . indexOf ( x )
122
170
} else {
123
- // Asc/desc sort the current property. Perform an asc sort by default,
124
- // then invert the result later if a desc has been requested for the
125
- // current property.
126
- if ( x === null && y === null ) {
127
- result = 0
128
- } else if ( ( ! t . isDefined ( x ) || x === null ) && t . isDefined ( y ) ) {
129
- result = - 1
130
- } else if ( t . isDefined ( x ) && ( ! t . isDefined ( y ) || y === null ) ) {
131
- result = 1
132
- } else if ( ! t . isDefined ( x ) && ! t . isDefined ( y ) ) {
133
- result = 0
134
- } else {
135
- result = x < y ? - 1 : x > y ? 1 : 0
136
- }
171
+ // Apply a simple asc/desc sort
172
+ x = a [ property ]
173
+ y = b [ property ]
174
+ // Perform an asc sort by default, then invert later if a desc has been
175
+ // requested for the current property.
176
+ results = getAscOrder ( x , y )
137
177
}
138
178
139
- // Reset this sorting function and parent, unless we have an equal
179
+ // Reset this sorting function and parent, unless there is an equal
140
180
// result and there are more sorts still to perform, in which case
141
181
// move on to the next one.
142
182
if ( result === 0 && sorts . length ) {
143
183
recurse = true
144
184
} else {
145
185
recurse = false
146
- sorts = Object . entries ( sortBy )
186
+ sorts = sortBy . slice ( 0 )
187
+ types = sortTypes . slice ( 0 )
147
188
}
148
189
149
- propSort = sorts . shift ( )
150
- property = t . isArrayLike ( propSort ) && propSort [ 0 ] || undefined
151
- sort = t . isArrayLike ( propSort ) && propSort [ 1 ] || 'asc'
190
+ property = sorts . shift ( )
191
+ sort = types . shift ( )
152
192
153
193
// Present the result
154
194
if ( recurse ) {
@@ -160,3 +200,19 @@ function compare (sortBy, computedProperties) {
160
200
}
161
201
}
162
202
}
203
+
204
+ function getAscOrder ( x , y ) {
205
+ let result
206
+ if ( x === null && y === null ) {
207
+ result = 0
208
+ } else if ( ( ! t . isDefined ( x ) || x === null ) && t . isDefined ( y ) ) {
209
+ result = - 1
210
+ } else if ( t . isDefined ( x ) && ( ! t . isDefined ( y ) || y === null ) ) {
211
+ result = 1
212
+ } else if ( ! t . isDefined ( x ) && ! t . isDefined ( y ) ) {
213
+ result = 0
214
+ } else {
215
+ result = x < y ? - 1 : x > y ? 1 : 0
216
+ }
217
+ return result
218
+ }
0 commit comments