<!DOCTYPE html>
<html ng-app="app">

<head>
  <link data-require="bootstrap-css@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
  <link rel="stylesheet" href="style.css" />
  <script src="http://code.angularjs.org/1.2.26/angular.js"></script>
  <!--ngDialog-->
  <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/css/ngDialog.min.css" />
  <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/css/ngDialog-theme-default.min.css" />
  <script src="http://cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/js/ngDialog.min.js"></script>
  <script src="app.js"></script>
</head>

<body>
  <div id="d" ng-controller="canvasCont">

    <div class="row">
      <!-- RIGHT COLUMN -->
      <div class="toolbox well well-sm">
        <h4>Tools</h4>
         <span class="glyphicon glyphicon-sunglasses"></span> Filters
         <span class="glyphicon glyphicon-erase"></span> Eraser
         <span class="glyphicon glyphicon-move"></span> Moving
         <span class="glyphicon glyphicon-tint"></span> Moving
         <span class="glyphicon glyphicon-picture"></span> Import image
         <span class="glyphicon glyphicon-font"></span> Add text
         <span class="glyphicon glyphicon-cog"></span> Settings
      </div>
      
      <div class="col-md-3 col-sm-3">
        <div class="toolbox well well-sm">
        <h4>Colors</h4>
          <div class="colorblock" ng-repeat="color in colorsArray" style="background:{{color}}" ng-click="selectColor(color)" ng-class="{'selected':color==selectedcolor}"></div>
          
        <h4>Brushes</h4>
          <div class="sizeblock" ng-repeat="size in sizesArray" style="width:{{size}}px;height:{{size}}px" ng-click="selectSize(size)" ng-class="{'selected':size==selectedsize}"></div>
        </div>

      </div>

      <!-- CENTRAL ZONE -->
      <div class="col-md-6 col-sm-6">

        <div class="layer-box" style="width:{{canvasWidth}}px; height:{{canvasHeight}}px;">
          <canvas ng-class="{active: (activeLayerIndex == layer.id), hidden : !layer.visible }" ng-repeat="layer in layers" layerid="layer.id" width="{{canvasWidth}}" height="{{canvasHeight}}" drawing=""></canvas>
        </div>

      </div>

      <!-- LEFT COLUMN -->
      <div class="col-md-3 col-sm-3">

        <!--layers settings-->
        <div class="controls well well-sm">
          <h4>Layers <span class="badge">{{layers.length}}</span></h4>
          <button ng-click="addLayer()" class="btn btn-primary">Add layer</button>

          <ul class="list-group layer-list">
            <li title="{{layer.id}}" class="list-group-item" ng-repeat="layer in layers track by $index" ng-click="selectThis(layer)" ng-class="{'layer-invisible': !layer.visible , 'layer-active':layer.id == activeLayerIndex}">
              <button type="button" class="btn btn-default btn-xs" ng-click="removeThis(layer)"><span class="glyphicon glyphicon-remove"></span>
              </button>
              {{layer.name}}
              <button type="button" class="btn btn-default btn-xs visibility-button" ng-show="layer.visible" ng-click="toggleThis(layer)"><span class="glyphicon glyphicon-eye-close"></span>
              </button>
              <button type="button" class="btn btn-default btn-xs visibility-button" ng-show="!layer.visible" ng-click="toggleThis(layer)"><span class="glyphicon glyphicon-eye-open"></span>
              </button>
            </li>
          </ul>

        </div>


      </div>
    </div>
    

<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
  Button with data-target
</button>
<div class="collapse" id="collapseExample">
  <div class="well">
     activeLayerIndex: {{activeLayerIndex}}
     <br>
     layers: {{layers | json}}
  </div>
</div>
    
    
  </div>
</body>

</html>
var app = angular.module("app", ['ngDialog']);

app.config(['ngDialogProvider', function (ngDialogProvider) {
    ngDialogProvider.setDefaults({
        className: 'ngdialog-theme-default',
        plain: true,
        showClose: true,
        closeByDocument: true,
        closeByEscape: true
    });
}]);

app.constant('APP_PRESETS', {
    'colors' : ['#000','#f00','#0f0','#00f','#fff', '#00FA9A', '#FFA500', '#FFFF00'],
    'sizes' : [3,5,10,20],
    'canvas' : {
      'width' : 500,
      'height': 200
    },
    'basicLayer' : {
      "name": "untitled",
      "id": 0,
      "visible": true
    }
});

app.controller("canvasCont", ['$scope', '$rootScope','ngDialog', 'APP_PRESETS',
    function($scope, $rootScope, ngDialog, APP_PRESETS) {
      
  $scope.selectedcolor = '#fff',
  $scope.selectedsize = 10,
  $scope.layers = [];
  
  $scope.colorsArray = APP_PRESETS.colors;
  $scope.sizesArray = APP_PRESETS.sizes;
  $scope.canvasWidth = APP_PRESETS.canvas.width;
  $scope.canvasHeight = APP_PRESETS.canvas.height;
  
  $scope.selectColor = function(c) {
    $scope.selectedcolor = c;
    $rootScope.selectedcolor = c;
  }

  $scope.selectSize = function(s) {
    $scope.selectedsize = s;
    $rootScope.selectedsize = s;
  }


  /*
  basic layer structure

  */
  
  $scope.saveLayerName = function(newlayername){
      
      if (newlayername.length < 2) {
        $scope.newlayername_note = 'Too short layer name';
        return false;
      }
      
      var newLyr = angular.extend({
      "name": "untitled",
      "id": 0,
      "visible": true
    }, {
      "name": newlayername,
      "id": Date.now().toString().substr(5),
      "visible": true
    });
    $scope.layers.push(newLyr);
    
    return true;
    
  }
  
  $scope.addLayer = function() {

    ngDialog.open({
      template: 'addLayertemplate.html',
      scope: $scope,
      plain: false
  });

  }

  $scope.removeThis = function(lr) {
    $scope.layers = $scope.layers.filter(function(item) {
      return item.id != lr.id;
    })
  };

  $scope.toggleThis = function(lr) {
    lr.visible = !lr.visible;
  }
  
  $scope.selectThis = function(lr){
    $scope.activeLayerIndex = lr.id;
    $rootScope.activeLayerID = lr.id;
  }
  
}])

