json-object-editor
Version:
JOE the Json Object Editor | Platform Edition
1,202 lines (1,155 loc) • 441 kB
JavaScript
/*/---------------------------------------------------------/*/
/*/ Craydent LLC v1.8.0 /*/
/*/ Copyright 2011 (http://craydent.com/about) /*/
/*/ Dual licensed under the MIT or GPL Version 2 licenses. /*/
/*/ (http://craydent.com/license) /*/
/*/---------------------------------------------------------/*/
/*----------------------------------------------------------------------------------------------------------------
/- Global CONSTANTS and variables
/---------------------------------------------------------------------------------------------------------------*/
var __version = "1.8.0",
__thisIsNewer = true,
$w = typeof window != "undefined" ? window : {location:(typeof location != "undefined"?location:{href:''}),console:(typeof console != "undefined"?console:{})},
$g = $w,
$d = typeof document != "undefined" ? document : {},
$l = $w.location;
if ($w.__craydentLoaded || typeof($c) != "undefined") {
var __current = ($w.__craydentVersion||$c.VERSION||"").split("."),
__thisVersion = __version.split(".");
if(__thisIsNewer = __isNewer(__current,__thisVersion)) {
$c.VERSION = __version;
}
}
function __isNewer(loadedVersion, thisVersion){
if (loadedVersion[0] == thisVersion[0]) {
loadedVersion.splice(0,1);
thisVersion.splice(0,1);
if (!thisVersion.length || !loadedVersion.length) {
return false;
}
return __isNewer(loadedVersion, thisVersion);
}
return parseInt(loadedVersion[0]) < parseInt(thisVersion[0]);
}
function __cleanUp() {
try {
delete $w.__current;
delete $w.__thisVersion;
delete $w.__thisIsNewer;
delete $w.__isNewer;
delete $w.__version;
delete $w._ie;
delete $w._droid;
delete $w._amay;
delete $w._browser;
delete $w._os;
delete $w._device;
delete $w._engine;
} catch(e) {
$w.__current = undefined;
$w.__thisVersion = undefined;
$w.__thisIsNewer = undefined;
$w.__isNewer = undefined;
$w.__version = undefined;
$w._ie = undefined;
$w._droid = undefined;
$w._amay = undefined;
$w._browser = undefined;
$w._os = undefined;
$w._device = undefined;
$w._engine = undefined;
}
}
$w.__craydentVersion = __version;
if (__thisIsNewer) {
var _ao,_ah, _df, _irregularNouns = {
"addendum":"addenda",
"alga":"algae",
"alumna":"alumnae",
"apparatus":"apparatuses",
"appendix":"appendices",
"bacillus":"bacilli",
"bacterium":"bacteria",
"beau":"beaux",
"bison":"bison",
"bureau":"bureaus",
"child":"children",
"corps":"corps",
"corpus":"corpora",
"curriculum":"curricula",
"datum":"data",
"deer":"deer",
"die":"dice",
"diagnosis":"diagnoses",
"erratum":"errata",
"fireman":"firemen",
"focus":"focuses",
"foot":"feet",
"genus":"genera",
"goose":"geese",
"index":"indices",
"louse":"lice",
"man":"men",
"matrix":"matrices",
"means":"means",
"medium":"media",
"memo":"memos",
"memorandum":"memoranda",
"moose":"moose",
"mouse":"mice",
"nebula":"nebulae",
"ovum":"ova",
"ox":"oxen",
"person":"people",
"radius":"radii",
"series":"series",
"sheep":"sheep",
"scissors":"scissors",
"species":"species",
"stratum":"strata",
"syllabus":"syllabi",
"tableau":"tableaux",
"that":"those",
"this":"these",
"tooth":"teeth",
"vertebra":"vertebrae",
"vita":"vitae",
"woman":"women",
"zero":"zeros"
};
/*----------------------------------------------------------------------------------------------------------------
/- define functions preventing overwriting other framework functions
/---------------------------------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------
/- private methods
/---------------------------------------------------------------------------------------------------------------*/
function __add_fillTemplate_ref (obj){
try {
var uid = suid();
fillTemplate.refs["ref_" + fillTemplate.refs.length] = uid;
fillTemplate.refs[uid] = obj;
fillTemplate.refs.push(obj);
return uid;
} catch (e) {
error('fillTemplate.__add_fillTemplate_ref', e);
}
}
function __and (){
try {
var len = arguments.length;
for(var a = 0; a<len; a++){
if(!arguments[a]){
return arguments[a - 1] || "";
}
}
return arguments[len - 1];
} catch (e) {
error('fillTemplate.__and', e);
}
}
function __andNotHelper (record, query, operands, index) {
try {
for (var i = 0, len = query.length; i < len; i++) {
for (var prop in query[i]) {
if (!query[i].hasOwnProperty(prop)) {
continue;
}
if (!(prop in operands
&& _subQuery(record, query[i][prop], prop, index)
|| _subQuery(record, query[i][prop], "$equals", prop, index)
)) {
return false;
}
}
}
return true;
} catch (e) {
error('where.__andNotHelper', e);
}
}
function __clean_micro_templates () {
var _micro_templates = fillTemplate._micro_templates;
for (var id in _micro_templates) {
if (!_micro_templates.hasOwnProperty(id)) { continue; }
if (!$CSS("[data-craydent-bind*='"+id+"']").length) { delete _micro_templates[id]; }
}
}
function __convert_regex_safe(reg_str) {
try {
return reg_str.replace(/\\/gi,"\\\\")
.replace(/\$/gi, "\\$")
.replace(/\//gi, "\\/")
.replace(/\^/gi, "\\^")
.replace(/\./gi, "\\.")
.replace(/\|/gi, "\\|")
.replace(/\*/gi, "\\*")
.replace(/\+/gi, "\\+")
.replace(/\?/gi, "\\?")
.replace(/\!/gi, "\\!")
.replace(/\{/gi, "\\{")
.replace(/\}/gi, "\\}")
.replace(/\[/gi, "\\[")
.replace(/\]/gi, "\\]")
.replace(/\(/gi, "\\(")
.replace(/\)/gi, "\\)")
.replace('\n','\\n');
} catch (e) {
error('__convert_regex_safe', e);
}
}
function __count(arr){
try {
return arr.length;
} catch (e) {
error('fillTemplate.count', e);
}
}
function __dup (old) {
try {
for (var prop in old){
if (!old.hasOwnProperty(prop)) { continue; }
this[prop] = old[prop];
}
} catch (e) {
error('__dup', e);
}
}
function __enum(obj, delimiter, prePost){
try {
delimiter = delimiter || ", ";
prePost = prePost || ["",""];
var props = [],
str = "";
if ($c.isArray(obj)) {
props = obj.slice(0);
}
if ($c.isObject(obj)) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
props.push(prop);
}
}
}
for (var i = 0, len = props.length; i < len; i++) {
var pre = prePost[0].replace_all(['{ENUM_VAR}','{ENUM_VAL}'],[props[i],obj[props[i]]]),
post = prePost[1].replace_all(['{ENUM_VAR}','{ENUM_VAL}'],[props[i],obj[props[i]]]);
str += pre + props[i] + post + delimiter;
}
return str.slice(0,-1*delimiter.length);
} catch (e) {
error('fillTemplate.enum', e);
}
}
function __interpreter (template, obj) {
try {
var codeBlock = /\$\{if .*?\}([\s\S]*)\$\{end_if\}/g.exec(template),
ifb = "${if(",
efb = "${end_if}";
// if (!codeBlock) {
// return template;
// }
// codeBlock = codeBlock[0];
template = template.replace_all(['${if (',') }'],['${if(',')}']);
var ifcount = 0;
var efcount = 0;
var ifindex = template.indexOf(ifb),
efindex = template.indexOf(efb);
if (ifindex == -1) {
return template;
}
//noinspection CommaExpressionJS
ifcount++, efcount++;
var before = template.substring(0,ifindex);
template = template.substring(ifindex);
ifindex = 0;
var blockstart = template.indexOf(')}'),
cond = template.substring(5, blockstart).strip();
while (ifcount == 1 || ifcount != efcount) {
ifindex = template.indexOf(ifb,ifindex+1);
if (ifindex > -1) {
if (ifindex < efindex) {
ifcount++;
} else {
efcount++;
efindex = template.indexOf(efb,efindex+1);
}
} else {
efindex++;
break;
}
}
if (ifcount == 1) {
efindex = template.indexOf(efb);
}
var block = template.substring(blockstart + 2, efindex),
statement = template.substring(0,efindex + efb.length);
if (cond.contains('${')) {
cond = fillTemplate(cond.replace_all(['${','}'],['"${','}"']), obj);
}
if(!tryEval(cond)) {
template = before + template.replace(statement, '');
} else {
// template = before + template.replace(block, __interpreter(block,obj));
template = before + template.replace(statement, __interpreter(block,obj));
}
return __interpreter(template,obj);
} catch (e) {
error('fillTemplate.interpreter', e);
}
}
function __logic_parser (code, obj, bind) {
if (!code) {
return "";
}
var ttc = $c.TEMPLATE_TAG_CONFIG, indexes = [], logic = {};
code = code.replace_all(ttc.IGNORE_CHARS,['']);
$c.eachProperty(ttc, function (value) {
if (!value.begin) { return; }
var index = code.indexOfAlt(value.begin);
indexes.push(index);
logic[index] = value;
});
var index = Math.min.apply(Math,indexes.condense([-1]));
if (!logic[index]) { return code; }
return code.substring(0,index) + logic[index].parser(code.substring(index),obj, bind);
}
function __observe_helper (obj, callback, acceptList, parent) {
try {
if ($c.isObject(obj)) { return observe(obj, callback, acceptList, parent); }
if (!$c.isArray(obj)) { return; }
for (var i = 0, len = obj.length; i < len; i++) {
if (!$c.isObject(obj[i])) { continue; }
observe(obj[i], callback, acceptList, parent);
}
} catch(e) {
error('observe.observe_helper', e);
}
}
function __on_observable_change (changes) {
try {
var change = changes[0], obj = change.object, prop = change.name, value = change.oldValue;
var _observing = fillTemplate._observing,
_micro_templates = fillTemplate._micro_templates;
// change values
if (obj[prop] != value) {
var id_index = _observing.indexOf(obj);
var hash = _observing["hash_"+id_index],
pattern = new RegExp(hash+"[a-zA-Z0-9,]*\."+prop+";?|$"),
//nodes = $CSS("[data-craydent-bind*='"+hash+"."+prop+"']");
nodes = Array.prototype.slice.call($CSS("[data-craydent-bind*='"+hash+"']")||[]).filter(function(node){
return pattern.test(node.getAttribute("data-craydent-bind"));
});
if (!$CSS("[data-craydent-bind*='"+hash+"']").length) {
delete _observing["hash_" + id_index];
return;
}
for (var i = 0, len = nodes.length; i < len; i++) {
if (nodes[i].isOrphan()) { continue; }
var id = nodes[i].getAttribute("data-craydent-bind").split(":")[0],
tobj = $c.getProperty(_observing,"parents_"+id_index + ".0") || obj;
nodes[i].replace(fillTemplate(_micro_templates[id].template.replace_all("${craydent_bind}",hash),tobj).toDomElement());
}
}
} catch(e) {
error('observe.on_observable_change', e);
}
}
function __or (){
try {
for(var a = 0, len = arguments.length; a<len; a++){
if(arguments[a]){
return arguments[a];
}
}
return "";
} catch (e) {
error('fillTemplate.__or', e);
}
}
function __processBlocks (start, end, code, lookups) {
lookups = lookups || {};
var blocks = [], sindexes = [], sindex = 0, eindexes = [], eindex = 0;
while ((sindex = code.indexOfAlt(start, sindex)) != -1 && (eindex = code.indexOfAlt(end, eindex)) != -1) {
sindex != -1 && (sindexes.push(sindex), sindex++);
eindex != -1 && (eindexes.push(eindex), eindex++);
}
// if true syntax error, start end missmatch
if (sindexes.length != eindexes.length) {
blocks.push({id: uid, block: "", body:"", code: code});
return blocks;
}
var j, pairs = OrderedList([], function (a, b) {
if (a.end < b.end) { return -1; }
if (a.end > b.end) { return 1; }
return 0;
});
j = 0;
while (j < sindexes.length) {
var e = 0;
while (eindexes[0] > sindexes[e]) {
e++;
}
e--;
pairs.add({begin: sindexes[e], end: eindexes[0]});
sindexes.removeAt(e);
eindexes.removeAt(0);
}
var endlength = code.match(end)[0].length;
for (var k = 0, len = pairs.size(); k < len; k++) {
var uid = "##" + suid() + "##",
block = code.slice(pairs[k].begin, pairs[k].end + endlength),
beginLength = block.match(start)[0].length,
body = code.slice(pairs[k].begin + beginLength, pairs[k].end);
code = code.replace(block, uid);
blocks.push({id: uid, block: block, body: body, code: code});
lookups[uid] = block;
for (var i = k + 1; i < len; i++) {
var offset = block.length - uid.length;
pairs[i].end -= offset;
if (pairs[i].begin > pairs[k].end) {
pairs[i].begin -= offset;
}
}
}
return blocks.reverse();
}
function __parseArithmeticExpr (doc,expr,field) {
try {
var value;
switch (field) {
case "$add":
value = 0;
for (var i = 0, len = expr["$add"].length; i < len; i++) {
value += __processExpression(doc, expr["$add"][i]);
}
return value;
case "$subtract":
return __processExpression(doc, expr["$subtract"][0]) - __processExpression(doc, expr["$subtract"][1]);
case "$multiply":
value = 1;
for (var i = 0, len = expr["$multiply"].length; i < len; i++) {
value *= __processExpression(doc, expr["$multiply"][i]);
}
return value;
case "$divide":
return __processExpression(doc, expr["$divide"][0]) / __processExpression(doc, expr["$divide"][1]);
case "$mod":
return __processExpression(doc, expr["$mod"][0]) % __processExpression(doc, expr["$mod"][1]);
}
} catch (e) {
error('aggregate.__parseArithmeticExpr', e);
}
}
function __parseArrayExpr (doc,expr,field) {
try {
switch (field) {
case "$size":
return (__processExpression(doc, expr, field) || []).length;
}
} catch (e) {
error('aggregate.__parseArrayExpr', e);
}
}
function __parseBooleanExpr (doc,expr,field) {
try {
var arr = [];
switch (field) {
case "$and":
arr = expr["$and"];
for (var i = 0, len = arr.length; i < len; i++) {
if (!__processExpression(doc, expr[i])) {
return false;
}
}
return true;
case "$or":
arr = expr["$or"];
for (var i = 0, len = arr.length; i < len; i++) {
if (__processExpression(doc, expr[i])) {
return true;
}
}
return false;
case "$not":
arr = expr["$not"];
return !__processExpression(doc, expr[0]);
}
} catch (e) {
error('aggregate.__parseBooleanExpr', e);
}
}
function __parseComparisonExpr (doc,expr,field) {
try {
var sortOrder = [
undefined,
null,
Number,
typeof Symbol != "undefined" ? Symbol : "Symbol",
String,
Object,
Array,
typeof BinData != "undefined" ? BinData : "BinData",
typeof ObjectId != "undefined" ? ObjectId : "ObjectId",
Boolean,
Date,
typeof Timestamp != "undefined" ? Timestamp : "Timestamp",
RegExp],
value1 = __processExpression(doc, expr[field][0]),
value2 = __processExpression(doc, expr[field][1]),
cmp = null;
if (value1 == value2) { cmp = 0; }
if (value1 < value2) { cmp = -1; }
if (value1 > value2) { cmp = 1; }
if (isNull(cmp)) {
value1 = sortOrder.indexOf([null, undefined].contains(value1) ? value1 : value1.constructor);
value2 = sortOrder.indexOf([null, undefined].contains(value2) ? value2 : value2.constructor);
if (value1 < value2) { cmp = -1; }
if (value1 > value2) { cmp = 1; }
}
switch (field) {
case "$cmp":
return cmp;
case "$eq":
return cmp === 0;
case "$gt":
return cmp === 1;
case "$gte":
return cmp === 1 || cmp === 0;
case "$lt":
return cmp === -1;
case "$lte":
return cmp === -1 || cmp === 0;
case "$ne":
return cmp !== 0;
}
} catch (e) {
error('aggregate.__parse', e);
}
}
function __parseCond(doc,expr){
try {
if (!$c.isObject(expr) || !expr['$cond']) {
return expr;
}
// parse $cond
var condition = expr['$cond'],
boolExpression,
thenStatement,
elseStatement;
if ($c.isArray(condition)) {
boolExpression = condition[0];
thenStatement = condition[1];
elseStatement = condition[2];
} else {
boolExpression = condition["if"];
thenStatement = condition["then"];
elseStatement = condition["else"];
}
//return [doc].where(boolExpression).length ? thenStatement : elseStatement;
return __processExpression(doc, boolExpression) ? thenStatement : elseStatement;
} catch (e) {
error('aggregate.__parseCond', e);
}
}
function __parseConditionalExpr (doc,expr,field) {
try {
switch (field) {
case "$cond":
return __parseCond(doc, expr);
case "$ifNull":
var value = __processExpression(doc, expr["$ifNull"][0]);
return isNull(value) ? __processExpression(doc, expr["$ifNull"][1]) : value;
}
} catch (e) {
error('aggregate.__parseConditionExpr', e);
}
}
function __parseDateExpr (doc,expr,field) {
var dt = __processExpression(doc, expr[field]);
try {
switch (field) {
case "$dayOfYear":
return dt.getDayOfYear();
case "$dayOfMonth":
return dt.getDate();
case "$dayOfWeek":
return dt.getDay() + 1;
case "$year":
return dt.getFullYear();
case "$month":
return dt.getMonth() + 1;
case "$week":
return dt.getWeek();
case "$hour":
return dt.getHours();
case "$minute":
return dt.getMinutes();
case "$second":
return dt.getSeconds();
case "$millisecond":
return dt.getMilliseconds();
case "$dateToString":
dt = __processExpression(doc, expr[field].date);
return dt.format(expr[field].format)
}
} catch (e) {
error('aggregate.__parseDateExpr', e);
}
}
function __parseSetExpr (doc,expr,field) {
try {
switch (field) {
case "$setEquals":
for (var i = 1, len = expr[field].length; i < len; i++) {
var set1 = $c.duplicate(__processExpression(doc, expr[field][i - 1])),
set2 = $c.duplicate(__processExpression(doc, expr[field][i]));
if (!$c.isArray(set1) || !$c.isArray(set2)){
//noinspection ExceptionCaughtLocallyJS
throw "Exception: All operands of $setEquals must be arrays. One argument is of type: " +
(typeof (!$c.isArray(set1) ? set1 : set2)).captialize();
}
set1.toSet();
set2.toSet();
if (set1.length != set2.length) { return false; }
for (var j = 0, jlen = set1.length; j < jlen; j++) {
if (!set2.contains(set1[j])) { return false; }
}
}
return true;
case "$setIntersection":
var rtnSet = $c.duplicate(__processExpression(doc, expr[field][0])),
errorMessage = "Exception: All operands of $setIntersection must be arrays. One argument is of type: ";
if(!$c.isArray(rtnSet)) {
//noinspection ExceptionCaughtLocallyJS
throw errorMessage + (typeof rtnSet).captialize();
}
rtnSet.toSet();
for (var i = 1, len = expr[field].length; i < len; i++) {
var set1 = $c.duplicate(__processExpression(doc, expr[field][i]));
if (!$c.isArray(set1)){
//noinspection ExceptionCaughtLocallyJS
throw errorMessage + + (typeof set1).captialize();
}
set1.toSet();
if (set1.length < rtnSet.length) {
var settmp = set1;
set1 = rtnSet;
rtnSet = settmp;
}
for (var j = 0; j < rtnSet.length; j++) {
if (!set1.contains(rtnSet[j])) {
rtnSet.removeAt(j);
j--;
}
}
if (!rtnSet.length) { return rtnSet; }
}
return rtnSet;
case "$setUnion":
var rtnSet = $c.duplicate(__processExpression(doc, expr[field][0])),
errorMessage = "Exception: All operands of $setUnion must be arrays. One argument is of type: ";
if(!$c.isArray(rtnSet)) {
//noinspection ExceptionCaughtLocallyJS
throw errorMessage + (typeof rtnSet).captialize();
}
//rtnSet.toSet();
for (var i = 1, len = expr[field].length; i < len; i++) {
var arr = $c.duplicate(__processExpression(doc, expr[field][i]));
if (!$c.isArray(arr)){
//noinspection ExceptionCaughtLocallyJS
throw errorMessage + + (typeof arr).captialize();
}
rtnSet = rtnSet.concat(arr);
}
return rtnSet.toSet();
case "$setDifference":
var arr1 = $c.duplicate(__processExpression(doc, expr[field][0])),
arr2 = $c.duplicate(__processExpression(doc, expr[field][1])),
rtnSet = [];
if (!$c.isArray(arr1) || !$c.isArray(arr2)){
//noinspection ExceptionCaughtLocallyJS
throw "Exception: All operands of $setEquals must be arrays. One argument is of type: " +
(typeof (!$c.isArray(arr1) ? arr1 : arr2)).captialize();
}
for (var i = 0, len = arr1.length; i < len; i++) {
var item = arr1[i];
if (!arr2.contains(item) && !rtnSet.contains(item)) {
rtnSet.push(item);
}
}
return rtnSet;
case "$setIsSubset":
var arr1 = $c.duplicate(__processExpression(doc, expr[field][0])),
arr2 = $c.duplicate(__processExpression(doc, expr[field][1])),
rtnSet = [];
if (!$c.isArray(arr1) || !$c.isArray(arr2)){
//noinspection ExceptionCaughtLocallyJS
throw "Exception: All operands of $setEquals must be arrays. One argument is of type: " +
(typeof (!$c.isArray(arr1) ? arr1 : arr2)).captialize();
}
return $c.isSubset(arr1,arr2);
case "$anyElementTrue":
var arr1 = $c.duplicate(__processExpression(doc, expr[field][0])),
falseCondition = [undefined,null,0,false];
for (var i = 0, len = arr1.length; i < len; i++) {
var item = arr1[i];
if (!falseCondition.contains(item)) {
return true;
}
}
return false;
case "$allElementsTrue":
var arr1 = $c.duplicate(__processExpression(doc, expr[field][0])),
falseCondition = [undefined,null,0,false];
for (var i = 0, len = arr1.length; i < len; i++) {
var item = arr1[i];
if (falseCondition.contains(item)) {
return false;
}
}
return true;
}
} catch (e) {
error('aggregate.__parseSetExpr', e);
}
}
function __parseStringExpr (doc,expr,field) {
try {
switch (field) {
case "$concat":
var value = "";
for (var i = 0, len = expr["$concat"].length; i < len; i++) {
value += __processExpression(doc, expr["$concat"][i]);
}
return value;
case "$substr":
var index = expr["$substr"][1], length = expr["$substr"][2] < 0 ? undefined : expr["$substr"][2];
return __processExpression(doc, expr["$substr"][0]).substr(index, length);
case "$toLower":
return (__processExpression(doc, expr["$toLower"]) || "").toLowerCase();
case "$toUpper":
return (__processExpression(doc, expr["$toLower"]) || "").toUpperCase();
case "$strcasecmp":
var value1 = (__processExpression(doc, expr["$strcasecmp"][0]) || "").toString(),
value2 = (__processExpression(doc, expr["$strcasecmp"][1]) || "").toString();
if (value1 == value2) {
return 0;
}
if (value1 < value2) {
return -1;
}
if (value1 > value2) {
return 1;
}
}
} catch (e) {
error('aggregate.__parseStringExpr', e);
}
}
function __parseVariableExpr (doc,expr,field) {
try {
switch (field) {
case "$map":
var input = __processExpression(doc, expr[field].input),
v_as = "$" + expr[field].as,
v_in = expr[field]["in"];
for (var i = 0, len = input.length; i < len; i++) {
doc[v_as] = input[i];
input[i] = __processExpression(doc, v_in);
delete doc[v_as];
}
return input;
case "$let":
var vars = expr[field].vars,
rmProps = [], rtn = null;
for (var prop in vars) {
if (!vars.hasOwnProperty(prop)) {
continue;
}
doc["$" + prop] = __processExpression(doc, vars[prop]);
rmProps.push(prop);
}
rtn = __processExpression(doc, expr[field]["in"]);
for (var i = 0, len = rmProps.length; i < len; i++) {
delete doc[rmProps[i]];
}
return rtn;
}
} catch (e) {
error('aggregate.__parseVariableExpr', e);
}
}
function __processAccumulator (doc,accumulator,previousValue,meta) {
try {
var value = __processExpression(doc, accumulator["$sum"] || accumulator["$avg"] || accumulator["$first"] || accumulator["$last"] || accumulator["$max"] || accumulator["$min"] || accumulator["$push"] || accumulator["$addToSet"]);
switch (true) {
case !!accumulator["$sum"]:
return value + (previousValue || 0);
case !!accumulator["$avg"]:
previousValue = previousValue || {n:0,avg:0};
//if (isNull(previousValue)) {
// (previousValue = 0).n = 0;
//}
previousValue.avg = ((previousValue.avg / (previousValue.n || 1)) + value) / previousValue.n;
if (meta.length == meta.index + 1) { previousValue = previousValue.avg; }
return previousValue;
case !!accumulator["$first"]:
if(isNull(previousValue)) { previousValue = value; }
return previousValue;
case !!accumulator["$last"]:
return value;
case !!accumulator["$max"]:
return Math.max(value, (previousValue || -9007199254740991));
case !!accumulator["$min"]:
return Math.min(value, (previousValue || 9007199254740991));
case !!accumulator["$push"]:
return (previousValue || []).push(value);
case !!accumulator["$addToSet"]:
previousValue = previousValue || [];
if (!previousValue.contains(value)) { previousValue.push(value); }
return previousValue;
}
} catch (e) {
error('aggregate.__processAccumulator', e);
}
}
function __processExpression (doc,expr) {
try {
if ($c.isString(expr)) {
if (expr[0] == "$") {
expr = expr.substr(1);
}
return $c.getProperty(doc, expr.replace("$CURRENT.", ""));
} else if (!$c.isObject(expr)) {
return expr;
}
//var exprKeys = {
//
//};
for (var field in expr) {
if (!expr.hasOwnProperty(field)) {
continue;
}
var value = expr[field],
literalKeys = ["$literal"],
boolKeys = ["$and", "$or", "$not"],
setKeys = ["$setEquals", "$setIntersection", "$setUnion", "$setDifference", "$setIsSubset", "$anyElementTrue", "$allElementsTrue"],
compareKeys = ["$cmp", "$eq", "$gt", "$gte", "$lt", "$lte", "$ne"],
arithmeticKeys = ["$add", "$subtract", "$multiply", "$divide", "$mod"],
stringKeys = ["$concat", "$substr", "$toLower", "$toUpper", "$strcasecmp"],
//searchKeys = ["meta"],
arrayKeys = ["$size"],
variableKeys = ["$map", "$let"],
dateKeys = ["$dayOfYear", "$dayOfMonth", "$dayOfWeek", "$year", "$month", "$week", "$hour", "$minute", "$second", "$millisecond", "$dateToString"],
conditionalKeys = ["$cond", "$ifNull"];
//accumulatorKeys = ["$sum", "$avg", "$first", "$last", "$max", "$min", "$push", "$addToSet"];
switch (true) {
case literalKeys.contains(field):
return expr;
case boolKeys.contains(field):
return __parseBooleanExpr(doc, expr, field);
case setKeys.contains(field):
return __parseSetExpr(doc, expr, field);
case compareKeys.contains(field):
return __parseComparisonExpr(doc, expr, field);
case arithmeticKeys.contains(field):
return __parseArithmeticExpr(doc, expr, field);
case stringKeys.contains(field):
return __parseStringExpr(doc, expr, field);
//case searchKeys.contains(field):
// return __parseTextSearchExpr (doc,expr);
case arrayKeys.contains(field):
return __parseArrayExpr(doc, expr, field);
case variableKeys.contains(field):
return __parseVariableExpr(doc, expr, field);
case dateKeys.contains(field):
return __parseDateExpr(doc, expr, field);
case conditionalKeys.contains(field):
return __parseConditionalExpr(doc, expr, field);
//case accumulatorKeys.contains(field):
// return __parseAccumulatorExpr(doc, expr, field);
default:
__processExpression (doc,value);
break;
}
}
} catch (e) {
error('aggregate.__parseExpression', e);
}
}
function __processGroup (docs, expr) {
try {
var _ids = expr._id, doc, i = 0, groupings = {}, results = [], meta = {index:0,length:docs.length/*,stop:false*/};
//while(doc = docs[i++]) {
for (var i = 0, len = docs.length; i < len; i++,meta.index = i) {
var doc = docs[i],result, key = "null", keys;
if (_ids) {
keys = {};
for (var prop in _ids) {
if (!_ids.hasOwnProperty(prop)) { continue; }
keys[prop] = __processExpression(doc, _ids[prop]);
}
key = JSON.stringify(keys);
}
if (!groupings[key]) {
result = groupings[key] = {_id:keys};
results.push(result);
} else {
result = groupings[key];
}
for (var prop in expr) {
if (!expr.hasOwnProperty(prop) || prop == "_id") { continue; }
result[prop] = __processAccumulator(doc, expr[prop],result[prop], meta);
//if (meta.stop) { break; }
}
}
return results;
} catch (e) {
error('aggregate.__processGroup', e);
}
}
function __processStage(docs, stage) {
try {
var operator = "", value = {};
for (var opts in stage) {
if (!stage.hasOwnProperty(opts)) {
continue;
}
if (operator) {
//noinspection ExceptionCaughtLocallyJS
throw "Exception: A pipeline stage specification object must contain exactly one field.";
}
operator = opts;
value = stage[opts];
}
switch (opts) {
case "$project":
for (var i = 0, len = docs.length; i < len; i++) {
var doc = {};
for (var prop in value) {
if (!value.hasOwnProperty(prop)) {
continue;
}
if ($c.parseBoolean(value[prop])) {
doc[prop] = docs[i];
} else {
doc[prop] = __processExpression(docs[i], value[prop]);
}
}
docs.replaceAt(i, doc);
}
return docs.where({}, value);
case "$match":
return docs.where(value);
case "$redact":
return _redact(docs, value);
case "$limit":
return docs.slice(0, value);
case "$skip":
return docs.slice(value);
case "$unwind":
return _unwind(docs, value);
case "$group":
return __processGroup(docs, value);
case "$sort":
var sorter = [];
for (var prop in value) {
if (!value.hasOwnProperty(prop)) { continue; }
var pre = "";
if (value[prop] == -1) {
pre = "!";
}
sorter.push(pre+prop);
}
return docs.sortBy(sorter);
//case "$geoNear":
// break;
case "$out":
var rtnDocs = $c.duplicate(docs,true);
if ($c.isString(value)) {
$w[value] = rtnDocs;
} else if ($c.isArray(value)) {
value.removeAll();
$c.merge(value,rtnDocs);
}
return rtnDocs;
}
return docs;
} catch (e) {
error('aggregate.__processStage', e);
}
}
function __run_replace (reg, template, use_run, obj) {
try {
var pre = "", post = "", split_param = "|", match;
//noinspection CommaExpressionJS
use_run && (pre="RUN[",post="]", split_param=/;(?!\\)/);
while ((match = reg.exec(template)) && match[1]) {
var funcValue = [],
func = "";
funcValue = match[1].replace_all(['\\[','\\]'],['[',']']).split(split_param);
while (funcValue[0].count("{") != funcValue[0].count("}")) {
funcValue[0]+= funcValue[1]+($c.isString(split_param)?split_param:";");
funcValue.splice(1,1);
}
func = funcValue.splice(0,1)[0].strip(";");
for (var i = 0, len = funcValue.length; i < len; i++) {
if (funcValue[i].contains("${")) {
funcValue[i] = fillTemplate(funcValue[i], obj);
}
try {
//funcValue[i] = eval("(" + funcValue[i].replace_all([';\\','\\[','\\]'], [';','[',']']) + ")");
funcValue[i] = eval("(" + funcValue[i].replace_all([';\\'], [';']) + ")");
} catch (e) {}
}
template = template.contains(match[1]) ? template.replace(match[1], (match[1] = match[1].replace_all(['\\[', '\\]'], ['[', ']']))) : template;
template = template.replace_all("${" + pre + match[1] + post +"}",
$w.getProperty(func) ? $w.getProperty(func).apply(obj, funcValue) : (tryEval("("+func+")")||foo)() || "");
}
return template;
} catch (e) {
error('fillTemplate.__run_replace', e);
}
}
function _ajaxServerResponse(response) {
try {
if (response.readyState == 4 && response.status==200) {
var objResponse = {};
try {
objResponse = eval(response.responseText.trim());
} catch (e) {
objResponse = eval("(" + response.responseText.trim() + ")");
}
if (!objResponse || objResponse.hasErrors) {
return false;
}
return objResponse;
}
return false;
} catch (e) {
error("ajax._ajaxServerResponse", e);
return false;
}
}
function _condense (obj, check_values) {
try {
var skip = [], arr = [], without = false;
if (check_values && check_values.constructor == Array) {
without = true;
}
for (var i = 0, len = obj.length; i < len; i++) {
if (check_values) {
var index = i;
if (without && check_values.contains(obj[i])) {
skip.push(i);
continue;
}
if (skip.indexOf(i) != -1) {
continue;
}
while ((index = obj.indexOf(obj[i],index+1)) != -1) {
skip.push(index);
}
}
(skip.indexOf && skip.indexOf(i) || _indexOf(skip, i)) == -1 && !isNull(obj[i]) && arr.push(obj[i]);
}
return arr;
} catch (e) {
error("_condence", e);
return false;
}
}
function _copyWithProjection(projection, record) {
var copy = {}, len = 0;
projection = projection || "*";
if ($c.isString(projection)) {
projection = projection.split(',');
}
if ($c.isArray(projection)) {
if (!(len = projection.length)) {
// _copyWithProjectionHelper(record,copy);
copy = $c.duplicate(record);
return copy;
}
var arr = projection;
projection = {};
for (var i = 0; i < len; i++) {
projection[arr[i]] = 1;
}
}
for (var prop in projection) {
if (projection.has(prop)) {
if (prop == "*") {
// _copyWithProjectionHelper(record,copy);
copy = $c.duplicate(record);
} else if (record[prop] && !$c.isArray(record[prop])) {
copy[prop] = record[prop];
} else if (record[prop]) {
var del = true;
if (prop.slice(-2) == ".$") {
prop = prop.slice(0,-2);
copy[prop] = record[prop].slice(0,1);
} else if (projection[prop]['$elemMatch']) {
copy[prop] = record[prop].where(projection[prop]['$elemMatch']).slice(0,1);
} else if (projection[prop]['$slice']) {
var start = 0, length = $c.isInt(projection[prop]['$slice']) ? projection[prop]['$slice'] : 0;
if ($c.isArray(projection[prop]['$slice'])) {
start = projection[prop]['$slice'][0];
length = projection[prop]['$slice'][1];
}
copy[prop] = record[prop].slice(start, length);
} else if (projection[prop]) {
del = false;
copy[prop] = record[prop];
}
if (del && !copy[prop].length) {
delete copy[prop];
}
} else {
copy[prop] = projection[prop];
}
}
}
return copy;
}
function _copyWithProjectionHelper(record,copy) {
for (var prop in record) {
if (record.has(prop)) {
copy[prop] = record[prop];
}
}
}
function _craydentSelector (by, overwrite, object, single) {
try {
if (!object || object === true) {
return undefined;
}
var elem = $d[by](object);
if (single) {
return ((elem && ((elem.length && elem[0]) || elem)) || $w[overwrite](object)[0]);
}
return (elem || $w[overwrite](object));
} catch (e) {
error('_craydentSelector', e);
}
}
function _dataset (){
try {
var attributes = this.attributes,
ds = {};
for (var i in attributes) {
if (!attributes.hasOwnProperty(i)) { continue; }
var attribute = attributes[i];
if (attribute.name.indexOf("data-") == 0) {
ds[attribute.name.substring(5)] = attribute.value;
}
}
return ds;
} catch (e) {
error("DOM._dataset", e);
}
}
function _defineFunction (name, func, override) {
try {
var args = _getFuncArgs(func),
fstr = func.toString().replace(/this/g