many ui improvements; responsive layout within the plugin, added slider for controlling range of watch expressions

test-unit-sauce
Brian Ford 12 years ago
parent 274c8cff93
commit 4035dc2c67

@ -0,0 +1,815 @@
/*!
* Bootstrap Responsive v2.0.4
*
* Copyright 2012 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world @twitter by @mdo and @fat.
*/
.clearfix {
*zoom: 1;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
.hide-text {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
.input-block-level {
display: block;
width: 100%;
min-height: 28px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.hidden {
display: none;
visibility: hidden;
}
.visible-phone {
display: none !important;
}
.visible-tablet {
display: none !important;
}
.hidden-desktop {
display: none !important;
}
@media (max-width: 767px) {
.visible-phone {
display: inherit !important;
}
.hidden-phone {
display: none !important;
}
.hidden-desktop {
display: inherit !important;
}
.visible-desktop {
display: none !important;
}
}
@media (min-width: 768px) and (max-width: 979px) {
.visible-tablet {
display: inherit !important;
}
.hidden-tablet {
display: none !important;
}
.hidden-desktop {
display: inherit !important;
}
.visible-desktop {
display: none !important ;
}
}
@media (max-width: 480px) {
.nav-collapse {
-webkit-transform: translate3d(0, 0, 0);
}
.page-header h1 small {
display: block;
line-height: 18px;
}
input[type="checkbox"],
input[type="radio"] {
border: 1px solid #ccc;
}
.form-horizontal .control-group > label {
float: none;
width: auto;
padding-top: 0;
text-align: left;
}
.form-horizontal .controls {
margin-left: 0;
}
.form-horizontal .control-list {
padding-top: 0;
}
.form-horizontal .form-actions {
padding-right: 10px;
padding-left: 10px;
}
.modal {
position: absolute;
top: 10px;
right: 10px;
left: 10px;
width: auto;
margin: 0;
}
.modal.fade.in {
top: auto;
}
.modal-header .close {
padding: 10px;
margin: -10px;
}
.carousel-caption {
position: static;
}
}
@media (max-width: 767px) {
body {
padding-right: 20px;
padding-left: 20px;
}
.navbar-fixed-top,
.navbar-fixed-bottom {
margin-right: -20px;
margin-left: -20px;
}
.container-fluid {
padding: 0;
}
.dl-horizontal dt {
float: none;
width: auto;
clear: none;
text-align: left;
}
.dl-horizontal dd {
margin-left: 0;
}
.container {
width: auto;
}
.row-fluid {
width: 100%;
}
.row,
.thumbnails {
margin-left: 0;
}
[class*="span"],
.row-fluid [class*="span"] {
display: block;
float: none;
width: auto;
margin-left: 0;
}
.input-large,
.input-xlarge,
.input-xxlarge,
input[class*="span"],
select[class*="span"],
textarea[class*="span"],
.uneditable-input {
display: block;
width: 100%;
min-height: 28px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.input-prepend input,
.input-append input,
.input-prepend input[class*="span"],
.input-append input[class*="span"] {
display: inline-block;
width: auto;
}
}
@media (min-width: 768px) and (max-width: 979px) {
.row {
margin-left: -20px;
*zoom: 1;
}
.row:before,
.row:after {
display: table;
content: "";
}
.row:after {
clear: both;
}
[class*="span"] {
float: left;
margin-left: 20px;
}
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
width: 724px;
}
.span12 {
width: 724px;
}
.span11 {
width: 662px;
}
.span10 {
width: 600px;
}
.span9 {
width: 538px;
}
.span8 {
width: 476px;
}
.span7 {
width: 414px;
}
.span6 {
width: 352px;
}
.span5 {
width: 290px;
}
.span4 {
width: 228px;
}
.span3 {
width: 166px;
}
.span2 {
width: 104px;
}
.span1 {
width: 42px;
}
.offset12 {
margin-left: 764px;
}
.offset11 {
margin-left: 702px;
}
.offset10 {
margin-left: 640px;
}
.offset9 {
margin-left: 578px;
}
.offset8 {
margin-left: 516px;
}
.offset7 {
margin-left: 454px;
}
.offset6 {
margin-left: 392px;
}
.offset5 {
margin-left: 330px;
}
.offset4 {
margin-left: 268px;
}
.offset3 {
margin-left: 206px;
}
.offset2 {
margin-left: 144px;
}
.offset1 {
margin-left: 82px;
}
.row-fluid {
width: 100%;
*zoom: 1;
}
.row-fluid:before,
.row-fluid:after {
display: table;
content: "";
}
.row-fluid:after {
clear: both;
}
.row-fluid [class*="span"] {
display: block;
float: left;
width: 100%;
min-height: 28px;
margin-left: 2.762430939%;
*margin-left: 2.709239449638298%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.row-fluid [class*="span"]:first-child {
margin-left: 0;
}
.row-fluid .span12 {
width: 99.999999993%;
*width: 99.9468085036383%;
}
.row-fluid .span11 {
width: 91.436464082%;
*width: 91.38327259263829%;
}
.row-fluid .span10 {
width: 82.87292817100001%;
*width: 82.8197366816383%;
}
.row-fluid .span9 {
width: 74.30939226%;
*width: 74.25620077063829%;
}
.row-fluid .span8 {
width: 65.74585634900001%;
*width: 65.6926648596383%;
}
.row-fluid .span7 {
width: 57.182320438000005%;
*width: 57.129128948638304%;
}
.row-fluid .span6 {
width: 48.618784527%;
*width: 48.5655930376383%;
}
.row-fluid .span5 {
width: 40.055248616%;
*width: 40.0020571266383%;
}
.row-fluid .span4 {
width: 31.491712705%;
*width: 31.4385212156383%;
}
.row-fluid .span3 {
width: 22.928176794%;
*width: 22.874985304638297%;
}
.row-fluid .span2 {
width: 14.364640883%;
*width: 14.311449393638298%;
}
.row-fluid .span1 {
width: 5.801104972%;
*width: 5.747913482638298%;
}
input,
textarea,
.uneditable-input {
margin-left: 0;
}
input.span12,
textarea.span12,
.uneditable-input.span12 {
width: 714px;
}
input.span11,
textarea.span11,
.uneditable-input.span11 {
width: 652px;
}
input.span10,
textarea.span10,
.uneditable-input.span10 {
width: 590px;
}
input.span9,
textarea.span9,
.uneditable-input.span9 {
width: 528px;
}
input.span8,
textarea.span8,
.uneditable-input.span8 {
width: 466px;
}
input.span7,
textarea.span7,
.uneditable-input.span7 {
width: 404px;
}
input.span6,
textarea.span6,
.uneditable-input.span6 {
width: 342px;
}
input.span5,
textarea.span5,
.uneditable-input.span5 {
width: 280px;
}
input.span4,
textarea.span4,
.uneditable-input.span4 {
width: 218px;
}
input.span3,
textarea.span3,
.uneditable-input.span3 {
width: 156px;
}
input.span2,
textarea.span2,
.uneditable-input.span2 {
width: 94px;
}
input.span1,
textarea.span1,
.uneditable-input.span1 {
width: 32px;
}
}
@media (min-width: 1200px) {
.row {
margin-left: -30px;
*zoom: 1;
}
.row:before,
.row:after {
display: table;
content: "";
}
.row:after {
clear: both;
}
[class*="span"] {
float: left;
margin-left: 30px;
}
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
width: 1170px;
}
.span12 {
width: 1170px;
}
.span11 {
width: 1070px;
}
.span10 {
width: 970px;
}
.span9 {
width: 870px;
}
.span8 {
width: 770px;
}
.span7 {
width: 670px;
}
.span6 {
width: 570px;
}
.span5 {
width: 470px;
}
.span4 {
width: 370px;
}
.span3 {
width: 270px;
}
.span2 {
width: 170px;
}
.span1 {
width: 70px;
}
.offset12 {
margin-left: 1230px;
}
.offset11 {
margin-left: 1130px;
}
.offset10 {
margin-left: 1030px;
}
.offset9 {
margin-left: 930px;
}
.offset8 {
margin-left: 830px;
}
.offset7 {
margin-left: 730px;
}
.offset6 {
margin-left: 630px;
}
.offset5 {
margin-left: 530px;
}
.offset4 {
margin-left: 430px;
}
.offset3 {
margin-left: 330px;
}
.offset2 {
margin-left: 230px;
}
.offset1 {
margin-left: 130px;
}
.row-fluid {
width: 100%;
*zoom: 1;
}
.row-fluid:before,
.row-fluid:after {
display: table;
content: "";
}
.row-fluid:after {
clear: both;
}
.row-fluid [class*="span"] {
display: block;
float: left;
width: 100%;
min-height: 28px;
margin-left: 2.564102564%;
*margin-left: 2.510911074638298%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.row-fluid [class*="span"]:first-child {
margin-left: 0;
}
.row-fluid .span12 {
width: 100%;
*width: 99.94680851063829%;
}
.row-fluid .span11 {
width: 91.45299145300001%;
*width: 91.3997999636383%;
}
.row-fluid .span10 {
width: 82.905982906%;
*width: 82.8527914166383%;
}
.row-fluid .span9 {
width: 74.358974359%;
*width: 74.30578286963829%;
}
.row-fluid .span8 {
width: 65.81196581200001%;
*width: 65.7587743226383%;
}
.row-fluid .span7 {
width: 57.264957265%;
*width: 57.2117657756383%;
}
.row-fluid .span6 {
width: 48.717948718%;
*width: 48.6647572286383%;
}
.row-fluid .span5 {
width: 40.170940171000005%;
*width: 40.117748681638304%;
}
.row-fluid .span4 {
width: 31.623931624%;
*width: 31.5707401346383%;
}
.row-fluid .span3 {
width: 23.076923077%;
*width: 23.0237315876383%;
}
.row-fluid .span2 {
width: 14.529914530000001%;
*width: 14.4767230406383%;
}
.row-fluid .span1 {
width: 5.982905983%;
*width: 5.929714493638298%;
}
input,
textarea,
.uneditable-input {
margin-left: 0;
}
input.span12,
textarea.span12,
.uneditable-input.span12 {
width: 1160px;
}
input.span11,
textarea.span11,
.uneditable-input.span11 {
width: 1060px;
}
input.span10,
textarea.span10,
.uneditable-input.span10 {
width: 960px;
}
input.span9,
textarea.span9,
.uneditable-input.span9 {
width: 860px;
}
input.span8,
textarea.span8,
.uneditable-input.span8 {
width: 760px;
}
input.span7,
textarea.span7,
.uneditable-input.span7 {
width: 660px;
}
input.span6,
textarea.span6,
.uneditable-input.span6 {
width: 560px;
}
input.span5,
textarea.span5,
.uneditable-input.span5 {
width: 460px;
}
input.span4,
textarea.span4,
.uneditable-input.span4 {
width: 360px;
}
input.span3,
textarea.span3,
.uneditable-input.span3 {
width: 260px;
}
input.span2,
textarea.span2,
.uneditable-input.span2 {
width: 160px;
}
input.span1,
textarea.span1,
.uneditable-input.span1 {
width: 60px;
}
.thumbnails {
margin-left: -30px;
}
.thumbnails > li {
margin-left: 30px;
}
.row-fluid .thumbnails {
margin-left: 0;
}
}
@media (max-width: 979px) {
body {
padding-top: 0;
}
.navbar-fixed-top,
.navbar-fixed-bottom {
position: static;
}
.navbar-fixed-top {
margin-bottom: 18px;
}
.navbar-fixed-bottom {
margin-top: 18px;
}
.navbar-fixed-top .navbar-inner,
.navbar-fixed-bottom .navbar-inner {
padding: 5px;
}
.navbar .container {
width: auto;
padding: 0;
}
.navbar .brand {
padding-right: 10px;
padding-left: 10px;
margin: 0 0 0 -5px;
}
.nav-collapse {
clear: both;
}
.nav-collapse .nav {
float: none;
margin: 0 0 9px;
}
.nav-collapse .nav > li {
float: none;
}
.nav-collapse .nav > li > a {
margin-bottom: 2px;
}
.nav-collapse .nav > .divider-vertical {
display: none;
}
.nav-collapse .nav .nav-header {
color: #999999;
text-shadow: none;
}
.nav-collapse .nav > li > a,
.nav-collapse .dropdown-menu a {
padding: 6px 15px;
font-weight: bold;
color: #999999;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.nav-collapse .btn {
padding: 4px 10px 4px;
font-weight: normal;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.nav-collapse .dropdown-menu li + li a {
margin-bottom: 2px;
}
.nav-collapse .nav > li > a:hover,
.nav-collapse .dropdown-menu a:hover {
background-color: #222222;
}
.nav-collapse.in .btn-group {
padding: 0;
margin-top: 5px;
}
.nav-collapse .dropdown-menu {
position: static;
top: auto;
left: auto;
display: block;
float: none;
max-width: none;
padding: 0;
margin: 0 15px;
background-color: transparent;
border: none;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.nav-collapse .dropdown-menu:before,
.nav-collapse .dropdown-menu:after {
display: none;
}
.nav-collapse .dropdown-menu .divider {
display: none;
}
.nav-collapse .navbar-form,
.nav-collapse .navbar-search {
float: none;
padding: 9px 15px;
margin: 9px 0;
border-top: 1px solid #222222;
border-bottom: 1px solid #222222;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
}
.navbar .nav-collapse .nav.pull-right {
float: none;
margin-left: 0;
}
.nav-collapse,
.nav-collapse.collapse {
height: 0;
overflow: hidden;
}
.navbar .btn-navbar {
display: block;
}
.navbar-static .navbar-inner {
padding-right: 10px;
padding-left: 10px;
}
}
@media (min-width: 980px) {
.nav-collapse.collapse {
height: auto !important;
overflow: visible !important;
}
}

1323
css/jquery-ui.css vendored

File diff suppressed because it is too large Load Diff

@ -16,3 +16,12 @@
body {
margin: 10px;
}
.well-top {
border-radius: 4px 4px 0 0;
margin-bottom: 0;
}
.well-bottom {
border-radius: 0 0 4px 4px;
border-top: none;
background-color: #E0E0E0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

@ -1,8 +1,21 @@
panelApp.filter('sortByTime', function () {
return function (input) {
return input.slice(0).sort(function (a, b) {
return function (input, range) {
var copy = input.slice(0),
min = range[0],
max = range[1];
copy = copy.sort(function (a, b) {
return b.time - a.time;
});
if (typeof min !== 'number' || typeof max !== 'number') {
return copy;
}
var start = Math.floor(input.length * min/100);
var end = Math.ceil(input.length * max/100) - start;
return copy.splice(start, end);
};
});
@ -13,6 +26,9 @@ panelApp.controller('PerfCtrl', function PerfCtrl($scope, appContext, filesystem
$scope.histogram = [];
$scope.timeline = [];
$scope.min = 0;
$scope.max = 100;
$scope.clearHistogram = function () {
appContext.clearHistogram();
};

@ -0,0 +1,43 @@
// range slider
panelApp.directive('slider', function($compile) {
return {
restrict: 'E',
terminal: true,
scope: {
minimum: '=minimum',
maximum: '=maximum'
},
link: function (scope, element, attrs) {
var dom = $('<div class="ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all">' +
'<div class="ui-slider-range ui-widget-header"></div>' +
'<a class="ui-slider-handle ui-state-default ui-corner-all" href="#"></a>' +
'<a class="ui-slider-handle ui-state-default ui-corner-all" href="#"></a>' +
'</div>');
element.append(dom);
$compile(element.contents())(scope.$new());
dom.slider({
range: true,
values: [0, 100],
slide: function () {
var min = $(this).slider('values', 0);
var max = $(this).slider('values', 1);
scope.minimum = min;
scope.maximum = max;
scope.$apply();
},
stop: function () {
var min = $(this).slider('values', 0);
var max = $(this).slider('values', 1);
scope.minimum = min;
scope.maximum = max;
scope.$apply();
}
});
}
};
});

File diff suppressed because one or more lines are too long

@ -1,15 +1,19 @@
<!doctype html>
<html ng-csp ng-app="panelApp">
<head>
<link rel="stylesheet" type="text/css" href="css/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-responsive.css">
<link rel="stylesheet" type="text/css" href="css/panel.css">
<script src="js/lib/angular.js"></script>
<script src="js/lib/jquery-1.7.2.min.js"></script>
<script src="js/lib/jquery-ui-1.8.21.custom.min.js"></script>
<script src="js/panelApp.js"></script>
<script src="js/directives/mtree.js"></script>
<script src="js/directives/slider.js"></script>
<script src="js/directives/wtree.js"></script>
<script src="js/filters/first.js"></script>
@ -24,19 +28,21 @@
<script src="js/controllers/TreeCtrl.js"></script>
</head>
<body ng-controller="TabCtrl">
<body ng-controller="TabCtrl" class="container-fluid">
<ul class="nav nav-tabs">
<li ng-repeat="tabId in ['Model', 'Performance', 'Options', 'Help']"
ng-class="{active: $parent.selectedTab == tabId}"
ng-click="$parent.selectedTab = tabId">
<div class="row-fluid">
<ul class="nav nav-tabs span12">
<li ng-repeat="tabId in ['Model', 'Performance', 'Options', 'Help']"
ng-class="{active: $parent.selectedTab == tabId}"
ng-click="$parent.selectedTab = tabId">
<a href="#">{{tabId}}</a>
</li>
</ul>
<a href="#">{{tabId}}</a>
</li>
</ul>
</div>
<div ng-class="{hidden: $parent.selectedTab != 'Model'}" ng-controller="TreeCtrl">
<div ng-class="{hidden: $parent.selectedTab != 'Model'}" ng-controller="TreeCtrl" class="row-fluid">
<h2>Model Tree</h2>
<div ng-class="{hidden: roots.length <= 1}">
<label for="select-root">Root <select id="select-root" ng-options="p.value as p.label for p in roots" ng-model="selectedRoot"></select></label>
@ -47,23 +53,29 @@
</div>
<div ng-class="{hidden: $parent.selectedTab != 'Performance'}" ng-controller="PerfCtrl">
<div ng-class="{hidden: $parent.selectedTab != 'Performance'}" ng-controller="PerfCtrl" class="row-fluid">
<h2>Performance</h2>
<div>
<label class="checkbox" for="extra">
<input type="checkbox" ng-model="enable" id="extra"> Enable (Causes tab to refresh)
<form class="well form-inline" class="row-fluid">
<label class="checkbox span4" for="extra">
<input type="checkbox" ng-model="enable" id="extra"> Enable <span class="label label-important">Causes tab to refresh</span>
</label>
<label class="checkbox" for="log">
<label class="checkbox span4" for="log">
<input type="checkbox" ng-model="log" id="log"> Log to console
</label>
</div>
<div ng-class="{hidden: !enable}">
</form>
<label for="select-root" ng-class="{hidden: roots.length <= 1}">Root
<select id="select-root" ng-options="p.value as p.label for p in roots" ng-model="selectedRoot"></select>
</label>
<div ng-class="{hidden: !enable}" class="row-fluid">
<div class="span6">
<h3>Watch Tree</h3>
<div class="well" style="height: 400px; overflow-y: auto;">
<label for="select-root" ng-class="{hidden: roots.length <= 1}">Root
<select id="select-root" ng-options="p.value as p.label for p in roots" ng-model="selectedRoot"></select>
</label>
<wtree val="trees[selectedRoot]" inspect="inspect"></wtree>
<wtree val="trees[selectedRoot]" inspect="inspect"></wtree>
</div>
</div>
<!--
<h3>Timeline</h3>
@ -73,52 +85,69 @@
</div>
-->
<h3>Watch Expressions</h3>
<div class="span6">
<h3>Watch Expressions</h3>
<div class="well" style="height: 400px; overflow-y: auto;">
<div ng-repeat="watch in histogram|sortByTime">
<span style="font-family: monospace;">{{watch.name | first}} </span>
<span> | {{watch.percent}}% | {{watch.time}}ms</span>
<div class="progress">
<div ng-style="{width: (watch.percent) + '%'}" class= "bar">
<div class="well well-top" style="height: 400px; overflow-y: auto;">
<div ng-repeat="watch in histogram|sortByTime:[min,max]">
<span style="font-family: monospace;">{{watch.name | first}} </span>
<span> | {{watch.percent}}% | {{watch.time}}ms</span>
<div class="progress">
<div ng-style="{width: (watch.percent) + '%'}" class= "bar">
</div>
</div>
</div>
</div>
<div class="well well-bottom">
<form class="form-inline">
<label>Filter expressions</label>
<slider minimum="min" maximum="max"></slider>
</form>
<button class="btn btn-success" ng-click="exportData()"><i class="icon-download-alt icon-white"></i> Save Data as JSON</button>
<button class="btn btn-danger" ng-click="clearHistogram()">Clear Data</button>
</div>
</div>
<button class="btn btn-success" ng-click="exportData()">Save Data as JSON</button>
<button class="btn btn-danger" ng-click="clearHistogram()">Clear Data</button>
</div>
</div>
<div ng-class="{hidden: $parent.selectedTab != 'Options'}" ng-controller="OptionsCtrl">
<h2>Options</h2>
<div>
<label class="checkbox" for="app">
<input type="checkbox" ng-model="debugger.app" id="app"> Show applications
</label>
</div>
<div>
<label class="checkbox" for="bindings">
<input type="checkbox" ng-model="debugger.bindings" id="bindings"> Show bindings
</label>
</div>
<div>
<label class="checkbox" for="scopes">
<input type="checkbox" ng-model="debugger.scopes" id="scopes"> Show scopes
</label>
<div ng-class="{hidden: $parent.selectedTab != 'Options'}" ng-controller="OptionsCtrl" class="row-fluid">
<div class="span6">
<h2>Options</h2>
<form class="well">
<label class="checkbox" for="app">
<input type="checkbox" ng-model="debugger.app" id="app"> Show applications
</label>
<label class="checkbox" for="bindings">
<input type="checkbox" ng-model="debugger.bindings" id="bindings"> Show bindings
</label>
<label class="checkbox" for="scopes">
<input type="checkbox" ng-model="debugger.scopes" id="scopes"> Show scopes
</label>
</form>
</div>
<h2>Info</h2>
<div>
Angular version: {{version}}
<div class="span6">
<h2>Info</h2>
<div class="well">
Angular version: {{version}}
</div>
</div>
</div>
<div ng-class="{hidden: selectedTab != 'Help'}">
<div ng-class="{hidden: selectedTab != 'Help'}" class="row-fluid">
<h2>Using the Batarang</h2>
<p>First, navigate Chrome Canary to the AngularJS application that you want to debug. <a href="https://developers.google.com/chrome-developer-tools/docs/overview#access">Open the Developer Tools</a>. There should be an AngularJS icon. Click on it to open he AngularJS Batarang.</p>
<p>First, navigate Chrome Canary to the AngularJS application that you want to debug. <a target="_blank" href="https://developers.google.com/chrome-developer-tools/docs/overview#access">Open the Developer Tools</a>. There should be an AngularJS icon. Click on it to open he AngularJS Batarang.</p>
<p>The Batarang has four tabs: Model, Performance, Options, and Help.</p>