describe('Testing a Hello World controller', function() {
var $scope = null;
var ctrl = null;
//you need to indicate your module in a test
beforeEach(module('plunker'));
beforeEach(inject(function($rootScope, $controller) {
$scope = $rootScope.$new();
ctrl = $controller('MainCtrl', {
$scope: $scope
});
}));
it('should say hallo to the World', function() {
expect($scope.name).toEqual('World');
});
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>Angular ChartJS Directive + Jasmine</title>
<link data-require="jasmine" data-semver="1.3.1" rel="stylesheet" href="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" />
<link data-require="bootstrap-css@*" data-semver="2.3.2" rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" />
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css" rel="stylesheet" />
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-colorpicker/2.5.1/css/bootstrap-colorpicker.min.css"/>
<script data-require="jquery@2.0.2" data-semver="2.0.2" src="http://code.jquery.com/jquery-2.0.2.min.js"></script>
<script data-require="json2" data-semver="0.0.2012100-8" src="//cdnjs.cloudflare.com/ajax/libs/json2/20121008/json2.js"></script>
<script data-require="jasmine" data-semver="1.3.1" src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
<script data-require="jasmine" data-semver="1.3.1" src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
<script data-require="angular.js" data-semver="1.1.5" src="http://code.angularjs.org/1.1.5/angular.min.js"></script>
<script data-require="angular-mocks" data-semver="1.1.5" src="http://code.angularjs.org/1.1.5/angular-mocks.js"></script>
<script data-require="angular-scenario@1.1.5" data-semver="1.1.5" src="http://code.angularjs.org/1.1.5/angular-scenario.js"></script>
<script data-require="bootstrap@2.3.2" data-semver="2.3.2" src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-colorpicker/2.5.1/js/bootstrap-colorpicker.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-bootstrap-colorpicker/3.0.32/js/bootstrap-colorpicker-module.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<script src="chartjs-directive.js"></script>
<script src="app.js"></script>
<script src="appSpec.js"></script>
<!-- bootstraps Jasmine -->
<script src="jasmineBootstrap.js"></script>
</head>
<body>
<div id="container" ng-controller="MainCtrl" class="container">
<div class="navbar navbar-inverse ">
<div class="navbar-inner">
<div class="container">
<!-- .btn-navbar is used as the toggle for collapsed navbar content -->
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<!-- Be sure to leave the brand out there if you want it shown -->
<a class="brand" href="#">ChartJS Directive</a>
<!-- Everything you want hidden at 940px or less, place within here -->
<div class="nav-collapse collapse">
<!-- .nav, .navbar-search, .navbar-form, etc -->
</div>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div class="well">
<chart-js id="chart1" width="chart.width" height="chart.height"
title="{{chart.title}}"
type="{{chart.type}}"
data="{{chart.data}}"
ng-model="chart">
<!-- Fallback -->
You do not support the HTML5 Canvas.
</chart-js>
</div>
<br/>
<form id="options-form" class="form-horizontal">
<div class="row-fluid">
<div class="span12">
<legend>Configuration</legend>
<div class="clearfix">
<formitem title="Title:">
<input type="text" class="input-medium" ng-model="chart.title"/>
</formitem>
<formitem title="Type:">
<select class="input-medium" ng-model="chart.type">
<option>Bar</option>
<option>Line</option>
<option>Pie</option>
<option>Polar</option>
<option>Radar</option>
<option>Doughnut</option>
</select>
</formitem>
<formitem title="Height:">
<input type="number" class="input-medium" ng-model="chart.height"/>
</formitem>
<formitem title="Width:">
<input type="number" class="input-medium" ng-model="chart.width"/>
</formitem>
</div>
</div>
<div class="span12">
<legend>Labels</legend>
<div class="clearfix">
<formitem title="{{$index}}" ng-repeat="item in chart.data.labels">
<input type="text" class="input-medium" ng-model="chart.data.labels[$index]" />
<span class="help-inline" ng-show="$last">
<button class="btn btn-mini btn-danger" ng-click="chart.data.labels.splice($index, 1)"><i class="icon-remove"></i></button>
<button class="btn btn-mini btn-success" ng-click="chart.data.labels.push('Label ' + $index)"><i class="icon-plus"></i></button>
</span>
</formitem>
</div>
</div>
</div>
<div ng-repeat="item in chart.data.datasets">
<legend>Dataset {{$index}}</legend>
<div class="clearfix">
<formitem title="Fill Color:" type="append">
<input colorpicker="rgba" class="input-medium" value="" type="text" ng-model="chart.data.datasets[$index].fillColor"/>
<span class="label color" style="background-color:{{chart.data.datasets[$index].fillColor}}"> </span>
</formitem>
<formitem title="Stroke Color:" type="append">
<input colorpicker="rgba" class="input-medium" value="" type="text" ng-model="chart.data.datasets[$index].strokeColor"/>
<span class="label color" style="background-color:{{chart.data.datasets[$index].strokeColor}}"> </span>
</formitem>
<formitem title="Point Color:" type="append">
<input colorpicker="rgba" class="input-medium" value="" type="text" ng-model="chart.data.datasets[$index].pointColor"/>
<span class="label color" style="background-color:{{chart.data.datasets[$index].pointColor}}"> </span>
</formitem>
<formitem title="Data:">
<div ng-repeat="d in item.data">
<span style="width:100px !important;">{{$index}} = </span>
<input type="text" class="input-small" ng-model="item.data[$index]" />
<span class="help-inline" ng-show="$last">
<button class="btn btn-mini btn-danger" ng-click="item.data.splice($index, 1)"><i class="icon-remove"></i></button>
<button class="btn btn-mini btn-success" ng-click="item.data.push(1)"><i class="icon-plus"></i></button>
</span>
</div>
</formitem>
</div>
</div>
<legend>Table Data</legend>
<div class="clearfix">
<table class="table table-small table-bordered table-condensed">
<thead>
<!--Labels-->
<th ng-repeat="item in chart.data.labels">
<span ng-model="chart.data.labels[$index]">{{chart.data.labels[$index]}}</span>
</th>
</thead>
<tbody>
<!--Datasets-->
<tr ng-repeat="item in chart.data.datasets">
<td ng-repeat="d in item.data">
<input type="number" class="input-small" ng-model="item.data[$index]" />
</td>
</tr>
</tbody>
</table>
</div>
</form>
<legend>Debug</legend>
<pre>{{chart | json}}</pre>
</div>
</div>
</div>
<div id="HTMLReporter" class="jasmine_reporter"></div>
</body>
</html>
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 250;
/**
Create the `HTMLReporter`, which Jasmine calls to provide results of each spec and each suite. The Reporter is responsible for presenting results to the user.
*/
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
/**
Delegate filtering of specs to the reporter. Allows for clicking on single suites or specs in the results to only run a subset of the suite.
*/
jasmineEnv.specFilter = function(spec) {
return htmlReporter.specFilter(spec);
};
/**
Run all of the tests when the page finishes loading - and make sure to run any previous `onload` handler
### Test Results
Scroll down to see the results of all of these specs.
*/
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
//document.querySelector('.version').innerHTML = jasmineEnv.versionString();
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
/* restore "body" styling that were changes by "jasmine.css"... */
body { background-color: white; padding: 0; margin: 8px; }
/* ... but remain the "jasmine.css" styling for the Jasmine reporting */
.jasmine_reporter { background-color: #eeeeee; padding: 0; margin: 0; }
.chart{
width:700px;
height:250px;
}
.well{
background-color:#fefefe;
}
legend {
cursor: pointer;
}
.table-small, .table-small input {
font-size:11px;
}
.color{
width: 25px; height: 20px;
}
app = angular.module("plunker", ["colorpicker.module", "chartjs.directive"])
"use strict"
###
@name - FormItem
@comment - This creates a form control group.
@usage <formitem title="Label:" type="text">[Contents]</box>
###
app.directive "formitem", ->
restrict: "E"
replace: true
transclude: true
scope:
title: "@"
name: "@"
help: "@"
placeholder: "@"
link: postLink = (scope, element, attrs) ->
element.find('input').addClass('input-medium')
console.log element
template: '''
<div class="control-group">
<div class="control-label">
<label for="{{name}}" id="{{name | lowercase}}">{{title}}</label>
</div>
<div class="controls" ng-transclude></div>
<span class="inline-help">{{help}}</span>
</div>
'''
app.controller "MainCtrl", ($scope, $rootScope) ->
$scope.defaults =
#Bar defaults
bar:
labels: ["January", "February", "March", "April", "May", "June", "July"]
datasets: [
fillColor: "rgba(220,220,220,0.5)"
strokeColor: "rgba(220,220,220,1)"
pointColor: "rgba(220,220,220,1)"
pointStrokeColor: "#fff"
data: [65, 59, 90, 81, 56, 55, 40]
,
fillColor: "rgba(151,187,205,0.5)"
strokeColor: "rgba(151,187,205,1)"
pointColor: "rgba(151,187,205,1)"
pointStrokeColor: "#fff"
data: [28, 48, 40, 19, 96, 27, 100]
]
line: {}
pie: {}
radar:
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Partying", "Running"]
datasets: [
fillColor: "rgba(220,220,220,0.5)"
strokeColor: "rgba(220,220,220,1)"
pointColor: "rgba(220,220,220,1)"
pointStrokeColor: "#fff"
data: [65, 59, 90, 81, 56, 55, 40]
,
fillColor: "rgba(151,187,205,0.5)"
strokeColor: "rgba(151,187,205,1)"
pointColor: "rgba(151,187,205,1)"
pointStrokeColor: "#fff"
data: [28, 48, 40, 19, 96, 27, 100]
]
doughnut: {}
#Chart options
$scope.chart =
title: "Chart"
type: "Bar"
height: 250
width: 600
options:
chart:
events:
selection: (e) ->
console.log e
data: null
$scope.chart.data = $scope.defaults[String($scope.chart.type).toLowerCase()]
options = {}
$scope.Chartjs = addItem: (o) ->
$scope.$apply ->
$scope.chart.data.datasets[0].data.push obj
#window.c = $scope.Chartjs;
angular.element(document).ready ->
angular.element("legend").bind "click", ->
angular.element(this).next().slideToggle()
# * How to Use
This is how to use this directive in your application
#### 1. Download or Use Bower
Download the [production version][min] or the [development version][max].
[min]: https://raw.github.com/jonniespratley/ng-chartjs-directive/master/dist/ng-chartjs-directive.min.js
[max]: https://raw.github.com/jonniespratley/ng-chartjs-directive/master/dist/ng-chartjs-directive.js
Or use bower package manager:
bower install ng-chartjs-directive --save
#### 2. Add Dependency
In the `index.html` page:
<script src="angular.js"></script>
<script src="dist/ng-chartjs-directive.min.js"></script>
In the `app.js` file add `jonniespratley.ngChartjsDirective` to the dependencies.
var app = angular.module('app', [
'jonniespratley.ngChartjsDirective'
]);
#### 4. Add Markup
Now add the following markup to your view.
<chart-js id="chart1"
width="{{chart.width}}"
height="{{chart.height}}"
title="{{chart.title}}"
type="{{chart.type}}"
data="{{chart.data}}"
options="{{chart.options}}"
ng-model="chart.data">
<!-- Fallback -->
You do not support the HTML5 Canvas.
</chart-js>
#### 5. Add Configuration
Now add the configuration inside of your controller.
$scope.chart = {
"title": "Chart",
"type": "Bar",
"height": 300,
"width": 600,
"options": {
"chart": {
"events": {}
}
},
"data": {
"labels": [
"January",
"February",
"March",
"April",
"May",
"June",
"July"
],
"datasets": [
{
"fillColor": "rgba(220,220,220,0.5)",
"strokeColor": "rgba(220,220,220,1)",
"pointColor": "rgba(220,220,220,1)",
"pointStrokeColor": "#fff",
"data": [
65,
59,
90,
81,
56,
55,
40
]
},
{
"fillColor": "rgba(151,187,205,0.5)",
"strokeColor": "rgba(151,187,205,1)",
"pointColor": "rgba(151,187,205,1)",
"pointStrokeColor": "#fff",
"data": [
28,
48,
40,
19,
96,
27,
100
]
}
]
}
}
<form id="options-form" class="form-horizontal">
<legend>Configuration</legend>
<div class="clearfix">
<formitem title="Title:">
<input type="text" class="input-medium" ng-model="chart.title"/>
</formitem>
<formitem title="Type:">
<select class="input-medium" ng-model="chart.type">
<option>Bar</option>
<option>Line</option>
<option>Pie</option>
<option>Polar</option>
<option>Radar</option>
<option>Doughnut</option>
</select>
</formitem>
<formitem title="Height:">
<input type="number" class="input-medium" ng-model="chart.height"/>
</formitem>
<formitem title="Width:">
<input type="number" class="input-medium" ng-model="chart.width"/>
</formitem>
</div>
<legend>Labels</legend>
<div class="clearfix">
<formitem title="{{$index}}" ng-repeat="item in chart.data.labels">
<input type="text" class="input-medium" ng-model="chart.data.labels[$index]" />
<span class="help-inline" ng-show="$last">
<button class="btn btn-mini btn-danger" ng-click="chart.data.labels.splice($index, 1)"><i class="icon-remove"></i></button>
<button class="btn btn-mini btn-success" ng-click="chart.data.labels.push('Label ' + $index)"><i class="icon-plus"></i></button>
</span>
</formitem>
</div>
<div ng-repeat="item in chart.data.datasets">
<legend>Dataset {{$index}}</legend>
<div class="clearfix">
<formitem title="Fill Color:" type="append">
<input colorpicker="rgba" class="input-medium" value="" type="text" ng-model="chart.data.datasets[$index].fillColor"/>
<span class="label color" style="background-color:{{chart.data.datasets[$index].fillColor}}"> </span>
</formitem>
<formitem title="Stroke Color:">
<input colorpicker="rgba" class="input-medium" value="" type="text" ng-model="chart.data.datasets[$index].strokeColor"/>
</formitem>
<formitem title="Point Color:">
<input colorpicker="rgba" class="input-medium" value="" type="text" ng-model="chart.data.datasets[$index].pointColor"/>
</formitem>
<formitem title="Data:">
<div ng-repeat="d in item.data">
<span style="width:100px !important;">{{$index}} = </span>
<input type="text" class="input-small" ng-model="item.data[$index]" />
<span class="help-inline" ng-show="$last">
<button class="btn btn-mini btn-danger" ng-click="item.data.splice($index, 1)"><i class="icon-remove"></i></button>
<button class="btn btn-mini btn-success" ng-click="item.data.push(1)"><i class="icon-plus"></i></button>
</span>
</div>
</formitem>
</div>
</div>
<legend>Table Data</legend>
<div class="clearfix">
<table class="table table-small table-bordered table-condensed">
<thead>
<!--Labels-->
<th ng-repeat="item in chart.data.labels">
<span ng-model="chart.data.labels[$index]">{{chart.data.labels[$index]}}</span>
</th>
</thead>
<tbody>
<!--Datasets-->
<tr ng-repeat="item in chart.data.datasets">
<td ng-repeat="d in item.data">
<input type="number" class="input-small" ng-model="item.data[$index]" />
</td>
</tr>
</tbody>
</table>
</div>
</form>
var app;
app = angular.module("chartjs.directive", []);
"use strict";
app.directive("chartJs", function($timeout, $q, $log) {
return {
scope: {
id: "@",
title: "@",
type: "@",
width: "=",
height: "=",
options: "@",
data: "@",
ngModel: "="
},
restrict: "E",
replace: true,
require: "?ngModel",
template: "<div class=\"chartjs\">\n <legend ng-show=\"{{title}}\">{{title}}</legend>\n <div class=\"chartjs-wrap\">\n <canvas id=\"chart_{{id}}\" width=\"{{width}}\" height=\"{{height}}\">\n Content\n </canvas>\n </div>\n <pre>\n height :{{height}}\n width :{{width}}\n </pre>\n</div>",
link: function(scope, element, attrs, ngModel) {
var CHART, buildChart, createChart, delta, resizeend, rtime, timeout;
if (!ngModel) {
return;
}
CHART = {
id: "#chart_" + attrs.id,
options: attrs.options,
type: 'bar',
data: []
};
rtime = new Date(1, 1, 2000, 12, '00', '00');
timeout = false;
delta = 700;
resizeend = function() {
if (new Date() - rtime < delta) {
setTimeout(resizeend, delta);
} else {
timeout = false;
buildChart();
}
};
createChart = function(id, type, data, options) {
var ctx, defaults, defer, wrapper;
defer = $q.defer();
ctx = angular.element(id).get(0).getContext("2d");
defaults = angular.extend({}, options);
wrapper = angular.element(id).parent();
scope.$apply(function() {
scope.width = ctx.width = wrapper.width();
scope.height = ctx.height = wrapper.height();
});
console.log('Chart', data, type);
defer.resolve(new Chart(ctx, {type: type, data: data, options: defaults}));
/*switch (type) {
case "line":
break;
case "bar":
defer.resolve(new Chart(ctx).Bar(data, defaults));
break;
case "doughnut":
defer.resolve(new Chart(ctx).Doughnut(data, defaults));
break;
case "pie":
defer.resolve(new Chart(ctx).Pie(data, defaults));
break;
case "polar":
defer.resolve(new Chart(ctx).PolarArea(data, defaults));
break;
case "radar":
defer.resolve(new Chart(ctx).Radar(data, defaults));
break;
default:
defer.resolve(new Chart(ctx).Line(data, defaults));
}*/
return defer.promise;
};
buildChart = function() {
$timeout((function() {
createChart(CHART.id, CHART.type, CHART.data, CHART.options);
}), 250);
};
scope.$watch("ngModel", function(newVal, oldVal) {
CHART.data = newVal.data;
$log.info("Model $viewValue:", newVal, oldVal);
}, true);
ngModel.$render = function() {
$log.info('Model render');
buildChart();
};
angular.element(window).resize(function() {
rtime = new Date();
if (timeout === false) {
timeout = true;
$timeout(resizeend, delta);
}
});
attrs.$observe("type", function(value) {
CHART.type = String(value).toLowerCase();
buildChart();
});
attrs.$observe("data", function(value) {
console.log('data changed', value);
buildChart();
});
}
};
});
// ---
// generated by coffee-script 1.9.2