major overhaul

test-unit-sauce
Brian Ford 11 years ago
parent 3800d92d71
commit 4682d4baf2

@ -37,6 +37,12 @@ body {
margin: 0;
}
bat-scope-tree .selected {
font-weight: bold;
text-decoration: underline;
color: #333;
}
/*
* Slider widget style based on jquery-ui-bootstrap
* http://addyosmani.github.com/jquery-ui-bootstrap

@ -1,4 +1,4 @@
panelApp.controller('DepsCtrl', function DepsCtrl($scope, appDeps, poll) {
angular.module('panelApp').controller('DepsCtrl', function DepsCtrl($scope, appDeps) {
$scope.$on('poll', function () {
appDeps.get(function (deps) {
$scope.$apply(function () {

@ -1,15 +1,18 @@
panelApp.controller('ModelCtrl', function ModelCtrl($scope, appContext, appModel, poll) {
angular.module('panelApp').controller('ModelCtrl', function ModelCtrl($scope, appContext, appModel) {
$scope.inspect = function () {
appContext.inspect(this.val.id);
};
$scope.select = function () {
$scope.selectedScope = this.val.id;
};
// TODO: fix this
$scope.edit = function () {
appContext.executeOnScope(this.val.id, function (scope, elt, args) {
scope[args.name] = args.value;
scope.$apply();
scope.$apply(function () {
scope[args.name] = args.value;
});
}, {
name: this.key,
value: JSON.parse(this.item)
@ -17,9 +20,17 @@ panelApp.controller('ModelCtrl', function ModelCtrl($scope, appContext, appModel
};
$scope.roots = [];
$scope.model = null;
$scope.selectedRoot = null;
$scope.selectedScope = null;
$scope.enableInspector = appModel.enableInspector;
$scope.$on('poll', function () {
// get the list of root scopes
appModel.getRootScopes(function (rootScopes) {
$scope.$apply(function () {
$scope.roots = rootScopes;
@ -28,13 +39,30 @@ panelApp.controller('ModelCtrl', function ModelCtrl($scope, appContext, appModel
} else if (!$scope.selectedRoot) {
$scope.selectedRoot = $scope.roots[0];
}
if ($scope.selectedRoot && !$scope.selectedScope) {
$scope.selectedScope = $scope.selectedRoot;
}
});
});
appModel.getModelTree($scope.selectedRoot, function (tree) {
$scope.$apply(function () {
$scope.tree = tree;
// get scope tree
if ($scope.selectedRoot) {
appModel.getScopeTree($scope.selectedRoot, function (tree) {
$scope.$apply(function () {
$scope.tree = tree;
});
});
});
}
// get models on the selected scope
if ($scope.selectedScope) {
appModel.getModel($scope.selectedScope, function (model) {
$scope.$apply(function () {
$scope.model = model;
});
});
}
});
});

@ -1,4 +1,4 @@
panelApp.controller('OptionsCtrl', function OptionsCtrl($scope, appInfo, appHighlight) {
angular.module('panelApp').controller('OptionsCtrl', function OptionsCtrl($scope, appInfo, appHighlight) {
$scope.debugger = {
scopes: false,

@ -1,4 +1,4 @@
panelApp.controller('PerfCtrl', function PerfCtrl($scope, appContext, appPerf, appModel, appWatch, filesystem, poll) {
angular.module('panelApp').controller('PerfCtrl', function PerfCtrl($scope, appContext, appPerf, appModel, appWatch, filesystem) {
$scope.histogram = [];

@ -1,6 +1,6 @@
// D3 visualization
// TODO: D3 as a service
panelApp.directive('batD3', function () {
angular.module('panelApp').directive('batD3', function () {
return {
restrict: 'E',
terminal: true,

@ -1,4 +1,4 @@
panelApp.directive('batJsonTree', function($compile) {
angular.module('panelApp').directive('batJsonTree', function($compile) {
return {
restrict: 'E',
terminal: true,
@ -12,29 +12,53 @@ panelApp.directive('batJsonTree', function($compile) {
var buildDom = function (object) {
var html = '';
if (object == undefined) {
html += 'null';
var prop;
if (object === undefined) {
html += '<i>undefined</i>';
} else if (object === null) {
html += '<i>null</i>';
} else if (object instanceof Array) {
var i;
html += '<div class="scope-branch">[';
for (i = 0; i < object.length; i++) {
html += buildDom(object[i]) + ', ';
html += '<div class="scope-branch">[ ';
if (object.length > 0) {
html += buildDom(object[i]);
for (i = 1; i < object.length; i++) {
html += ',' + buildDom(object[i]);
}
}
html += ']</div>';
} else if (object instanceof Object) {
html += ' { ';
for (prop in object) {
if (object.hasOwnProperty(prop)) {
html += '<div class="scope-branch">' + prop + ': ' + buildDom(object[prop]) + '</div>';
}
}
html += ' } ';
} else {
html += '<span>' + object.toString() + '</span>';
}
return html;
};
var isEmpty = function (object) {
var prop;
for (prop in object) {
if (object.hasOwnProperty(prop)) {
return false;
}
}
return true;
};
scope.$watch('val', function (newVal, oldVal) {
element.html(buildDom(newVal));
if (newVal === null) {
element.html('<div class="alert alert-info">Select a scope to view its models.</div>');
} else if (isEmpty(newVal)) {
element.html('<pre>{ This scope has no models }</pre>');
} else {
element.html('<pre>' + buildDom(newVal) + '</pre>');
}
});
}
};

@ -1,43 +0,0 @@
panelApp.directive('batModelTree', function ($compile) {
// make toggle settings persist across $compile
var modelState = {};
var scopeState = {};
return {
restrict: 'E',
terminal: true,
scope: {
val: '=',
edit: '=',
inspect: '='
},
link: function (scope, element, attrs) {
// this is more complicated then it should be
// see: https://github.com/angular/angular.js/issues/898
element.append(
'<div class="scope-branch">' +
'<a href ng-click="inspect()">Scope ({{val.id}})</a>' +
'<span ng-show="val.children.length"> | <a href ng-click="scopeState[val.id] = !scopeState[val.id]">scopes</a></span>' +
'<span ng-show="val.locals"> | <a href ng-click="modelState[val.id] = !modelState[val.id]">models</a></span>' +
'<div ng-show="modelState[val.id]">' +
'<bat-json-tree val="val.locals" ></bat-json-tree>' +
'</div>' +
'<div ng-hide="scopeState[val.id]">' +
'<div ng-repeat="child in val.children">' +
'<bat-model-tree val="child" inspect="inspect" edit="edit"></bat-model-tree>' +
'</div>' +
'</div>' +
'</div>');
var childScope = scope.$new();
childScope.modelState = modelState;
childScope.scopeState = scopeState;
$compile(element.contents())(childScope);
}
};
});

@ -0,0 +1,46 @@
angular.module('panelApp').directive('batScopeTree', function ($compile) {
// make toggle settings persist across $compile
var modelState = {};
var scopeState = {};
var selected = null;
var template =
'<div class="scope-branch">' +
'<a href ng-click="inspect()">&lt;</a> ' +
'<a href ng-click="select()" ng-class="{selected: selectedScope == val.id}">Scope ({{val.id}})</a>' +
'<div ng-repeat="child in val.children">' +
'<bat-scope-tree ' +
'val="child" ' +
'inspect="inspect" ' +
'select="select" ' +
'selected-scope="selectedScope">' +
'</bat-scope-tree>' +
'</div>' +
'</div>';
return {
restrict: 'E',
terminal: true,
scope: {
val: '=',
select: '=',
selectedScope: '=',
inspect: '='
},
link: function (scope, element, attrs) {
// this is more complicated then it should be
// see: https://github.com/angular/angular.js/issues/898
element.append(template);
var childScope = scope.$new();
childScope.select = scope.select;
//childScope.selectedScope = scope.selectedScope;
childScope.inspect = scope.inspect;
$compile(element.contents())(childScope);
}
};
});

@ -1,5 +1,5 @@
// range slider
panelApp.directive('batSlider', function($compile) {
angular.module('panelApp').directive('batSlider', function($compile) {
return {
restrict: 'E',
terminal: true,

@ -1,4 +1,4 @@
panelApp.directive('batTabs', function ($compile, $templateCache, $http) {
angular.module('panelApp').directive('batTabs', function ($compile, $templateCache, $http) {
return {
restrict: 'E',
transclude: true,

@ -1,5 +1,5 @@
// watchers tree
panelApp.directive('batWatcherTree', function($compile) {
angular.module('panelApp').directive('batWatcherTree', function($compile) {
// make toggle settings persist across $compile
var scopeState = {};

@ -1,5 +1,5 @@
// returns the first line of a multi-line string
panelApp.filter('first', function () {
angular.module('panelApp').filter('first', function () {
return function (input, output) {
return input.split("\n")[0];
};

@ -1,5 +1,5 @@
// returns the number's first 4 decimals
panelApp.filter('precision', function () {
angular.module('panelApp').filter('precision', function () {
return function (input, output) {
return input.toPrecision(4);
};

@ -1,6 +1,6 @@
// Sort watchers by time
// Used by the performance tab
panelApp.filter('sortByTime', function () {
angular.module('panelApp').filter('sortByTime', function () {
return function (input, min, max) {
var copy = input.slice(0);

@ -76,6 +76,9 @@ var inject = function () {
nu; // The new object or array
switch (typeof value) {
case 'object':
if (value instanceof HTMLElement) {
return value.innerHTML;
}
if (!value) {
return null;
}
@ -181,6 +184,73 @@ var inject = function () {
}());
}
// throttle based on _.throttle from Lo-Dash
// https://github.com/bestiejs/lodash/blob/master/lodash.js#L4625
var throttle = function (func, wait) {
var args,
result,
thisArg,
timeoutId,
lastCalled = 0;
function trailingCall() {
lastCalled = new Date();
timeoutId = null;
result = func.apply(thisArg, args);
}
return function() {
var now = new Date(),
remaining = wait - (now - lastCalled);
args = arguments;
thisArg = this;
if (remaining <= 0) {
clearTimeout(timeoutId);
timeoutId = null;
lastCalled = now;
result = func.apply(thisArg, args);
}
else if (!timeoutId) {
timeoutId = setTimeout(trailingCall, remaining);
}
return result;
};
};
var debounce = function (func, wait, immediate) {
var args,
result,
thisArg,
timeoutId;
function delayed() {
timeoutId = null;
if (!immediate) {
result = func.apply(thisArg, args);
}
}
return function() {
var isImmediate = immediate && !timeoutId;
args = arguments;
thisArg = this;
clearTimeout(timeoutId);
timeoutId = setTimeout(delayed, wait);
if (isImmediate) {
result = func.apply(thisArg, args);
}
return result;
};
};
var updateScopeModelCache = function (scope) {
debug.models[scope.$id] = getScopeLocals(scope);
debug.scopeDirty[scope.$id] = false;
};
var popover = null;
// Public API
// ==========
@ -199,14 +269,21 @@ var inject = function () {
return ids;
},
// returns null or cached scope
getModel: function (id) {
if (debug.scopeDirty[id]) {
updateScopeModelCache(debug.scopes[id]);
return debug.models[id];
}
},
getScopeTree: function (id) {
if (debug.rootScopeDirty[id] === false) {
if (debug.scopeTreeDirty[id] === false) {
return;
}
var traverse = function (sc) {
var tree = {
id: sc.$id,
locals: debug.scopes[sc.$id],
children: []
};
@ -224,9 +301,10 @@ var inject = function () {
var tree = traverse(root);
if (tree) {
debug.rootScopeDirty[id] = false;
debug.scopeTreeDirty[id] = false;
}
return tree;
},
@ -266,6 +344,241 @@ var inject = function () {
var tree = traverse(root);
return tree;
},
enable: function () {
if (popover) {
return;
}
var angular = window.angular;
popover = angular.element(
'<div style="position: fixed; left: 50px; top: 50px; z-index: 9999; background-color: #f1f1f1; box-shadow: 0 15px 10px -10px rgba(0, 0, 0, 0.5), 0 1px 4px rgba(0, 0, 0, 0.3), 0 0 40px rgba(0, 0, 0, 0.1) inset;">' +
'<div style="position: relative" style="min-width: 300px; min-height: 100px;">' +
'<div style="min-width: 100px; min-height: 50px; padding: 5px;"><pre>{ Please select a scope }</pre></div>' +
'<button style="position: absolute; top: -15px; left: -15px; cursor: move;">⇱</button>' +
'<button style="position: absolute; top: -15px; left: 10px;">+</button>' +
'<button style="position: absolute; top: -15px; right: -15px;">x</button>' +
'<style>' +
'.ng-scope.batarang-selected { border: 1px solid red; } ' +
'.bat-indent { margin-left: 20px; }' +
'</style>' +
'</div>' +
'</div>');
angular.element(window.document.body).append(popover);
var popoverContent = angular.element(angular.element(popover.children('div')[0]).children()[0]);
var dragElt = angular.element(angular.element(popover.children('div')[0]).children()[1]);
var selectElt = angular.element(angular.element(popover.children('div')[0]).children()[2]);
var closeElt = angular.element(angular.element(popover.children('div')[0]).children()[3]);
console.log(closeElt);
var currentScope = null,
currentElt = null;
function onMove (ev) {
var x = ev.clientX,
y = ev.clientY;
if (x > window.outerWidth - 100) {
x = window.outerWidth - 100;
} else if (x < 0) {
x = 0;
}
if (y > window.outerHeight - 100) {
y = window.outerHeight - 100;
} else if (y < 0) {
y = 0;
}
x += 5;
y += 5;
popover.css('left', x + 'px');
popover.css('top', y + 'px');
}
closeElt.bind('click', function () {
popover.remove();
popover = null;
});
selectElt.bind('click', bindSelectScope);
var selecting = false;
function bindSelectScope () {
if (selecting) {
return;
}
setTimeout(function () {
selecting = true;
selectElt.attr('disabled', true);
angular.element(document.body).css('cursor', 'crosshair');
angular.element(document.getElementsByClassName('ng-scope'))
.bind('click', onSelectScope)
.bind('mouseover', onHoverScope);
}, 30);
}
var hoverScopeElt = null;
function markHoverElt () {
if (hoverScopeElt) {
hoverScopeElt.addClass('batarang-selected');
}
}
function unmarkHoverElt () {
if (hoverScopeElt) {
hoverScopeElt.removeClass('batarang-selected');
}
}
function onSelectScope (ev) {
render(this);
angular.element(document.getElementsByClassName('ng-scope'))
.unbind('click', onSelectScope)
.unbind('mouseover', onHoverScope);
unmarkHoverElt();
selecting = false;
selectElt.attr('disabled', false);
angular.element(document.body).css('cursor', '');
hovering = false;
}
var hovering = false;
function onHoverScope (ev) {
if (hovering) {
return;
}
hovering = true;
var that = this;
setTimeout(function () {
unmarkHoverElt();
hoverScopeElt = angular.element(that);
markHoverElt();
hovering = false;
render(that);
}, 100);
}
function onUnhoverScope (ev) {
angular.element(this).css('border', '');
}
dragElt.bind('mousedown', function (ev) {
ev.preventDefault();
rendering = true;
angular.element(document).bind('mousemove', onMove);
});
angular.element(document).bind('mouseup', function () {
angular.element(document).unbind('mousemove', onMove);
setTimeout(function () {
rendering = false;
}, 120);
});
function renderTree (data) {
var tree = angular.element('<div class="bat-indent"></div>');
angular.forEach(data, function (val, key) {
var toAppend;
if (val === undefined) {
toAppend = '<i>undefined</i>';
} else if (val === null) {
toAppend = '<i>null</i>';
} else if (val instanceof Array) {
toAppend = '[ ... ]';
} else if (val instanceof Object) {
toAppend = '{ ... }';
} else {
toAppend = val.toString();
}
if (data instanceof Array) {
toAppend = '<div>' +
toAppend +
((key===data.length-1)?'':',') +
'</div>';
} else {
toAppend = '<div>' +
key +
': ' +
toAppend +
(key!==0?'':',') +
'</div>';
}
toAppend = angular.element(toAppend);
if (val instanceof Array || val instanceof Object) {
function recur () {
toAppend.unbind('click', recur);
toAppend.html('');
toAppend
.append(angular.element('<span>' +
key + ': ' +
((val instanceof Array)?'[':'{') +
'<span>').bind('click', collapse))
.append(renderTree(val))
.append('<span>' + ((val instanceof Array)?']':'}') + '<span>');
}
function collapse () {
toAppend.html('');
toAppend.append(angular.element('<div>' +
key +
': ' +
((val instanceof Array)?'[ ... ]':'{ ... }') +
'</div>').bind('click', recur));
}
toAppend.bind('click', recur);
}
tree.append(toAppend);
});
return tree;
}
var isEmpty = function (object) {
var prop;
for (prop in object) {
if (object.hasOwnProperty(prop)) {
return false;
}
}
return true;
};
var objLength = function (object) {
var prop, len = 0;
for (prop in object) {
if (object.hasOwnProperty(prop)) {
len += 1;
}
}
return len;
};
var rendering = false;
var render = function (elt) {
if (rendering) {
return;
}
rendering = true;
setTimeout(function () {
var scope = angular.element(elt).scope();
rendering = false;
if (scope === currentScope) {
return;
}
currentScope = scope;
currentElt = elt;
var models = getScopeLocals(scope);
popoverContent.children().remove();
if (isEmpty(models)) {
popoverContent.append(angular.element('<i>This scope has no models</i>'));
} else {
popoverContent.append(renderTree(models));
}
}, 100);
};
}
};
@ -282,14 +595,16 @@ var inject = function () {
watchPerf: {},
applyPerf: {},
// map of scope.$ids --> model objects
// map of scope.$ids --> $scope objects
scopes: {},
// map of scope.$ids --> model objects
models: {},
// map of $ids --> bools
scopeDirty: {},
// map of $ids --> refs to root scopes
// map of $ids --> refs to $rootScope objects
rootScopes: {},
// map of $ids --> bools
rootScopeDirty: {},
scopeTreeDirty: {},
deps: []
};
@ -363,7 +678,7 @@ var inject = function () {
});
$provide.decorator('$rootScope', function ($delegate) {
var watchFnToHumanReadableString = function (fn) {
if (fn.exp) {
return fn.exp.trim();
@ -398,7 +713,7 @@ var inject = function () {
$delegate.__proto__.$watch = function (watchExpression, applyFunction) {
var thatScope = this;
var watchStr = watchFnToHumanReadableString(watchExpression);
if (!debug.watchPerf[watchStr]) {
debug.watchPerf[watchStr] = {
time: 0,
@ -442,8 +757,8 @@ var inject = function () {
var start = performance.now();
var ret = unpatchedApplyFunction.apply(this, arguments);
var end = performance.now();
debug.scopeDirty[this.$id] = true;
debug.scopes[thatScope.$id] = getScopeLocals(thatScope);
//TODO: move these checks out of here and into registering the watcher
if (!debug.applyPerf[applyStr]) {
debug.applyPerf[applyStr] = {
@ -453,7 +768,6 @@ var inject = function () {
}
debug.applyPerf[applyStr].time += (end - start);
debug.applyPerf[applyStr].calls += 1;
debug.rootScopeDirty[thatScope.$root.$id] = true;
return ret;
};
}
@ -469,12 +783,16 @@ var inject = function () {
if (debug.watchers[this.$id]) {
delete debug.watchers[this.$id];
}
if (debug.models[this.$id]) {
delete debug.models[this.$id];
}
if (debug.scopes[this.$id]) {
delete debug.scopes[this.$id];
}
return _destroy.apply(this, arguments);
};
// patch $new
// ----------
var _new = $delegate.__proto__.$new;
@ -483,6 +801,7 @@ var inject = function () {
var ret = _new.apply(this, arguments);
if (ret.$root) {
debug.rootScopes[ret.$root.$id] = ret.$root;
debug.scopeTreeDirty[ret.$root.$id] = true;
}
// create empty watchers array for this scope
@ -490,11 +809,23 @@ var inject = function () {
debug.watchers[ret.$id] = [];
}
debug.rootScopeDirty[ret.$root.$id] = true;
debug.scopes[ret.$id] = ret;
debug.scopeDirty[ret.$id] = true;
return ret;
};
// patch $digest
// -------------
var _digest = $delegate.__proto__.$digest;
$delegate.__proto__.$digest = function (fn) {
var ret = _digest.apply(this, arguments);
debug.scopeDirty[this.$id] = true;
return ret;
};
// patch $apply
// ------------
var _apply = $delegate.__proto__.$apply;
@ -502,6 +833,7 @@ var inject = function () {
var start = performance.now();
var ret = _apply.apply(this, arguments);
var end = performance.now();
debug.scopeDirty[this.$id] = true;
// If the debugging option is enabled, log to console
// --------------------------------------------------
@ -521,7 +853,7 @@ var inject = function () {
// Return a script element with the above code embedded in it
var script = window.document.createElement('script');
script.innerHTML = '(' + fn.toString() + '(window))';
return script;
}()));
};

@ -1 +1,6 @@
var panelApp = angular.module('panelApp', []);
// Broadcast poll events
angular.module('panelApp', []).run(function ($rootScope) {
setInterval(function () {
$rootScope.$broadcast('poll');
}, 500);
});

@ -1,5 +1,5 @@
// Service for running code in the context of the application being debugged
panelApp.factory('appContext', function (chromeExtension) {
angular.module('panelApp').factory('appContext', function (chromeExtension) {
// Public API
// ==========
@ -79,7 +79,7 @@ panelApp.factory('appContext', function (chromeExtension) {
// TODO: depreciate this; only poll from now on?
// There are some cases where you need to gather data on a once-per-bootstrap basis, for
// instance getting the version of AngularJS
// TODO: move to chromeExtension?
watchRefresh: function (cb) {
var port = chrome.extension.connect();

@ -1,5 +1,5 @@
// Service for injecting CSS into the application
panelApp.factory('appCss', function (chromeExtension) {
angular.module('panelApp').factory('appCss', function (chromeExtension) {
return {
addCssRule: function (args) {
chromeExtension.eval(function (window, args) {

@ -1,5 +1,5 @@
// Service for retrieving and caching application dependencies
panelApp.factory('appDeps', function (chromeExtension, appContext) {
angular.module('panelApp').factory('appDeps', function (chromeExtension, appContext) {
var _depsCache = [];

@ -1,5 +1,5 @@
// Service for highlighting parts of the application
panelApp.factory('appHighlight', function (appCss) {
angular.module('panelApp').factory('appHighlight', function (appCss) {
//TODO: improve look of highlighting; for instance, if an element is bound and a scope,
// you will only see the most recently applied outline

@ -1,5 +1,5 @@
// Service for running code in the context of the application being debugged
panelApp.factory('appInfo', function (chromeExtension, appContext) {
angular.module('panelApp').factory('appInfo', function (chromeExtension, appContext) {
var _versionCache = null,
_srcCache = null;

@ -1,5 +1,5 @@
// Service for highlighting parts of the application
panelApp.factory('appInspect', function (chromeExtension) {
angular.module('panelApp').factory('appInspect', function (chromeExtension) {
return {
enable: function () {
chromeExtension.eval(function (window) {

@ -1,7 +1,8 @@
// Service for running code in the context of the application being debugged
panelApp.factory('appModel', function (chromeExtension, appContext) {
angular.module('panelApp').factory('appModel', function (chromeExtension, appContext) {
var _scopeCache = {},
var _scopeTreeCache = {},
_scopeCache = {},
_rootScopeCache = [];
@ -27,18 +28,39 @@ panelApp.factory('appModel', function (chromeExtension, appContext) {
});
},
getModelTree: function (id, callback) {
// only runs callback if model has changed since last call
getModel: function (id, callback) {
if (!id) {
return;
}
chromeExtension.eval(function (window, args) {
return window.__ngDebug.getScopeTree(args.id);
return window.__ngDebug.getModel(args.id);
}, {id: id}, function (tree) {
if (tree) {
_scopeCache[id] = tree;
}
callback(_scopeCache[id]);
});
},
getScopeTree: function (id, callback) {
if (!id) {
return;
}
chromeExtension.eval(function (window, args) {
return window.__ngDebug.getScopeTree(args.id);
}, {id: id}, function (tree) {
if (tree) {
_scopeTreeCache[id] = tree;
}
callback(_scopeTreeCache[id]);
});
},
enableInspector: function (argument) {
chromeExtension.eval(function (window, args) {
return window.__ngDebug.enable();
});
}
};
});

@ -1,5 +1,5 @@
// Service for retrieving and caching performance data
panelApp.factory('appPerf', function (chromeExtension, appContext) {
angular.module('panelApp').factory('appPerf', function (chromeExtension, appContext) {
var _histogramCache = [],
_watchNameToPerf = {},

@ -1,5 +1,5 @@
// Service for running code in the context of the application being debugged
panelApp.factory('appWatch', function (chromeExtension) {
angular.module('panelApp').factory('appWatch', function (chromeExtension) {
var _watchCache = {};

@ -1,5 +1,5 @@
// abstraction layer for Chrome Extension APIs
panelApp.value('chromeExtension', {
angular.module('panelApp').value('chromeExtension', {
sendRequest: function (requestName, cb) {
chrome.extension.sendRequest({
script: requestName,

@ -1,5 +1,5 @@
// Service for exporting as JSON
panelApp.factory('filesystem', function(chromeExtension) {
angular.module('panelApp').factory('filesystem', function(chromeExtension) {
// taken from:
// http://html5-demos.appspot.com/static/html5storage/index.html#slide59

@ -1,11 +0,0 @@
// Service for broadcasting poll events
panelApp.factory('poll', function ($rootScope) {
setInterval(function () {
$rootScope.$broadcast('poll');
}, 500);
return {
setInterval: function (int) {}
};
});

@ -17,7 +17,7 @@
<script src="js/directives/d3.js"></script>
<script src="js/directives/jsonTree.js"></script>
<script src="js/directives/modelTree.js"></script>
<script src="js/directives/scopeTree.js"></script>
<script src="js/directives/slider.js"></script>
<script src="js/directives/tabs.js"></script>
<script src="js/directives/watcherTree.js"></script>
@ -36,7 +36,6 @@
<script src="js/services/appWatch.js"></script>
<script src="js/services/chromeExtension.js"></script>
<script src="js/services/filesystem.js"></script>
<script src="js/services/poll.js"></script>
<script src="js/controllers/DepsCtrl.js"></script>
<script src="js/controllers/ModelCtrl.js"></script>

@ -1,13 +1,29 @@
<div ng-controller="ModelCtrl">
<h2>Models</h2>
<div ng-show="roots.length > 1">
<label for="select-root">Root
<select
ng-options="root.toString() for root in roots"
ng-model="selectedRoot"></select>
</label>
<div class="span6">
<h2>Scopes</h2>
<div ng-show="roots.length > 1">
<label for="select-root">Root
<select
ng-options="root.toString() for root in roots"
ng-model="selectedRoot"></select>
</label>
</div>
<pre>
<bat-scope-tree
val="tree"
inspect="inspect"
select="select"
selected-scope="selectedScope"
edit="edit"></bat-scope-tree>
</pre>
</div>
<div class="span6">
<h2>Models<span ng-show="selectedScope"> for ({{selectedScope}})</span></h2>
<bat-json-tree val="model"></bat-json-tree>
</div>
<div class="span6">
<button class="btn" ng-click="enableInspector()">Enable Inspector</button>
</div>
<pre>
<bat-model-tree val="tree" inspect="inspect" edit="edit"></bat-model-tree>
</pre>
</div>

@ -0,0 +1,24 @@
files = [
JASMINE,
JASMINE_ADAPTER,
'js/lib/angular.js',
'js/lib/angular-mocks.js',
'js/panelApp.js',
'js/controllers/*.js',
'js/directives/*.js',
'js/filters/*.js',
'js/services/*.js',
'test/mock/*.js',
'test/*.js'
];
exclude = [];
autoWatch = true;
autoWatchInterval = 1;
logLevel = LOG_INFO;
logColors = true;

File diff suppressed because it is too large Load Diff

@ -0,0 +1,20 @@
<!doctype html>
<html ng-app="testApp">
<head>
<script src="angular-expose-isolate-scopes.js"></script>
<script>
angular.module('testApp', [])
.controller('TestCtrl', function ($scope) {
$scope.someArray = [];
setTimeout(function () {
$scope.$digest(function() {
$scope.someArray.push(1);
});
}, 0)
});
</script>
</head>
<body ng-controller="TestCtrl">
<my-trans-dir this="person"></my-trans-dir>
</body>
</html>

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html ng-app="myApp">
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<link rel="stylesheet" type="text/css" href="http://angular-ui.github.com/ng-grid/css/ng-grid.css" />
<style>
/*style.css*/
.gridStyle {
border: 1px solid rgb(212,212,212);
width: 400px;
height: 300px
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<script src="http://angular-ui.github.com/ng-grid/lib/ng-grid.debug.js"></script>
<script>
// main.js
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope) {
$scope.myData = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 27},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.gridOptions = { data: 'myData' };
});
</script>
</head>
<body ng-controller="MyCtrl">
<div class="gridStyle" ng-grid="gridOptions"></div>
</body>
</html>

@ -0,0 +1,25 @@
<!doctype html>
<html ng-app="testApp">
<head>
<script src="angular-expose-isolate-scopes.js"></script>
<script>
angular.module('testApp', [])
.controller('TestCtrl', function ($scope) {
$scope.person = 'bob';
$scope.other = 'john';
})
.directive('myTransDir', function () {
return {
restrict: 'E',
template: '{{that}}',
scope: {
that: '=this'
}
};
});
</script>
</head>
<body ng-controller="TestCtrl">
<my-trans-dir this="person"></my-trans-dir>
</body>
</html>

@ -0,0 +1,30 @@
<!doctype html>
<html ng-app="testApp">
<head>
<script src="angular-expose-isolate-scopes.js"></script>
<script>
angular.module('testApp', [])
.controller('TestCtrl', function ($scope) {
$scope.person = 'bob';
$scope.other = 'bob';
})
.directive('myTransDir', function () {
return {
restrict: 'E',
template: '{{that}} pre-trans' +
'<div ng-transclude></div>' +
'post-trans {{that}}',
transclude: true,
scope: {
that: '=this'
}
};
});
</script>
</head>
<body ng-controller="TestCtrl">
<my-trans-dir this="person">
this is inside
</my-trans-dir>
</body>
</html>