AngularJS - Excel

HTML

<div ng-app ng-controller="sheet">
  <table>
    <tr class="column-label">
      <td></td>
      <td ng-repeat="column in columns">{{column}}</td>
    </tr>
    <tr ng-repeat="row in rows">
      <td class="row-label">{{row}}</td>
      <td ng-repeat="column in columns">
        <div>
          <input ng-model="cells[column+row]">
          <div ng-bind="compute(column+row)"
               class="output"></div>
        </div>
      </td>
    </tr>
  </table>
</div>

CSS

body { font-family: sans-serif; }
  .output, input { 
    font-size: 10pt;
    position: absolute;
    height: 1.2em;
    width: 50pt;
    height: 16pt;
    overflow: hidden;
    padding-left: 4pt;
  }
  input { border: none;}
  .output { 
    background: white; 
    pointer-events: none;
    padding-top: 2pt;
    height: 14pt;
  }
  input:focus + .output { display: none; }
 
  table { border-collapse: collapse; } 
  td > div {
    width: 55pt;
    height: 16pt;
  } 
  td { border: 1px solid #EEE; }
  .column-label  > td, .row-label {
    text-align: center;
    background: #EEE;
  }
  .row-label { width: 2em; }

JavaScript

function sheet($scope, $parse) {
    $scope.columns = ['A', 'B', 'C', 'D', 'E'];
    $scope.rows = [1, 2, 3, 4];
    $scope.cells = {};
    
    process = function(exp) {
        var res = exp.substring(1);
        return res.replace(/[A-Z]\d+/g, function(ref) {
            return 'compute("' + ref + '")';
        });
    }
    $scope.compute = function(cell) {
        var exp = $scope.cells[cell];
        if (exp){
            if ((exp.substring(0,1) == "=") || (exp.substring(0,1) == "+")){
                return $parse(process(exp))($scope);
            }else{
                var value;
                if (!isNaN(parseFloat(exp))){
                    value = parseFloat(exp);
                }
                return value;
            }
        }
    };
}