Source: functions/comparator.js

  1. /**
  2. * A string, a function, or an array of mixed values.
  3. *
  4. * ```javascript
  5. * 'age' // age property of an object
  6. * '-age' // age property of an object, ordering reversed
  7. * function(a, b) {} // a function which compares two values
  8. * ['age', 'done'] // age property of an object, and when equal, the done value
  9. * 'creator.name' // name sub-property of creator property
  10. * '{creator.name}, {age}' // formatted string
  11. * ```
  12. *
  13. * @typedef {String|comparisonCallback|Array} comparatorInput
  14. */
  15. var Comparators = {};
  16. function saveComparator(name, comparatorInput, nullsFirst)
  17. {
  18. var comparator = createComparator( comparatorInput, nullsFirst );
  19. Comparators[ name ] = comparator;
  20. return comparator;
  21. }
  22. function addComparator(second, comparatorInput, nullsFirst)
  23. {
  24. var first = createComparator( comparatorInput, nullsFirst );
  25. if ( !isFunction( second ) )
  26. {
  27. return first;
  28. }
  29. return function compareCascading(a, b)
  30. {
  31. var d = first( a, b );
  32. return d !== 0 ? d : second( a, b );
  33. };
  34. }
  35. /**
  36. * Creates a function which compares two values.
  37. *
  38. * @memberof Rekord
  39. * @param {comparatorInput} comparator
  40. * The input which creates a comparison function.
  41. * @param {Boolean} [nullsFirst=false] -
  42. * True if null values should be sorted first.
  43. * @return {comparisonCallback}
  44. */
  45. function createComparator(comparator, nullsFirst)
  46. {
  47. if ( isFunction( comparator ) )
  48. {
  49. return comparator;
  50. }
  51. else if ( isString( comparator ) )
  52. {
  53. if ( comparator in Comparators )
  54. {
  55. return Comparators[ comparator ];
  56. }
  57. if ( comparator.charAt(0) === '-' )
  58. {
  59. var parsed = createComparator( comparator.substring( 1 ), !nullsFirst );
  60. return function compareObjectsReversed(a, b)
  61. {
  62. return -parsed( a, b );
  63. };
  64. }
  65. else if ( comparator.indexOf('{') !== -1 )
  66. {
  67. return function compareFormatted(a, b)
  68. {
  69. var af = format( comparator, a );
  70. var bf = format( comparator, b );
  71. return af.localeCompare( bf );
  72. };
  73. }
  74. else if ( comparator.indexOf('.') !== -1 )
  75. {
  76. return function compareExpression(a, b)
  77. {
  78. var ap = parse( comparator, a );
  79. var bp = parse( comparator, b );
  80. return compare( ap, bp, nullsFirst );
  81. };
  82. }
  83. else
  84. {
  85. return function compareObjects(a, b)
  86. {
  87. var av = isValue( a ) ? a[ comparator ] : a;
  88. var bv = isValue( b ) ? b[ comparator ] : b;
  89. return compare( av, bv, nullsFirst );
  90. };
  91. }
  92. }
  93. else if ( isArray( comparator ) )
  94. {
  95. var parsedChain = [];
  96. for (var i = 0; i < comparator.length; i++)
  97. {
  98. parsedChain[ i ] = createComparator( comparator[ i ], nullsFirst );
  99. }
  100. return function compareObjectsCascade(a, b)
  101. {
  102. var d = 0;
  103. for (var i = 0; i < parsedChain.length && d === 0; i++)
  104. {
  105. d = parsedChain[ i ]( a, b );
  106. }
  107. return d;
  108. };
  109. }
  110. return null;
  111. }