diff --git a/css/d3.css b/css/d3.css index 10e8081..f4ab55a 100644 --- a/css/d3.css +++ b/css/d3.css @@ -38,3 +38,14 @@ path.arc { .link.target { stroke: #2ca02c; } + +d3 { + display: block; + max-width: 600px; + height: 100%; + margin: auto; +} + +svg text { + font-size: 1.4em; +} \ No newline at end of file diff --git a/js/controllers/DepsCtrl.js b/js/controllers/DepsCtrl.js index b31e904..80c4278 100644 --- a/js/controllers/DepsCtrl.js +++ b/js/controllers/DepsCtrl.js @@ -1,4 +1,6 @@ panelApp.controller('DepsCtrl', function DepsCtrl($scope, appContext) { - //$scope.deps = appContext.getDeps(); - $scope.deps = [{"name":"$provide","size":0,"imports":[]},{"name":"$rootScope","size":0,"imports":["$injector","$exceptionHandler","$parse"]},{"name":"$injector","size":0,"imports":[]},{"name":"$exceptionHandler","size":0,"imports":["$log"]},{"name":"$log","size":0,"imports":["$window"]},{"name":"$window","size":0,"imports":[]},{"name":"$parse","size":0,"imports":["$filter","$sniffer"]},{"name":"$filter","size":0,"imports":["$injector"]},{"name":"$sniffer","size":0,"imports":["$window"]},{"name":"$rootElement","size":0,"imports":[]},{"name":"$compile","size":0,"imports":["$injector","$interpolate","$exceptionHandler","$http","$templateCache","$parse","$controller","$rootScope"]},{"name":"$interpolate","size":0,"imports":["$parse"]},{"name":"$http","size":0,"imports":["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector"]},{"name":"$httpBackend","size":0,"imports":["$browser","$window","$document"]},{"name":"$browser","size":0,"imports":["$window","$log","$sniffer","$document"]},{"name":"$document","size":0,"imports":["$window"]},{"name":"$cacheFactory","size":0,"imports":[]},{"name":"$q","size":0,"imports":["$rootScope","$exceptionHandler"]},{"name":"$templateCache","size":0,"imports":["$cacheFactory"]},{"name":"$controller","size":0,"imports":["$injector","$window"]},{"name":"scriptDirective","size":0,"imports":["$injector","$exceptionHandler","$templateCache"]},{"name":"styleDirective","size":0,"imports":["$injector","$exceptionHandler"]},{"name":"ngControllerDirective","size":0,"imports":["$injector","$exceptionHandler"]},{"name":"aDirective","size":0,"imports":["$injector","$exceptionHandler"]},{"name":"ngClickDirective","size":0,"imports":["$injector","$exceptionHandler","$parse"]},{"name":"ngRepeatDirective","size":0,"imports":["$injector","$exceptionHandler"]},{"name":"inputDirective","size":0,"imports":["$injector","$exceptionHandler","$browser","$sniffer"]},{"name":"ngModelDirective","size":0,"imports":["$injector","$exceptionHandler"]},{"name":"formDirective","size":0,"imports":["$injector","$exceptionHandler"]},{"name":"ngSubmitDirective","size":0,"imports":["$injector","$exceptionHandler"]},{"name":"thing","size":0,"imports":[]},{"name":"otherThing","size":0,"imports":["thing","$http"]}]; + appContext.watchPoll(function () { + $scope.deps = appContext.getDeps(); + }); + $scope.deps = appContext.getDeps(); }); diff --git a/js/directives/d3.js b/js/directives/d3.js index d32c791..e60c8bb 100644 --- a/js/directives/d3.js +++ b/js/directives/d3.js @@ -12,9 +12,7 @@ panelApp.directive('d3', function($compile) { // Initialize Element // ------------------ - var dom = document.createElement('div'); - element.append(dom); - var div = d3.select(dom); + var div = d3.select(element[0]); // Constants // --------- @@ -28,6 +26,7 @@ panelApp.directive('d3', function($compile) { // Helpers // ------- + // generate element ids that do not have '$' var sanitize = function (key) { return key.replace('$', 'dollar') } @@ -37,6 +36,28 @@ panelApp.directive('d3', function($compile) { root: function(classes) { var map = {}; + // add "classes" with no dependencies + var exist = {}, + toAdd = []; + classes.forEach(function (cl) { + exist[cl.name] = true; + }); + classes.forEach(function (cl) { + cl.imports.forEach(function (im) { + if (!exist[im]) { + toAdd.push(im); + exist[im] = true; + } + }); + }); + toAdd.forEach(function (a) { + classes.push({ + name: a, + size: 0, + imports: [] + }); + }); + function find(name, data) { var node = map[name], i; if (!node) { @@ -94,8 +115,9 @@ panelApp.directive('d3', function($compile) { .angle(function(d) { return d.x / 180 * Math.PI; }); var svg = div.append("svg:svg") - .attr("width", w) - .attr("height", w) + .attr("preserveAspectRatio", "xMinYMin meet") + .attr("viewBox", [0, 0, w, h].join(' ')) + .attr("height", h) .append("svg:g") .attr("transform", "translate(" + rx + "," + ry + ")"); @@ -105,13 +127,16 @@ panelApp.directive('d3', function($compile) { .on("mousedown", mousedown); // Render the data whenever "val" changes + // -------------------------------------- scope.$watch('val', function (newVal, oldVal) { var classes = newVal; - if (!classes || classes.length === 0) { + if (oldVal || !classes || classes.length === 0) { return; } + //div[0].innerHTML = ''; + var nodes = cluster.nodes(packages.root(classes)), links = packages.imports(nodes), splines = bundle(links); diff --git a/js/inject/debug.js b/js/inject/debug.js index 86e07a0..784690c 100644 --- a/js/inject/debug.js +++ b/js/inject/debug.js @@ -62,13 +62,110 @@ var inject = function () { }; */ + var annotate = angular.injector().annotate; + + // not all versions of AngularJS expose annotate + if (!annotate) { + annotate = (function () { + + var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; + var FN_ARG_SPLIT = /,/; + var FN_ARG = /^\s*(_?)(.+?)\1\s*$/; + var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; + + // TODO: should I keep these assertions? + function assertArg(arg, name, reason) { + if (!arg) { + throw new Error("Argument '" + (name || '?') + "' is " + (reason || "required")); + } + return arg; + } + function assertArgFn(arg, name, acceptArrayAnnotation) { + if (acceptArrayAnnotation && angular.isArray(arg)) { + arg = arg[arg.length - 1]; + } + + assertArg(angular.isFunction(arg), name, 'not a function, got ' + + (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg)); + return arg; + } + + return function (fn) { + var $inject, + fnText, + argDecl, + last; + + if (typeof fn == 'function') { + if (!($inject = fn.$inject)) { + $inject = []; + fnText = fn.toString().replace(STRIP_COMMENTS, ''); + argDecl = fnText.match(FN_ARGS); + argDecl[1].split(FN_ARG_SPLIT).forEach(function(arg) { + arg.replace(FN_ARG, function(all, underscore, name) { + $inject.push(name); + }); + }); + fn.$inject = $inject; + } + } else if (angular.isArray(fn)) { + last = fn.length - 1; + assertArgFn(fn[last], 'fn') + $inject = fn.slice(0, last); + } else { + assertArgFn(fn, 'fn', true); + } + return $inject; + }; + }()); + } + var module = angular.module; - /* - angular.module = function () { - console.log(arguments); - return module.apply(this, arguments); + angular.module = function (moduleName) { + //console.log(arguments); + var mod = module.apply(this, arguments); + + var methods = [ + 'constant', + 'controller', + 'directive', + 'factory', + 'filter', + 'provider', + 'service', + 'value' + ]; + methods.forEach(function (met) { + var temp = mod[met]; + mod[met] = function (thingName, definition) { + var def; + if (typeof definition === 'function') { + def = annotate(definition); + } else { + def = definition.slice(0); + def.pop(); + } + debug.deps.push({ + name: thingName, + type: met, + size: def.length, + imports: def + }); + /* + console.log( + 'module: ' + moduleName, + 'type: ' + met, + thingName, + 'requires: ' + def); + */ + + return temp.apply(this, arguments); + } + }); + + //console.log(mod); + return mod; }; - */ /* angular.providerHook(function (name, path, fn) { @@ -235,7 +332,8 @@ var inject = function () { // only inject if cookie is set if (document.cookie.indexOf('__ngDebug=true') != -1) { - document.addEventListener('DOMContentLoaded', inject); + document.addEventListener('DOMContentLoaded', inject); +/* (function () { @@ -275,4 +373,5 @@ if (document.cookie.indexOf('__ngDebug=true') != -1) { } }()); +*/ } diff --git a/js/services/appContext.js b/js/services/appContext.js index c13e369..1ea4428 100644 --- a/js/services/appContext.js +++ b/js/services/appContext.js @@ -136,7 +136,8 @@ panelApp.factory('appContext', function(chromeExtension) { // get histogram data var histogram = [], - timeline; + timeline, + deps; // performance if (window.__ngDebug) { @@ -152,6 +153,7 @@ panelApp.factory('appContext', function(chromeExtension) { } }(window.__ngDebug.watchExp)); + deps = __ngDebug.deps; timeline = __ngDebug.timeline; } @@ -159,7 +161,8 @@ panelApp.factory('appContext', function(chromeExtension) { roots: rootIds, trees: trees, histogram: histogram, - timeline: timeline + timeline: timeline, + deps: deps }; }, function (data) { diff --git a/panel.html b/panel.html index f65d356..4ccb75f 100644 --- a/panel.html +++ b/panel.html @@ -120,7 +120,12 @@
- +
+

Service Dependencies

+
+ +
+