123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- var Op = require("../Op"),
- traverse = require("traverse");
- //TODO: ...write this...
- var SortOp = module.exports = (function(){
- // CONSTRUCTOR
- var base = Op, proto, klass = function SortOp(opts){
- // Parse sorts from options object
- if(typeof(opts) !== "object") throw new Error("the $sort key specification must be an object");
- this.sorts = [];
- for(var p in opts){
- if(p[0] === "$") throw new Error("$sort: FieldPath field names may not start with '$'.; code 16410");
- if(p === "") throw new Error("$sort: FieldPath field names may not be empty strings.; code 15998");
- this.sorts.push({path:p.split("."), direction:opts[p]});
- }
- console.log("SORTS FOR $sort OP:", this.sorts);
- this.objs = [];
- base.call(this, opts);
- };
- proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
- // PRIVATE STUFF
- // Helpers for sorting
- var types = ["undefined", "null", "NaN", "number", "string", "object", "boolean", "Date"];
- function getTypeOf(o){
- if(o === undefined) return "undefined";
- if(o === null) return "null";
- if(isNaN(o)) return "NaN";
- if(o.constructor === Date) return "Date";
- return typeof(o);
- }
- // PROTOTYPE MEMBERS
- proto.write = function writeDeferredForSorting(obj){
- console.log("$sort deferring:", obj);
- this.objs.push(obj);
- };
- proto.end = function endSort(obj){
- console.log("$sort end event");
- if(this.objs.length){
- console.log("OBJS TO BE SORTED:", this.objs);
- this.objs.sort(function(a, b){
- for(var i = 0, l = this.sorts.length; i < l; i++){
- //TODO: this probably needs to compareDeep using traverse(a).forEach(...check b...) or similar
- var sort = this.sorts[i],
- aVal = traverse(a).get(sort.path), aType = getTypeOf(aVal),
- bVal = traverse(b).get(sort.path), bType = getTypeOf(bVal);
- // null and undefined go first
- if(aType !== bType){
- return (types.indexOf(aType) - types.indexOf(bType)) * sort.direction;
- }else{
- // don't trust type cohersion
- if(aType == "number") bVal = parseFloat(bVal);
- if(isNaN(bVal)) return 1;
- if(aType == "string") bVal = bVal.toString();
- // return sort value only if it can be determined at this level
- if(aVal < bVal) return -1 * sort.direction;
- if(aVal > bVal) return 1 * sort.direction;
- }
- }
- return 0;
- });
- console.log("$sort has sorted");
- for(var i = 0, l = this.objs.length; i < l; i++)
- this.queue(this.objs[i]);
- }
- this.end();
- };
- return klass;
- })();
|