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}}">&nbsp;</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}}">&nbsp;</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}}">&nbsp;</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}}">&nbsp;</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