<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
    <script src="http://www.ag-grid.com/dist/ag-grid.js"></script>
    <link rel="stylesheet" type="text/css" href="http://www.ag-grid.com/dist/ag-grid.css">
    <link rel="stylesheet" type="text/css" href="http://www.ag-grid.com/dist/theme-fresh.css">
    <script src="controller.js"></script>
</head>

<body ng-app="example" ng-controller="exampleCtrl">
    <div ag-grid="gridOptions" style="height: 460px;" class="ag-fresh"></div>
</body>
</html>
var module = angular.module("example", ["agGrid"]);

module.controller("exampleCtrl", function($scope) {
  
    $scope.data = [
      { id: 1,
        text: "This is some really long text that would ordinarily be truncated with ellipses at the first line."
      }, {
        id: 2,
        text: "The quick brown fox jumped over the lazy dogs."
      }, {
        id: 3,
        text: "This is a test of the emergency broadcast system. This is only a test."
      }, {
        id: 4,
        text: "A shorter line of text."
      }, {
        id: 5,
        text: "This a long line of text to test the line-clamping feature. This is a long line of text."
      }, {
        id: 6,
        text: "This is some really long text that would ordinarily be truncated with ellipses at the first line."
      }, {
        id: 7,
        text: "The quick brown fox jumped over the lazy dogs."
      }, {
        id: 8,
        text: "This is a test of the emergency broadcast system. This is only a test."
      }, {
        id: 9,
        text: "A shorter line of text."
      }, {
        id: 10,
        text: "This a long line of text to test the line-clamping feature. This is a long line of text."
      }
    ];
  
    $scope.columnDefs = [
        { headerName: "ID", field: "id", width: 50 },
        { headerName: "Text", field: "text", width: 260, cellRenderer: CellRenderer }
    ];


    var maxLines = 2; // This is key! Defines the number of lines that will be visible in each cell row. The last line will be truncated with ellipses.

    $scope.gridOptions = {
        columnDefs: $scope.columnDefs,
        rowData: $scope.data,
        enableColResize: true,
        enableFilter: false,
        enableSorting: false,
        showToolPanel: false,
        rowHeight: 4+(maxLines*19), // 19 is your cell's line-height and 4 is a little extra for padding

        onColumnResized: function(col) {
            $scope.columnDefs[col.column.index].width = col.column.actualWidth;
            $scope.gridOptions.api.refreshView();
        }
    };
    
    
    function CellRenderer(params) {
        var width = params.colDef.width - 6; // 6 gives us a little padding
        var debug = false;
        if (params.rowIndex === 1) debug = true;
        font = 'normal 14px "Helvetica Neue",Helvetica,Arial,sans-serif';
        var result = GetWidthHeight(params.value, width, font, debug);
        var out = "";
        
        for (var i=0; i < result.OutputLines.length-1; i++) {
            out += '<div style="width: '+width+'px">'+result.OutputLines[i]+'</div>\n';
        }
        out += '<div style="overflow: hidden; text-overflow: ellipsis; width: '+width+'px;">'+result.OutputLines[i]+'</div>';
        return out;
    }


    /**
     * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
     *
     * @param {String} text The text to be rendered.
     * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
     *
     * @see http://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
     */
    function GetTextWidth(text, font) {
        // re-use canvas object for better performance
        var canvas = this.canvas || (this.canvas = document.createElement("canvas"));
        var context = canvas.getContext("2d");
        context.font = font;
        var metrics = context.measureText(text);
        return parseInt(metrics.width*1.15); // don't ask why I'm adding 15% to the width... it just works. If you can figure out how to make it exact, please let me know.
    }

    function GetWidthHeight(string, AllowedWidth, font, debug) {
        var words = string.split(" "); // split on spaces
        var LineWidth = 0, CharCounter = 0, StartCounter = 0, MaxWidth = 0;
        var DivText = "";
        var NumLines = 1;
        var OutputLines = [];

        for (var i=0; i < words.length; i++) {
            var text = words[i];
            var ThisWidth = GetTextWidth(text, font);
            if (debug) console.log(text + " = " + ThisWidth + "px");
            if (LineWidth + ThisWidth > AllowedWidth) {
                // end this line, begin a new one.
                if (LineWidth > MaxWidth) MaxWidth = LineWidth;
                var LineOut = string.substr(StartCounter, CharCounter);
                i--; // go back one word since this word needs to start on a new line
                if (debug) {
                    console.log("LINE OUT: " + LineOut);
                    console.log("LINE PIXEL WIDTH: " + LineWidth);
                }
                LineWidth = ThisWidth;
                StartCounter = StartCounter + CharCounter;
                OutputLines[NumLines-1] = LineOut;
                if (NumLines == maxLines) {
                    OutputLines[NumLines-1] = string.substr(StartCounter-CharCounter);
                    break;
                }
                CharCounter = 0;
                NumLines++;
            } else {
                LineWidth += ThisWidth;
                CharCounter += text.length + 1;
                if (i == words.length-1) {
                    OutputLines[NumLines-1] = string.substr(StartCounter);
                }
            }
        }
        if (MaxWidth === 0) MaxWidth = AllowedWidth;
        if (OutputLines.length === 0) OutputLines.push(string);
        return {
            OutputLines: OutputLines,
            NumLines: NumLines,
            MaxWidth: MaxWidth
        };
    }

});