app.directive("drawing", function($rootScope) {
  return {
    scope: {
      sel: '=',
      layerid : '='
    },
    restrict: "A",
    link: function(scope, element, attrs) {
      var ctx = element[0].getContext('2d');

      // variable that decides if something should be drawn on mousemove
      var drawing = false;

      // the last coordinates before the current move
      var lastX;
      var lastY;

      element.bind('mousedown', function(event) {
        
        if ($rootScope.activeLayerID == scope.layerid) {
        
          if (event.offsetX !== undefined) {
            lastX = event.offsetX;
            lastY = event.offsetY;
          } else {
            lastX = event.layerX - event.currentTarget.offsetLeft;
            lastY = event.layerY - event.currentTarget.offsetTop;
          }
  
          // begins new line
          ctx.beginPath();
  
          drawing = true;
        }
      });
      element.bind('mousemove', function(event) {
        
        if ($rootScope.activeLayerID == scope.layerid) {
        
          if (drawing) {
            // get current mouse position
            if (event.offsetX !== undefined) {
              currentX = event.offsetX;
              currentY = event.offsetY;
            } else {
              currentX = event.layerX - event.currentTarget.offsetLeft;
              currentY = event.layerY - event.currentTarget.offsetTop;
            }
  
            draw(lastX, lastY, currentX, currentY);
  
            // set current coordinates to last one
            lastX = currentX;
            lastY = currentY;
          }
        }

      });
      element.bind('mouseup', function(event) {
        // stop drawing
        drawing = false;
      });

      // canvas reset
      function reset() {
        element[0].width = element[0].width;
      }

      function draw(lX, lY, cX, cY) {
        // line from
        ctx.moveTo(lX, lY);
        // to
        ctx.lineTo(cX, cY);
        // color
        ctx.strokeStyle = $rootScope.selectedcolor;
        ctx.lineWidth = $rootScope.selectedsize;
        // draw it
        ctx.stroke();
      }
    }
  };
});

/*
function colorPicker(){
  var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
img.onload = function() {
  ctx.drawImage(img, 0, 0);
  img.style.display = 'none';
};
var color = document.getElementById('color');
function pick(event) {
  var x = event.layerX;
  var y = event.layerY;
  var pixel = ctx.getImageData(x, y, 1, 1);
  var data = pixel.data;
  var rgba = 'rgba(' + data[0] + ',' + data[1] +
             ',' + data[2] + ',' + data[3] + ')';
  color.style.background =  rgba;
  color.textContent = rgba;
}
canvas.addEventListener('mousemove', pick);
}
*/
/* Styles go here */

body {
  font-family: "Eau Naturelle", "Helvetica", "Arial", "Lucida Grande", "Gill Sans", "Verdana", sans-serif;
  font-weight: 100;
  color: #444;
  background-color: #ddd;
}
#canvas {
  border-bottom: 1px solid rgba(0, 0, 0, 0.3);
  background-color: #FFF;
  box-shadow: 0 9px 20px -5px rgba(0, 0, 0, 0.8);
}

h1 {
  color: #444;
  font-family: "Eau Naturelle", "Helvetica", "Arial", "Lucida Grande", "Gill Sans", "Verdana", sans-serif;
  font-weight: 500;
}
a {
  color: #4a9;
  text-decoration: none;
  font-style: italic;
  font-weight: 800;
}
.colorblock, .sizeblock {
  display:inline-block;
}
.colorblock {
  width: 20px;
  height: 20px;
  cursor: pointer;
  margin:2px;
  border-radius:5px;
  border: 2px solid transparent;
}
.sizeblock {
  background: #000;
  border-radius: 20px;
  cursor: pointer;
  margin: 2px;
}
.selected {
  border: 2px solid cyan;
}
.visibility-button {
  float:right;
}
.layer-box canvas{
  position:absolute;
  z-index:10;
}
.layer-box canvas.active{
  z-index:100;
}
.layer-box canvas.hidden{
  opacity:0;
}
.layer-active {
  background: #0044cc;
  color:#fff;
}

 .layer-invisible .visibility-marker {
  color: #f00;
}
# Simple AngularJS drawing directive

Now also works with FireFox!
<div class="dialog-contents">
  <label>Layer name:</label>
  <input type="text" ng-model="newlayername" />
  <div class="note" ng-show="alertshow && newlayername.length<2">too short!</div>
  <input type="button" value="OK" ng-click="alertshow = true && saveLayerName(newlayername) && closeThisDialog()" />
</div>