angular.module('batarang.json-tree', []).
directive('batJsonTree', ['$compile', 'inspectedApp', batJsonTreeDirective]);
var BAT_JSON_TREE_TEMPLATE = '
';
/*
* TODO: remove dependency on inspectedApp service
*/
function batJsonTreeDirective($compile, inspectedApp) {
return {
restrict: 'E',
terminal: true,
scope: {
scopeId: '=',
val: '='
},
link: jsonTreeLinkFn
};
function jsonTreeLinkFn(scope, element, attrs) {
var root = angular.element(BAT_JSON_TREE_TEMPLATE)
element.append(root);
var branches = {
'': root
};
scope.$watch('val', function (val) {
Object.
keys(val).
filter(function (key) {
return key.substr(0, 2) !== '$$';
}).
sort(byPathDepth).
forEach(function (key) {
buildDom(val[key], key);
});
}, true);
function buildDom(object, depth) {
branches[depth].html('');
if (!typeof object === 'undefined') {
return;
}
var buildBranch = function (key) {
var val = object[key];
var fullPath = depth;
if (depth) {
fullPath += '.';
}
fullPath += key;
var parentElt = angular.element('' +
'' + key + '' +
': ' +
''),
childElt;
if (val === null) {
childElt = angular.element('null');
} else if (val['~object'] || val['~array-length'] !== undefined) {
parentElt.addClass('parent');
// you can't expand an empty array
if (val['~array-length'] !== 0) {
parentElt.on('click', function () {
inspectedApp.watch(scope.scopeId, fullPath);
parentElt.addClass('expanded');
});
}
if (val['~object']) {
childElt = angular.element('Object');
} else {
childElt = angular.element(
'Array[' +
val['~array-length'] +
']');
}
} else {
// TODO: what doe sregex look like?
if (typeof val === 'string') {
val = '"' + val + '"';
}
childElt = angular.element(
'' +
val +
'');
}
parentElt.append(childElt);
branches[fullPath] = childElt;
return parentElt;
};
var properties;
if (object instanceof Array) {
properties = object.map(function (item, i) {
return i;
});
} else if (object != null) {
properties = Object.keys(object);
} else {
properties = [];
}
properties.
map(buildBranch).
forEach(function (elt) {
branches[depth].append(elt);
});
};
}
}
function byPathDepth(a, b) { // sort '' first
if (a === '') {
return -1;
} else if (b === '') {
return 1;
} else { // sort by tree depth
return a.split('.').length - b.split('.').length;
}
}