var app = angular.module('plunker', ['angularGrid']);

app.controller('MainCtrl', function($scope) {
  
    $scope.selectAllChecked = false;
    
    $scope.selectAllRows = function(){
        if ($scope.selectAllChecked) {
            $scope.gridOptions.api.selectAll();
        } else {
            $scope.gridOptions.api.deselectAll();
        }
    };

    var columnDefs = [{
        checkboxSelection: true,
        width:30,
        suppressResize: true,
        headerCellRenderer: function(params){
            return '<input type="checkbox" ng-model="selectAllChecked" ng-change="selectAllRows()">';
        }
    }, {
        headerName: 'EMAIL',
        field: 'Email'
    }, {
        headerName: 'ROLE',
        field: 'Role'
    }];

    var rowData = [{
            Role: 'Agent',
            Email: 'releqiw@hotmail.com'
        }, {
            Role: 'Agent',
            Email: 'femew@hotmail.com'
        }, {
            Role: 'Manager',
            Email: 'femew@hotmail.com'
        }
      ];

    $scope.gridOptions = {
        columnDefs: columnDefs,
        rowData: rowData,
        dontUseScrolls: false,
        rowSelection: 'multiple',
        rowDeselection: true,
        rowHeight: 40,
        enableColResize: true,
        angularCompileRows: true,
        angularCompileHeaders: true,
        suppressCellSelection: true,
        suppressRowClickSelection: true
    };
});

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

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.3/angular.js" data-semver="1.4.3"></script>
  <script src="app.js"></script>
  <script src="angular-grid.js"></script>
  <link rel="stylesheet" type="text/css" href="angular-grid.css">
  <link rel="stylesheet" type="text/css" href="theme-fresh.css">


</head>

<body ng-controller="MainCtrl">
  <input type="checkbox" ng-model="selectAllChecked" ng-change="selectAllRows()" />Select All

  <div ag-grid="gridOptions" class="ag-fresh"></div>

</body>

</html>
/* Put your css in here */

/**
 * angular-grid - High performance and feature rich data grid for AngularJS
 * @version v1.11.1
 * @link http://www.angulargrid.com/
 * @license MIT
 */
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var FUNCTION_STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
        var FUNCTION_ARGUMENT_NAMES = /([^\s,]+)/g;
        var Utils = (function () {
            function Utils() {
            }
            Utils.iterateObject = function (object, callback) {
                var keys = Object.keys(object);
                for (var i = 0; i < keys.length; i++) {
                    var key = keys[i];
                    var value = object[key];
                    callback(key, value);
                }
            };
            Utils.map = function (array, callback) {
                var result = [];
                for (var i = 0; i < array.length; i++) {
                    var item = array[i];
                    var mappedItem = callback(item);
                    result.push(mappedItem);
                }
                return result;
            };
            Utils.forEach = function (array, callback) {
                if (!array) {
                    return;
                }
                for (var i = 0; i < array.length; i++) {
                    var value = array[i];
                    callback(value, i);
                }
            };
            Utils.getFunctionParameters = function (func) {
                var fnStr = func.toString().replace(FUNCTION_STRIP_COMMENTS, '');
                var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(FUNCTION_ARGUMENT_NAMES);
                if (result === null) {
                    return [];
                }
                else {
                    return result;
                }
            };
            Utils.find = function (collection, predicate, value) {
                if (collection === null || collection === undefined) {
                    return null;
                }
                for (var i = 0; i < collection.length; i++) {
                    if (collection[i][predicate] === value) {
                        return collection[i];
                    }
                }
                return null;
            };
            Utils.toStrings = function (array) {
                return this.map(array, function (item) {
                    if (item === undefined || item === null || !item.toString) {
                        return null;
                    }
                    else {
                        return item.toString();
                    }
                });
            };
            Utils.iterateArray = function (array, callback) {
                for (var index = 0; index < array.length; index++) {
                    var value = array[index];
                    callback(value, index);
                }
            };
            Utils.getValue = function (expressionService, data, colDef, node, api, context) {
                var valueGetter = colDef.valueGetter;
                var field = colDef.field;
                // if there is a value getter, this gets precedence over a field
                if (valueGetter) {
                    var params = {
                        data: data,
                        node: node,
                        colDef: colDef,
                        api: api,
                        context: context
                    };
                    if (typeof valueGetter === 'function') {
                        // valueGetter is a function, so just call it
                        return valueGetter(params);
                    }
                    else if (typeof valueGetter === 'string') {
                        // valueGetter is an expression, so execute the expression
                        return expressionService.evaluate(valueGetter, params);
                    }
                }
                else if (field && data) {
                    return data[field];
                }
                else {
                    return undefined;
                }
            };
            //Returns true if it is a DOM node
            //taken from: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
            Utils.isNode = function (o) {
                return (typeof Node === "object" ? o instanceof Node : o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName === "string");
            };
            //Returns true if it is a DOM element
            //taken from: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
            Utils.isElement = function (o) {
                return (typeof HTMLElement === "object" ? o instanceof HTMLElement : o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string");
            };
            Utils.isNodeOrElement = function (o) {
                return this.isNode(o) || this.isElement(o);
            };
            //adds all type of change listeners to an element, intended to be a text field
            Utils.addChangeListener = function (element, listener) {
                element.addEventListener("changed", listener);
                element.addEventListener("paste", listener);
                element.addEventListener("input", listener);
            };
            //if value is undefined, null or blank, returns null, otherwise returns the value
            Utils.makeNull = function (value) {
                if (value === null || value === undefined || value === "") {
                    return null;
                }
                else {
                    return value;
                }
            };
            Utils.removeAllChildren = function (node) {
                if (node) {
                    while (node.hasChildNodes()) {
                        node.removeChild(node.lastChild);
                    }
                }
            };
            Utils.isVisible = function (element) {
                return (element.offsetParent !== null);
            };
            //loads the template and returns it as an element. makes up for no simple way in
            //the dom api to load html directly, eg we cannot do this: document.createElement(template)
            Utils.loadTemplate = function (template) {
                var tempDiv = document.createElement("div");
                tempDiv.innerHTML = template;
                return tempDiv.firstChild;
            };
            //if passed '42px' then returns the number 42
            //        pixelStringToNumber(val: any) {
            //            if (typeof val === "string") {
            //                if (val.indexOf("px") >= 0) {
            //                    val.replace("px", "");
            //                }
            //                return parseInt(val);
            //            } else {
            //                return val;
            //            }
            //        }
            Utils.querySelectorAll_addCssClass = function (eParent, selector, cssClass) {
                var eRows = eParent.querySelectorAll(selector);
                for (var k = 0; k < eRows.length; k++) {
                    this.addCssClass(eRows[k], cssClass);
                }
            };
            Utils.querySelectorAll_removeCssClass = function (eParent, selector, cssClass) {
                var eRows = eParent.querySelectorAll(selector);
                for (var k = 0; k < eRows.length; k++) {
                    this.removeCssClass(eRows[k], cssClass);
                }
            };
            Utils.querySelectorAll_replaceCssClass = function (eParent, selector, cssClassToRemove, cssClassToAdd) {
                var eRows = eParent.querySelectorAll(selector);
                for (var k = 0; k < eRows.length; k++) {
                    this.removeCssClass(eRows[k], cssClassToRemove);
                    this.addCssClass(eRows[k], cssClassToAdd);
                }
            };
            Utils.addOrRemoveCssClass = function (element, className, addOrRemove) {
                if (addOrRemove) {
                    this.addCssClass(element, className);
                }
                else {
                    this.removeCssClass(element, className);
                }
            };
            Utils.addCssClass = function (element, className) {
                if (element.className && element.className.length > 0) {
                    var cssClasses = element.className.split(' ');
                    if (cssClasses.indexOf(className) < 0) {
                        cssClasses.push(className);
                        element.className = cssClasses.join(' ');
                    }
                }
                else {
                    element.className = className;
                }
            };
            Utils.offsetHeight = function (element) {
                return element && element.clientHeight ? element.clientHeight : 0;
            };
            Utils.offsetWidth = function (element) {
                return element && element.clientWidth ? element.clientWidth : 0;
            };
            Utils.removeCssClass = function (element, className) {
                if (element.className && element.className.length > 0) {
                    var cssClasses = element.className.split(' ');
                    var index = cssClasses.indexOf(className);
                    if (index >= 0) {
                        cssClasses.splice(index, 1);
                        element.className = cssClasses.join(' ');
                    }
                }
            };
            Utils.removeFromArray = function (array, object) {
                array.splice(array.indexOf(object), 1);
            };
            Utils.defaultComparator = function (valueA, valueB) {
                var valueAMissing = valueA === null || valueA === undefined;
                var valueBMissing = valueB === null || valueB === undefined;
                if (valueAMissing && valueBMissing) {
                    return 0;
                }
                if (valueAMissing) {
                    return -1;
                }
                if (valueBMissing) {
                    return 1;
                }
                if (valueA < valueB) {
                    return -1;
                }
                else if (valueA > valueB) {
                    return 1;
                }
                else {
                    return 0;
                }
            };
            Utils.formatWidth = function (width) {
                if (typeof width === "number") {
                    return width + "px";
                }
                else {
                    return width;
                }
            };
            // tries to use the provided renderer. if a renderer found, returns true.
            // if no renderer, returns false.
            Utils.useRenderer = function (eParent, eRenderer, params) {
                var resultFromRenderer = eRenderer(params);
                if (this.isNode(resultFromRenderer) || this.isElement(resultFromRenderer)) {
                    //a dom node or element was returned, so add child
                    eParent.appendChild(resultFromRenderer);
                }
                else {
                    //otherwise assume it was html, so just insert
                    var eTextSpan = document.createElement('span');
                    eTextSpan.innerHTML = resultFromRenderer;
                    eParent.appendChild(eTextSpan);
                }
            };
            // if icon provided, use this (either a string, or a function callback).
            // if not, then use the second parameter, which is the svgFactory function
            Utils.createIcon = function (iconName, gridOptionsWrapper, colDefWrapper, svgFactoryFunc) {
                var eResult = document.createElement('span');
                var userProvidedIcon;
                // check col for icon first
                if (colDefWrapper && colDefWrapper.colDef.icons) {
                    userProvidedIcon = colDefWrapper.colDef.icons[iconName];
                }
                // it not in col, try grid options
                if (!userProvidedIcon && gridOptionsWrapper.getIcons()) {
                    userProvidedIcon = gridOptionsWrapper.getIcons()[iconName];
                }
                // now if user provided, use it
                if (userProvidedIcon) {
                    var rendererResult;
                    if (typeof userProvidedIcon === 'function') {
                        rendererResult = userProvidedIcon();
                    }
                    else if (typeof userProvidedIcon === 'string') {
                        rendererResult = userProvidedIcon;
                    }
                    else {
                        throw 'icon from grid options needs to be a string or a function';
                    }
                    if (typeof rendererResult === 'string') {
                        eResult.innerHTML = rendererResult;
                    }
                    else if (this.isNodeOrElement(rendererResult)) {
                        eResult.appendChild(rendererResult);
                    }
                    else {
                        throw 'iconRenderer should return back a string or a dom object';
                    }
                }
                else {
                    // otherwise we use the built in icon
                    eResult.appendChild(svgFactoryFunc());
                }
                return eResult;
            };
            Utils.addStylesToElement = function (eElement, styles) {
                Object.keys(styles).forEach(function (key) {
                    eElement.style[key] = styles[key];
                });
            };
            Utils.getScrollbarWidth = function () {
                var outer = document.createElement("div");
                outer.style.visibility = "hidden";
                outer.style.width = "100px";
                outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
                document.body.appendChild(outer);
                var widthNoScroll = outer.offsetWidth;
                // force scrollbars
                outer.style.overflow = "scroll";
                // add innerdiv
                var inner = document.createElement("div");
                inner.style.width = "100%";
                outer.appendChild(inner);
                var widthWithScroll = inner.offsetWidth;
                // remove divs
                outer.parentNode.removeChild(outer);
                return widthNoScroll - widthWithScroll;
            };
            Utils.isKeyPressed = function (event, keyToCheck) {
                var pressedKey = event.which || event.keyCode;
                return pressedKey === keyToCheck;
            };
            Utils.setVisible = function (element, visible) {
                if (visible) {
                    element.style.display = 'inline';
                }
                else {
                    element.style.display = 'none';
                }
            };
            return Utils;
        })();
        grid.Utils = Utils;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var Constants = (function () {
            function Constants() {
            }
            Constants.STEP_EVERYTHING = 0;
            Constants.STEP_FILTER = 1;
            Constants.STEP_SORT = 2;
            Constants.STEP_MAP = 3;
            Constants.ASC = "asc";
            Constants.DESC = "desc";
            Constants.ROW_BUFFER_SIZE = 20;
            Constants.MIN_COL_WIDTH = 10;
            Constants.SUM = 'sum';
            Constants.MIN = 'min';
            Constants.MAX = 'max';
            Constants.KEY_TAB = 9;
            Constants.KEY_ENTER = 13;
            Constants.KEY_SPACE = 32;
            Constants.KEY_DOWN = 40;
            Constants.KEY_UP = 38;
            Constants.KEY_LEFT = 37;
            Constants.KEY_RIGHT = 39;
            return Constants;
        })();
        grid.Constants = Constants;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="utils.ts" />
/// <reference path="constants.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var _ = grid.Utils;
        var constants = grid.Constants;
        var ColumnController = (function () {
            function ColumnController() {
                this.listeners = [];
                this.createModel();
            }
            ColumnController.prototype.init = function (angularGrid, selectionRendererFactory, gridOptionsWrapper, expressionService) {
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.angularGrid = angularGrid;
                this.selectionRendererFactory = selectionRendererFactory;
                this.expressionService = expressionService;
            };
            ColumnController.prototype.createModel = function () {
                var that = this;
                this.model = {
                    // used by:
                    // + inMemoryRowController -> sorting, building quick filter text
                    // + headerRenderer -> sorting (clearing icon)
                    getAllColumns: function () {
                        return that.allColumns;
                    },
                    // + rowController -> while inserting rows, and when tabbing through cells (need to change this)
                    // need a newMethod - get next col index
                    getDisplayedColumns: function () {
                        return that.displayedColumns;
                    },
                    // + toolPanel
                    getGroupedColumns: function () {
                        return that.pivotColumns;
                    },
                    // + rowController
                    getValueColumns: function () {
                        return that.valueColumns;
                    },
                    // used by:
                    // + angularGrid -> for setting body width
                    // + rowController -> setting main row widths (when inserting and resizing)
                    getBodyContainerWidth: function () {
                        return that.getTotalColWidth(false);
                    },
                    // used by:
                    // + angularGrid -> setting pinned body width
                    getPinnedContainerWidth: function () {
                        return that.getTotalColWidth(true);
                    },
                    // used by:
                    // + headerRenderer -> setting pinned body width
                    getHeaderGroups: function () {
                        return that.headerGroups;
                    },
                    // used by:
                    // + api.getFilterModel() -> to map colDef to column, key can be colDef or field
                    getColumn: function (key) {
                        return that.getColumn(key);
                    },
                    // used by:
                    // + rowRenderer -> for navigation
                    getVisibleColBefore: function (col) {
                        var oldIndex = that.visibleColumns.indexOf(col);
                        if (oldIndex > 0) {
                            return that.visibleColumns[oldIndex - 1];
                        }
                        else {
                            return null;
                        }
                    },
                    // used by:
                    // + rowRenderer -> for navigation
                    getVisibleColAfter: function (col) {
                        var oldIndex = that.visibleColumns.indexOf(col);
                        if (oldIndex < (that.visibleColumns.length - 1)) {
                            return that.visibleColumns[oldIndex + 1];
                        }
                        else {
                            return null;
                        }
                    },
                    getDisplayNameForCol: function (column) {
                        return that.getDisplayNameForCol(column);
                    }
                };
            };
            ColumnController.prototype.getState = function () {
                if (!this.allColumns || this.allColumns.length < 0) {
                    return [];
                }
                var result = [];
                for (var i = 0; i < this.allColumns.length; i++) {
                    var column = this.allColumns[i];
                    var pivotIndex = this.pivotColumns.indexOf(column);
                    var resultItem = {
                        colId: column.colId,
                        hide: !column.visible,
                        aggFunc: column.aggFunc ? column.aggFunc : null,
                        width: column.actualWidth,
                        pivotIndex: pivotIndex >= 0 ? pivotIndex : null
                    };
                    result.push(resultItem);
                }
                return result;
            };
            ColumnController.prototype.setState = function (columnState) {
                var oldColumnList = this.allColumns;
                this.allColumns = [];
                this.pivotColumns = [];
                this.valueColumns = [];
                var that = this;
                _.forEach(columnState, function (stateItem) {
                    var oldColumn = _.find(oldColumnList, 'colId', stateItem.colId);
                    if (!oldColumn) {
                        console.warn('ag-grid: column ' + stateItem.colId + ' not found');
                        return;
                    }
                    // following ensures we are left with boolean true or false, eg converts (null, undefined, 0) all to true
                    oldColumn.visible = stateItem.hide ? false : true;
                    // if width provided and valid, use it, otherwise stick with the old width
                    oldColumn.actualWidth = stateItem.width >= constants.MIN_COL_WIDTH ? stateItem.width : oldColumn.actualWidth;
                    // accept agg func only if valid
                    var aggFuncValid = [constants.MIN, constants.MAX, constants.SUM].indexOf(stateItem.aggFunc) >= 0;
                    if (aggFuncValid) {
                        oldColumn.aggFunc = stateItem.aggFunc;
                        that.valueColumns.push(oldColumn);
                    }
                    else {
                        oldColumn.aggFunc = null;
                    }
                    // if pivot
                    if (typeof stateItem.pivotIndex === 'number' && stateItem.pivotIndex >= 0) {
                        that.pivotColumns.push(oldColumn);
                    }
                    that.allColumns.push(oldColumn);
                    oldColumnList.splice(oldColumnList.indexOf(oldColumn), 1);
                });
                // anything left over, we got no data for, so add in the column as non-value, non-pivot and hidden
                _.forEach(oldColumnList, function (oldColumn) {
                    oldColumn.visible = false;
                    oldColumn.aggFunc = null;
                    that.allColumns.push(oldColumn);
                });
                this.pivotColumns.sort(function (colA, colB) {
                    return colA.pivotIndex < colB.pivotIndex;
                });
                this.updateModel();
                this.fireColumnsChanged();
            };
            ColumnController.prototype.getColumn = function (key) {
                for (var i = 0; i < this.allColumns.length; i++) {
                    var colDefMatches = this.allColumns[i].colDef === key;
                    var fieldMatches = this.allColumns[i].colDef.field === key;
                    if (colDefMatches || fieldMatches) {
                        return this.allColumns[i];
                    }
                }
            };
            ColumnController.prototype.getDisplayNameForCol = function (column) {
                var colDef = column.colDef;
                var headerValueGetter = colDef.headerValueGetter;
                if (headerValueGetter) {
                    var params = {
                        colDef: colDef,
                        api: this.gridOptionsWrapper.getApi(),
                        context: this.gridOptionsWrapper.getContext()
                    };
                    if (typeof headerValueGetter === 'function') {
                        // valueGetter is a function, so just call it
                        return headerValueGetter(params);
                    }
                    else if (typeof headerValueGetter === 'string') {
                        // valueGetter is an expression, so execute the expression
                        return this.expressionService.evaluate(headerValueGetter, params);
                    }
                    return _.getValue(this.expressionService, undefined, colDef);
                }
                else if (colDef.displayName) {
                    console.warn("ag-grid: Found displayName " + colDef.displayName + ", please use headerName instead, displayName is deprecated.");
                    return colDef.displayName;
                }
                else {
                    return colDef.headerName;
                }
            };
            ColumnController.prototype.addListener = function (listener) {
                this.listeners.push(listener);
            };
            ColumnController.prototype.fireColumnsChanged = function () {
                for (var i = 0; i < this.listeners.length; i++) {
                    this.listeners[i].columnsChanged(this.allColumns, this.pivotColumns, this.valueColumns);
                }
            };
            ColumnController.prototype.getModel = function () {
                return this.model;
            };
            // called by angularGrid
            ColumnController.prototype.setColumns = function (columnDefs) {
                this.checkForDeprecatedItems(columnDefs);
                this.createColumns(columnDefs);
                this.createPivotColumns();
                this.createValueColumns();
                this.updateModel();
                this.fireColumnsChanged();
            };
            ColumnController.prototype.checkForDeprecatedItems = function (columnDefs) {
                if (columnDefs) {
                    for (var i = 0; i < columnDefs.length; i++) {
                        var colDef = columnDefs[i];
                        if (colDef.group !== undefined) {
                            console.warn('ag-grid: ' + colDef.field + ' colDef.group is deprecated, please use colDef.headerGroup');
                            colDef.headerGroup = colDef.group;
                        }
                        if (colDef.groupShow !== undefined) {
                            console.warn('ag-grid: ' + colDef.field + ' colDef.groupShow is deprecated, please use colDef.headerGroupShow');
                            colDef.headerGroupShow = colDef.groupShow;
                        }
                    }
                }
            };
            // called by headerRenderer - when a header is opened or closed
            ColumnController.prototype.headerGroupOpened = function (group) {
                group.expanded = !group.expanded;
                this.updateGroups();
                this.updateDisplayedColumns();
                this.angularGrid.refreshHeaderAndBody();
            };
            // called by toolPanel - when change in columns happens
            ColumnController.prototype.onColumnStateChanged = function () {
                this.updateModel();
                this.angularGrid.refreshHeaderAndBody();
            };
            // called from API
            ColumnController.prototype.hideColumns = function (colIds, hide) {
                for (var i = 0; i < this.allColumns.length; i++) {
                    var idThisCol = this.allColumns[i].colId;
                    var hideThisCol = colIds.indexOf(idThisCol) >= 0;
                    if (hideThisCol) {
                        this.allColumns[i].visible = !hide;
                    }
                }
                this.onColumnStateChanged();
                this.fireColumnsChanged(); // to tell toolbar
            };
            ColumnController.prototype.updateModel = function () {
                this.updateVisibleColumns();
                this.updatePinnedColumns();
                this.buildGroups();
                this.updateGroups();
                this.updateDisplayedColumns();
            };
            ColumnController.prototype.updateDisplayedColumns = function () {
                if (!this.gridOptionsWrapper.isGroupHeaders()) {
                    // if not grouping by headers, then pull visible cols
                    this.displayedColumns = this.visibleColumns;
                }
                else {
                    // if grouping, then only show col as per group rules
                    this.displayedColumns = [];
                    for (var i = 0; i < this.headerGroups.length; i++) {
                        var group = this.headerGroups[i];
                        group.addToVisibleColumns(this.displayedColumns);
                    }
                }
            };
            // public - called from api
            ColumnController.prototype.sizeColumnsToFit = function (gridWidth) {
                // avoid divide by zero
                if (gridWidth <= 0 || this.displayedColumns.length === 0) {
                    return;
                }
                var columnStartWidth = 0; // will contain the starting total width of the cols been spread
                var colsToSpread = []; // all visible cols, except those with avoidSizeToFit
                var widthForSpreading = gridWidth; // grid width minus the columns we are not resizing
                for (var j = 0; j < this.displayedColumns.length; j++) {
                    if (this.displayedColumns[j].colDef.suppressSizeToFit === true) {
                        // don't include col, and remove the width from teh available width
                        widthForSpreading -= this.displayedColumns[j].actualWidth;
                    }
                    else {
                        // include the col
                        colsToSpread.push(this.displayedColumns[j]);
                        columnStartWidth += this.displayedColumns[j].actualWidth;
                    }
                }
                // if no width left over to spread with, do nothing
                if (widthForSpreading <= 0) {
                    return;
                }
                var scale = widthForSpreading / columnStartWidth;
                var pixelsForLastCol = widthForSpreading;
                for (var i = 0; i < (colsToSpread.length - 1); i++) {
                    var column = colsToSpread[i];
                    var newWidth = Math.round(column.actualWidth * scale);
                    column.actualWidth = newWidth;
                    pixelsForLastCol -= newWidth;
                }
                // size the last by whats remaining (this avoids rounding errors that could
                // occur with scaling everything, where it result in some pixels off)
                var lastColumn = colsToSpread[colsToSpread.length - 1];
                lastColumn.actualWidth = pixelsForLastCol;
                // widths set, refresh the gui
                this.angularGrid.refreshHeaderAndBody();
            };
            ColumnController.prototype.buildGroups = function () {
                // if not grouping by headers, do nothing
                if (!this.gridOptionsWrapper.isGroupHeaders()) {
                    this.headerGroups = null;
                    return;
                }
                // split the columns into groups
                var currentGroup = null;
                this.headerGroups = [];
                var that = this;
                var lastColWasPinned = true;
                this.visibleColumns.forEach(function (column) {
                    // do we need a new group, because we move from pinned to non-pinned columns?
                    var endOfPinnedHeader = lastColWasPinned && !column.pinned;
                    if (!column.pinned) {
                        lastColWasPinned = false;
                    }
                    // do we need a new group, because the group names doesn't match from previous col?
                    var groupKeyMismatch = currentGroup && column.colDef.headerGroup !== currentGroup.name;
                    // we don't group columns where no group is specified
                    var colNotInGroup = currentGroup && !currentGroup.name;
                    // do we need a new group, because we are just starting
                    var processingFirstCol = currentGroup === null;
                    var newGroupNeeded = processingFirstCol || endOfPinnedHeader || groupKeyMismatch || colNotInGroup;
                    // create new group, if it's needed
                    if (newGroupNeeded) {
                        var pinned = column.pinned;
                        currentGroup = new HeaderGroup(pinned, column.colDef.headerGroup);
                        that.headerGroups.push(currentGroup);
                    }
                    currentGroup.addColumn(column);
                });
            };
            ColumnController.prototype.updateGroups = function () {
                // if not grouping by headers, do nothing
                if (!this.gridOptionsWrapper.isGroupHeaders()) {
                    return;
                }
                for (var i = 0; i < this.headerGroups.length; i++) {
                    var group = this.headerGroups[i];
                    group.calculateExpandable();
                    group.calculateDisplayedColumns();
                }
            };
            ColumnController.prototype.updateVisibleColumns = function () {
                this.visibleColumns = [];
                // see if we need to insert the default grouping column
                var needAGroupColumn = this.pivotColumns.length > 0 && !this.gridOptionsWrapper.isGroupSuppressAutoColumn() && !this.gridOptionsWrapper.isGroupUseEntireRow();
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                if (needAGroupColumn) {
                    // if one provided by user, use it, otherwise create one
                    var groupColDef = this.gridOptionsWrapper.getGroupColumnDef();
                    if (!groupColDef) {
                        groupColDef = {
                            headerName: localeTextFunc('group', 'Group'),
                            cellRenderer: {
                                renderer: "group"
                            }
                        };
                    }
                    // no group column provided, need to create one here
                    var groupColumn = new Column(groupColDef, this.gridOptionsWrapper.getColWidth());
                    this.visibleColumns.push(groupColumn);
                }
                for (var i = 0; i < this.allColumns.length; i++) {
                    var column = this.allColumns[i];
                    var hideBecauseOfPivot = this.pivotColumns.indexOf(column) >= 0 && this.gridOptionsWrapper.isGroupHidePivotColumns();
                    if (column.visible && !hideBecauseOfPivot) {
                        column.index = this.visibleColumns.length;
                        this.visibleColumns.push(this.allColumns[i]);
                    }
                }
            };
            ColumnController.prototype.updatePinnedColumns = function () {
                var pinnedColumnCount = this.gridOptionsWrapper.getPinnedColCount();
                for (var i = 0; i < this.visibleColumns.length; i++) {
                    var pinned = i < pinnedColumnCount;
                    this.visibleColumns[i].pinned = pinned;
                }
            };
            ColumnController.prototype.createColumns = function (columnDefs) {
                this.allColumns = [];
                var that = this;
                if (columnDefs) {
                    for (var i = 0; i < columnDefs.length; i++) {
                        var colDef = columnDefs[i];
                        // this is messy - we swap in another col def if it's checkbox selection - not happy :(
                        if (colDef === 'checkboxSelection') {
                            colDef = that.selectionRendererFactory.createCheckboxColDef();
                        }
                        var width = that.calculateColInitialWidth(colDef);
                        var column = new Column(colDef, width);
                        that.allColumns.push(column);
                    }
                }
            };
            ColumnController.prototype.createPivotColumns = function () {
                this.pivotColumns = [];
                var groupKeys = this.gridOptionsWrapper.getGroupKeys();
                if (!groupKeys || groupKeys.length <= 0) {
                    return;
                }
                for (var i = 0; i < groupKeys.length; i++) {
                    var groupKey = groupKeys[i];
                    var column = this.getColumn(groupKey);
                    if (!column) {
                        column = this.createDummyColumn(groupKey);
                    }
                    this.pivotColumns.push(column);
                }
            };
            ColumnController.prototype.createValueColumns = function () {
                this.valueColumns = [];
                for (var i = 0; i < this.allColumns.length; i++) {
                    var column = this.allColumns[i];
                    if (column.colDef.aggFunc) {
                        column.aggFunc = column.colDef.aggFunc;
                        this.valueColumns.push(column);
                    }
                }
            };
            ColumnController.prototype.createDummyColumn = function (field) {
                var colDef = {
                    field: field,
                    headerName: field,
                    hide: false
                };
                var width = this.gridOptionsWrapper.getColWidth();
                var column = new Column(colDef, width);
                return column;
            };
            ColumnController.prototype.calculateColInitialWidth = function (colDef) {
                if (!colDef.width) {
                    // if no width defined in colDef, use default
                    return this.gridOptionsWrapper.getColWidth();
                }
                else if (colDef.width < constants.MIN_COL_WIDTH) {
                    // if width in col def to small, set to min width
                    return constants.MIN_COL_WIDTH;
                }
                else {
                    // otherwise use the provided width
                    return colDef.width;
                }
            };
            // private
            // call with true (pinned), false (not-pinned) or undefined (all columns)
            ColumnController.prototype.getTotalColWidth = function (includePinned) {
                var widthSoFar = 0;
                var pinedNotImportant = typeof includePinned !== 'boolean';
                this.displayedColumns.forEach(function (column) {
                    var includeThisCol = pinedNotImportant || column.pinned === includePinned;
                    if (includeThisCol) {
                        widthSoFar += column.actualWidth;
                    }
                });
                return widthSoFar;
            };
            return ColumnController;
        })();
        grid.ColumnController = ColumnController;
        var HeaderGroup = (function () {
            function HeaderGroup(pinned, name) {
                this.allColumns = [];
                this.displayedColumns = [];
                this.expandable = false;
                this.expanded = false;
                this.pinned = pinned;
                this.name = name;
            }
            HeaderGroup.prototype.addColumn = function (column) {
                this.allColumns.push(column);
            };
            // need to check that this group has at least one col showing when both expanded and contracted.
            // if not, then we don't allow expanding and contracting on this group
            HeaderGroup.prototype.calculateExpandable = function () {
                // want to make sure the group doesn't disappear when it's open
                var atLeastOneShowingWhenOpen = false;
                // want to make sure the group doesn't disappear when it's closed
                var atLeastOneShowingWhenClosed = false;
                // want to make sure the group has something to show / hide
                var atLeastOneChangeable = false;
                for (var i = 0, j = this.allColumns.length; i < j; i++) {
                    var column = this.allColumns[i];
                    if (column.colDef.headerGroupShow === 'open') {
                        atLeastOneShowingWhenOpen = true;
                        atLeastOneChangeable = true;
                    }
                    else if (column.colDef.headerGroupShow === 'closed') {
                        atLeastOneShowingWhenClosed = true;
                        atLeastOneChangeable = true;
                    }
                    else {
                        atLeastOneShowingWhenOpen = true;
                        atLeastOneShowingWhenClosed = true;
                    }
                }
                this.expandable = atLeastOneShowingWhenOpen && atLeastOneShowingWhenClosed && atLeastOneChangeable;
            };
            HeaderGroup.prototype.calculateDisplayedColumns = function () {
                // clear out last time we calculated
                this.displayedColumns = [];
                // it not expandable, everything is visible
                if (!this.expandable) {
                    this.displayedColumns = this.allColumns;
                    return;
                }
                for (var i = 0, j = this.allColumns.length; i < j; i++) {
                    var column = this.allColumns[i];
                    switch (column.colDef.headerGroupShow) {
                        case 'open':
                            // when set to open, only show col if group is open
                            if (this.expanded) {
                                this.displayedColumns.push(column);
                            }
                            break;
                        case 'closed':
                            // when set to open, only show col if group is open
                            if (!this.expanded) {
                                this.displayedColumns.push(column);
                            }
                            break;
                        default:
                            // default is always show the column
                            this.displayedColumns.push(column);
                            break;
                    }
                }
            };
            // should replace with utils method 'add all'
            HeaderGroup.prototype.addToVisibleColumns = function (colsToAdd) {
                for (var i = 0; i < this.displayedColumns.length; i++) {
                    var column = this.displayedColumns[i];
                    colsToAdd.push(column);
                }
            };
            return HeaderGroup;
        })();
        var Column = (function () {
            function Column(colDef, actualWidth) {
                this.colDef = colDef;
                this.actualWidth = actualWidth;
                this.visible = !colDef.hide;
                // in the future, the colKey might be something other than the index
                if (colDef.colId) {
                    this.colId = colDef.colId;
                }
                else if (colDef.field) {
                    this.colId = colDef.field;
                }
                else {
                    this.colId = '' + Column.colIdSequence++;
                }
            }
            Column.colIdSequence = 0;
            return Column;
        })();
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var ExpressionService = (function () {
            function ExpressionService() {
                this.expressionToFunctionCache = {};
            }
            ExpressionService.prototype.evaluate = function (expression, params) {
                try {
                    var javaScriptFunction = this.createExpressionFunction(expression);
                    var result = javaScriptFunction(params.value, params.context, params.node, params.data, params.colDef, params.rowIndex, params.api);
                    return result;
                }
                catch (e) {
                    // the expression failed, which can happen, as it's the client that
                    // provides the expression. so print a nice message
                    console.error('Processing of the expression failed');
                    console.error('Expression = ' + expression);
                    console.error('Exception = ' + e);
                    return null;
                }
            };
            ExpressionService.prototype.createExpressionFunction = function (expression) {
                // check cache first
                if (this.expressionToFunctionCache[expression]) {
                    return this.expressionToFunctionCache[expression];
                }
                // if not found in cache, return the function
                var functionBody = this.createFunctionBody(expression);
                var theFunction = new Function('x, ctx, node, data, colDef, rowIndex, api', functionBody);
                // store in cache
                this.expressionToFunctionCache[expression] = theFunction;
                return theFunction;
            };
            ExpressionService.prototype.createFunctionBody = function (expression) {
                // if the expression has the 'return' word in it, then use as is,
                // if not, then wrap it with return and ';' to make a function
                if (expression.indexOf('return') >= 0) {
                    return expression;
                }
                else {
                    return 'return ' + expression + ';';
                }
            };
            return ExpressionService;
        })();
        grid.ExpressionService = ExpressionService;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="constants.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var DEFAULT_ROW_HEIGHT = 30;
        var constants = grid.Constants;
        function isTrue(value) {
            return value === true || value === 'true';
        }
        var GridOptionsWrapper = (function () {
            function GridOptionsWrapper(gridOptions) {
                this.gridOptions = gridOptions;
                this.setupDefaults();
            }
            GridOptionsWrapper.prototype.isRowSelection = function () {
                return this.gridOptions.rowSelection === "single" || this.gridOptions.rowSelection === "multiple";
            };
            GridOptionsWrapper.prototype.isRowDeselection = function () {
                return isTrue(this.gridOptions.rowDeselection);
            };
            GridOptionsWrapper.prototype.isRowSelectionMulti = function () {
                return this.gridOptions.rowSelection === 'multiple';
            };
            GridOptionsWrapper.prototype.getContext = function () {
                return this.gridOptions.context;
            };
            GridOptionsWrapper.prototype.isVirtualPaging = function () {
                return isTrue(this.gridOptions.virtualPaging);
            };
            GridOptionsWrapper.prototype.isShowToolPanel = function () {
                return isTrue(this.gridOptions.showToolPanel);
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressPivot = function () {
                return isTrue(this.gridOptions.toolPanelSuppressPivot);
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressValues = function () {
                return isTrue(this.gridOptions.toolPanelSuppressValues);
            };
            GridOptionsWrapper.prototype.isRowsAlreadyGrouped = function () {
                return isTrue(this.gridOptions.rowsAlreadyGrouped);
            };
            GridOptionsWrapper.prototype.isGroupSelectsChildren = function () {
                return isTrue(this.gridOptions.groupSelectsChildren);
            };
            GridOptionsWrapper.prototype.isGroupHidePivotColumns = function () {
                return isTrue(this.gridOptions.groupHidePivotColumns);
            };
            GridOptionsWrapper.prototype.isGroupIncludeFooter = function () {
                return isTrue(this.gridOptions.groupIncludeFooter);
            };
            GridOptionsWrapper.prototype.isSuppressRowClickSelection = function () {
                return isTrue(this.gridOptions.suppressRowClickSelection);
            };
            GridOptionsWrapper.prototype.isSuppressCellSelection = function () {
                return isTrue(this.gridOptions.suppressCellSelection);
            };
            GridOptionsWrapper.prototype.isSuppressUnSort = function () {
                return isTrue(this.gridOptions.suppressUnSort);
            };
            GridOptionsWrapper.prototype.isSuppressMultiSort = function () {
                return isTrue(this.gridOptions.suppressMultiSort);
            };
            GridOptionsWrapper.prototype.isGroupSuppressAutoColumn = function () {
                return isTrue(this.gridOptions.groupSuppressAutoColumn);
            };
            GridOptionsWrapper.prototype.isGroupHeaders = function () {
                return isTrue(this.gridOptions.groupHeaders);
            };
            GridOptionsWrapper.prototype.isDontUseScrolls = function () {
                return isTrue(this.gridOptions.dontUseScrolls);
            };
            GridOptionsWrapper.prototype.isSuppressDescSort = function () {
                return isTrue(this.gridOptions.suppressDescSort);
            };
            GridOptionsWrapper.prototype.isUnSortIcon = function () {
                return isTrue(this.gridOptions.unSortIcon);
            };
            GridOptionsWrapper.prototype.getRowStyle = function () {
                return this.gridOptions.rowStyle;
            };
            GridOptionsWrapper.prototype.getRowClass = function () {
                return this.gridOptions.rowClass;
            };
            GridOptionsWrapper.prototype.getHeaderCellRenderer = function () {
                return this.gridOptions.headerCellRenderer;
            };
            GridOptionsWrapper.prototype.getApi = function () {
                return this.gridOptions.api;
            };
            GridOptionsWrapper.prototype.isEnableColResize = function () {
                return isTrue(this.gridOptions.enableColResize);
            };
            GridOptionsWrapper.prototype.getGroupDefaultExpanded = function () {
                return this.gridOptions.groupDefaultExpanded;
            };
            GridOptionsWrapper.prototype.getGroupKeys = function () {
                return this.gridOptions.groupKeys;
            };
            GridOptionsWrapper.prototype.getGroupAggFunction = function () {
                return this.gridOptions.groupAggFunction;
            };
            GridOptionsWrapper.prototype.getGroupAggFields = function () {
                return this.gridOptions.groupAggFields;
            };
            GridOptionsWrapper.prototype.getAllRows = function () {
                return this.gridOptions.rowData;
            };
            GridOptionsWrapper.prototype.isGroupUseEntireRow = function () {
                return isTrue(this.gridOptions.groupUseEntireRow);
            };
            GridOptionsWrapper.prototype.getGroupColumnDef = function () {
                return this.gridOptions.groupColumnDef;
            };
            GridOptionsWrapper.prototype.isAngularCompileRows = function () {
                return isTrue(this.gridOptions.angularCompileRows);
            };
            GridOptionsWrapper.prototype.isAngularCompileFilters = function () {
                return isTrue(this.gridOptions.angularCompileFilters);
            };
            GridOptionsWrapper.prototype.isAngularCompileHeaders = function () {
                return isTrue(this.gridOptions.angularCompileHeaders);
            };
            GridOptionsWrapper.prototype.getColumnDefs = function () {
                return this.gridOptions.columnDefs;
            };
            GridOptionsWrapper.prototype.getRowHeight = function () {
                return this.gridOptions.rowHeight;
            };
            GridOptionsWrapper.prototype.getModelUpdated = function () {
                return this.gridOptions.modelUpdated;
            };
            GridOptionsWrapper.prototype.getCellClicked = function () {
                return this.gridOptions.cellClicked;
            };
            GridOptionsWrapper.prototype.getCellDoubleClicked = function () {
                return this.gridOptions.cellDoubleClicked;
            };
            GridOptionsWrapper.prototype.getCellValueChanged = function () {
                return this.gridOptions.cellValueChanged;
            };
            GridOptionsWrapper.prototype.getCellFocused = function () {
                return this.gridOptions.cellFocused;
            };
            GridOptionsWrapper.prototype.getRowSelected = function () {
                return this.gridOptions.rowSelected;
            };
            GridOptionsWrapper.prototype.getSelectionChanged = function () {
                return this.gridOptions.selectionChanged;
            };
            GridOptionsWrapper.prototype.getVirtualRowRemoved = function () {
                return this.gridOptions.virtualRowRemoved;
            };
            GridOptionsWrapper.prototype.getDatasource = function () {
                return this.gridOptions.datasource;
            };
            GridOptionsWrapper.prototype.getReady = function () {
                return this.gridOptions.ready;
            };
            GridOptionsWrapper.prototype.getRowBuffer = function () {
                return this.gridOptions.rowBuffer;
            };
            GridOptionsWrapper.prototype.isEnableSorting = function () {
                return isTrue(this.gridOptions.enableSorting) || isTrue(this.gridOptions.enableServerSideSorting);
            };
            GridOptionsWrapper.prototype.isEnableServerSideSorting = function () {
                return isTrue(this.gridOptions.enableServerSideSorting);
            };
            GridOptionsWrapper.prototype.isEnableFilter = function () {
                return isTrue(this.gridOptions.enableFilter) || isTrue(this.gridOptions.enableServerSideFilter);
            };
            GridOptionsWrapper.prototype.isEnableServerSideFilter = function () {
                return this.gridOptions.enableServerSideFilter;
            };
            GridOptionsWrapper.prototype.setSelectedRows = function (newSelectedRows) {
                return this.gridOptions.selectedRows = newSelectedRows;
            };
            GridOptionsWrapper.prototype.setSelectedNodesById = function (newSelectedNodes) {
                return this.gridOptions.selectedNodesById = newSelectedNodes;
            };
            GridOptionsWrapper.prototype.getIcons = function () {
                return this.gridOptions.icons;
            };
            GridOptionsWrapper.prototype.getGroupRowInnerRenderer = function () {
                if (this.gridOptions.groupInnerRenderer) {
                    console.warn('ag-grid: as of v1.10.0 (21st Jun 2015) groupInnerRenderer is now called groupRowInnerRenderer. Please change you code as groupInnerRenderer is deprecated.');
                    return this.gridOptions.groupInnerRenderer;
                }
                else {
                    return this.gridOptions.groupRowInnerRenderer;
                }
            };
            GridOptionsWrapper.prototype.getColWidth = function () {
                if (typeof this.gridOptions.colWidth !== 'number' || this.gridOptions.colWidth < constants.MIN_COL_WIDTH) {
                    return 200;
                }
                else {
                    return this.gridOptions.colWidth;
                }
            };
            GridOptionsWrapper.prototype.getHeaderHeight = function () {
                if (typeof this.gridOptions.headerHeight === 'number') {
                    // if header height provided, used it
                    return this.gridOptions.headerHeight;
                }
                else {
                    // otherwise return 25 if no grouping, 50 if grouping
                    if (this.isGroupHeaders()) {
                        return 50;
                    }
                    else {
                        return 25;
                    }
                }
            };
            GridOptionsWrapper.prototype.setupDefaults = function () {
                if (!this.gridOptions.rowHeight) {
                    this.gridOptions.rowHeight = DEFAULT_ROW_HEIGHT;
                }
            };
            GridOptionsWrapper.prototype.getPinnedColCount = function () {
                // if not using scrolls, then pinned columns doesn't make
                // sense, so always return 0
                if (this.isDontUseScrolls()) {
                    return 0;
                }
                if (this.gridOptions.pinnedColumnCount) {
                    //in case user puts in a string, cast to number
                    return Number(this.gridOptions.pinnedColumnCount);
                }
                else {
                    return 0;
                }
            };
            GridOptionsWrapper.prototype.getLocaleTextFunc = function () {
                var that = this;
                return function (key, defaultValue) {
                    var localeText = that.gridOptions.localeText;
                    if (localeText && localeText[key]) {
                        return localeText[key];
                    }
                    else {
                        return defaultValue;
                    }
                };
            };
            return GridOptionsWrapper;
        })();
        grid.GridOptionsWrapper = GridOptionsWrapper;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var template = '<div>' + '<div>' + '<select class="ag-filter-select" id="filterType">' + '<option value="1">[CONTAINS]</option>' + '<option value="2">[EQUALS]</option>' + '<option value="3">[STARTS WITH]</option>' + '<option value="4">[ENDS WITH]</option>' + '</select>' + '</div>' + '<div>' + '<input class="ag-filter-filter" id="filterText" type="text" placeholder="[FILTER...]"/>' + '</div>' + '</div>';
        var CONTAINS = 1;
        var EQUALS = 2;
        var STARTS_WITH = 3;
        var ENDS_WITH = 4;
        var TextFilter = (function () {
            function TextFilter(params) {
                this.filterParams = params.filterParams;
                this.filterChangedCallback = params.filterChangedCallback;
                this.localeTextFunc = params.localeTextFunc;
                this.valueGetter = params.valueGetter;
                this.createGui();
                this.filterText = null;
                this.filterType = CONTAINS;
                this.createApi();
            }
            /* public */
            TextFilter.prototype.onNewRowsLoaded = function () {
                var keepSelection = this.filterParams && this.filterParams.newRowsAction === 'keep';
                if (!keepSelection) {
                    this.api.setType(CONTAINS);
                    this.api.setFilter(null);
                }
            };
            /* public */
            TextFilter.prototype.afterGuiAttached = function () {
                this.eFilterTextField.focus();
            };
            /* public */
            TextFilter.prototype.doesFilterPass = function (node) {
                if (!this.filterText) {
                    return true;
                }
                var value = this.valueGetter(node);
                if (!value) {
                    return false;
                }
                var valueLowerCase = value.toString().toLowerCase();
                switch (this.filterType) {
                    case CONTAINS:
                        return valueLowerCase.indexOf(this.filterText) >= 0;
                    case EQUALS:
                        return valueLowerCase === this.filterText;
                    case STARTS_WITH:
                        return valueLowerCase.indexOf(this.filterText) === 0;
                    case ENDS_WITH:
                        var index = valueLowerCase.indexOf(this.filterText);
                        return index >= 0 && index === (valueLowerCase.length - this.filterText.length);
                    default:
                        // should never happen
                        console.warn('invalid filter type ' + this.filterType);
                        return false;
                }
            };
            /* public */
            TextFilter.prototype.getGui = function () {
                return this.eGui;
            };
            /* public */
            TextFilter.prototype.isFilterActive = function () {
                return this.filterText !== null;
            };
            TextFilter.prototype.createTemplate = function () {
                return template.replace('[FILTER...]', this.localeTextFunc('filterOoo', 'Filter...')).replace('[EQUALS]', this.localeTextFunc('equals', 'Equals')).replace('[CONTAINS]', this.localeTextFunc('contains', 'Contains')).replace('[STARTS WITH]', this.localeTextFunc('startsWith', 'Starts with')).replace('[ENDS WITH]', this.localeTextFunc('endsWith', 'Ends with'));
            };
            TextFilter.prototype.createGui = function () {
                this.eGui = utils.loadTemplate(this.createTemplate());
                this.eFilterTextField = this.eGui.querySelector("#filterText");
                this.eTypeSelect = this.eGui.querySelector("#filterType");
                utils.addChangeListener(this.eFilterTextField, this.onFilterChanged.bind(this));
                this.eTypeSelect.addEventListener("change", this.onTypeChanged.bind(this));
            };
            TextFilter.prototype.onTypeChanged = function () {
                this.filterType = parseInt(this.eTypeSelect.value);
                this.filterChangedCallback();
            };
            TextFilter.prototype.onFilterChanged = function () {
                var filterText = utils.makeNull(this.eFilterTextField.value);
                if (filterText && filterText.trim() === '') {
                    filterText = null;
                }
                if (filterText) {
                    this.filterText = filterText.toLowerCase();
                }
                else {
                    this.filterText = null;
                }
                this.filterChangedCallback();
            };
            TextFilter.prototype.createApi = function () {
                var that = this;
                this.api = {
                    EQUALS: EQUALS,
                    CONTAINS: CONTAINS,
                    STARTS_WITH: STARTS_WITH,
                    ENDS_WITH: ENDS_WITH,
                    setType: function (type) {
                        that.filterType = type;
                        that.eTypeSelect.value = type;
                    },
                    setFilter: function (filter) {
                        filter = utils.makeNull(filter);
                        if (filter) {
                            that.filterText = filter.toLowerCase();
                            that.eFilterTextField.value = filter;
                        }
                        else {
                            that.filterText = null;
                            that.eFilterTextField.value = null;
                        }
                    },
                    getType: function () {
                        return that.filterType;
                    },
                    getFilter: function () {
                        return that.filterText;
                    },
                    getModel: function () {
                        if (that.isFilterActive()) {
                            return {
                                type: that.filterType,
                                filter: that.filterText
                            };
                        }
                        else {
                            return null;
                        }
                    },
                    setModel: function (dataModel) {
                        if (dataModel) {
                            this.setType(dataModel.type);
                            this.setFilter(dataModel.filter);
                        }
                        else {
                            this.setFilter(null);
                        }
                    }
                };
            };
            TextFilter.prototype.getApi = function () {
                return this.api;
            };
            return TextFilter;
        })();
        grid.TextFilter = TextFilter;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var template = '<div>' + '<div>' + '<select class="ag-filter-select" id="filterType">' + '<option value="1">[EQUALS]</option>' + '<option value="2">[LESS THAN]</option>' + '<option value="3">[GREATER THAN]</option>' + '</select>' + '</div>' + '<div>' + '<input class="ag-filter-filter" id="filterText" type="text" placeholder="[FILTER...]"/>' + '</div>' + '</div>';
        var EQUALS = 1;
        var LESS_THAN = 2;
        var GREATER_THAN = 3;
        var NumberFilter = (function () {
            function NumberFilter(params) {
                this.filterParams = params.filterParams;
                this.filterChangedCallback = params.filterChangedCallback;
                this.localeTextFunc = params.localeTextFunc;
                this.valueGetter = params.valueGetter;
                this.createGui();
                this.filterNumber = null;
                this.filterType = EQUALS;
                this.createApi();
            }
            /* public */
            NumberFilter.prototype.onNewRowsLoaded = function () {
                var keepSelection = this.filterParams && this.filterParams.newRowsAction === 'keep';
                if (!keepSelection) {
                    this.api.setType(EQUALS);
                    this.api.setFilter(null);
                }
            };
            /* public */
            NumberFilter.prototype.afterGuiAttached = function () {
                this.eFilterTextField.focus();
            };
            /* public */
            NumberFilter.prototype.doesFilterPass = function (node) {
                if (this.filterNumber === null) {
                    return true;
                }
                var value = this.valueGetter(node);
                if (!value && value !== 0) {
                    return false;
                }
                var valueAsNumber;
                if (typeof value === 'number') {
                    valueAsNumber = value;
                }
                else {
                    valueAsNumber = parseFloat(value);
                }
                switch (this.filterType) {
                    case EQUALS:
                        return valueAsNumber === this.filterNumber;
                    case LESS_THAN:
                        return valueAsNumber <= this.filterNumber;
                    case GREATER_THAN:
                        return valueAsNumber >= this.filterNumber;
                    default:
                        // should never happen
                        console.warn('invalid filter type ' + this.filterType);
                        return false;
                }
            };
            /* public */
            NumberFilter.prototype.getGui = function () {
                return this.eGui;
            };
            /* public */
            NumberFilter.prototype.isFilterActive = function () {
                return this.filterNumber !== null;
            };
            NumberFilter.prototype.createTemplate = function () {
                return template.replace('[FILTER...]', this.localeTextFunc('filterOoo', 'Filter...')).replace('[EQUALS]', this.localeTextFunc('equals', 'Equals')).replace('[LESS THAN]', this.localeTextFunc('lessThan', 'Less than')).replace('[GREATER THAN]', this.localeTextFunc('greaterThan', 'Greater than'));
            };
            NumberFilter.prototype.createGui = function () {
                this.eGui = utils.loadTemplate(this.createTemplate());
                this.eFilterTextField = this.eGui.querySelector("#filterText");
                this.eTypeSelect = this.eGui.querySelector("#filterType");
                utils.addChangeListener(this.eFilterTextField, this.onFilterChanged.bind(this));
                this.eTypeSelect.addEventListener("change", this.onTypeChanged.bind(this));
            };
            NumberFilter.prototype.onTypeChanged = function () {
                this.filterType = parseInt(this.eTypeSelect.value);
                this.filterChangedCallback();
            };
            NumberFilter.prototype.onFilterChanged = function () {
                var filterText = utils.makeNull(this.eFilterTextField.value);
                if (filterText && filterText.trim() === '') {
                    filterText = null;
                }
                if (filterText) {
                    this.filterNumber = parseFloat(filterText);
                }
                else {
                    this.filterNumber = null;
                }
                this.filterChangedCallback();
            };
            NumberFilter.prototype.createApi = function () {
                var that = this;
                this.api = {
                    EQUALS: EQUALS,
                    LESS_THAN: LESS_THAN,
                    GREATER_THAN: GREATER_THAN,
                    setType: function (type) {
                        that.filterType = type;
                        that.eTypeSelect.value = type;
                    },
                    setFilter: function (filter) {
                        filter = utils.makeNull(filter);
                        if (filter !== null && !(typeof filter === 'number')) {
                            filter = parseFloat(filter);
                        }
                        that.filterNumber = filter;
                        that.eFilterTextField.value = filter;
                    },
                    getType: function () {
                        return that.filterType;
                    },
                    getFilter: function () {
                        return that.filterNumber;
                    },
                    getModel: function () {
                        if (that.isFilterActive()) {
                            return {
                                type: that.filterType,
                                filter: that.filterNumber
                            };
                        }
                        else {
                            return null;
                        }
                    },
                    setModel: function (dataModel) {
                        if (dataModel) {
                            this.setType(dataModel.type);
                            this.setFilter(dataModel.filter);
                        }
                        else {
                            this.setFilter(null);
                        }
                    }
                };
            };
            NumberFilter.prototype.getApi = function () {
                return this.api;
            };
            return NumberFilter;
        })();
        grid.NumberFilter = NumberFilter;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var SetFilterModel = (function () {
            function SetFilterModel(colDef, rowModel, valueGetter) {
                this.colDef = colDef;
                this.rowModel = rowModel;
                this.valueGetter = valueGetter;
                this.createUniqueValues();
                // by default, no filter, so we display everything
                this.displayedValues = this.uniqueValues;
                this.miniFilter = null;
                //we use a map rather than an array for the selected values as the lookup
                //for a map is much faster than the lookup for an array, especially when
                //the length of the array is thousands of records long
                this.selectedValuesMap = {};
                this.selectEverything();
            }
            SetFilterModel.prototype.refreshUniqueValues = function (keepSelection) {
                this.createUniqueValues();
                var oldModel = Object.keys(this.selectedValuesMap);
                this.selectedValuesMap = {};
                this.filterDisplayedValues();
                if (keepSelection) {
                    this.setModel(oldModel);
                }
                else {
                    this.selectEverything();
                }
            };
            SetFilterModel.prototype.createUniqueValues = function () {
                if (this.colDef.filterParams && this.colDef.filterParams.values) {
                    this.uniqueValues = utils.toStrings(this.colDef.filterParams.values);
                }
                else {
                    this.uniqueValues = utils.toStrings(this.iterateThroughNodesForValues());
                }
                if (this.colDef.comparator) {
                    this.uniqueValues.sort(this.colDef.comparator);
                }
                else {
                    this.uniqueValues.sort(utils.defaultComparator);
                }
            };
            SetFilterModel.prototype.iterateThroughNodesForValues = function () {
                var uniqueCheck = {};
                var result = [];
                var that = this;
                function recursivelyProcess(nodes) {
                    for (var i = 0; i < nodes.length; i++) {
                        var node = nodes[i];
                        if (node.group && !node.footer) {
                            // group node, so dig deeper
                            recursivelyProcess(node.children);
                        }
                        else {
                            var value = that.valueGetter(node);
                            if (value === "" || value === undefined) {
                                value = null;
                            }
                            if (!uniqueCheck.hasOwnProperty(value)) {
                                result.push(value);
                                uniqueCheck[value] = 1;
                            }
                        }
                    }
                }
                var topLevelNodes = this.rowModel.getTopLevelNodes();
                recursivelyProcess(topLevelNodes);
                return result;
            };
            //sets mini filter. returns true if it changed from last value, otherwise false
            SetFilterModel.prototype.setMiniFilter = function (newMiniFilter) {
                newMiniFilter = utils.makeNull(newMiniFilter);
                if (this.miniFilter === newMiniFilter) {
                    //do nothing if filter has not changed
                    return false;
                }
                this.miniFilter = newMiniFilter;
                this.filterDisplayedValues();
                return true;
            };
            SetFilterModel.prototype.getMiniFilter = function () {
                return this.miniFilter;
            };
            SetFilterModel.prototype.filterDisplayedValues = function () {
                // if no filter, just use the unique values
                if (this.miniFilter === null) {
                    this.displayedValues = this.uniqueValues;
                    return;
                }
                // if filter present, we filter down the list
                this.displayedValues = [];
                var miniFilterUpperCase = this.miniFilter.toUpperCase();
                for (var i = 0, l = this.uniqueValues.length; i < l; i++) {
                    var uniqueValue = this.uniqueValues[i];
                    if (uniqueValue !== null && uniqueValue.toString().toUpperCase().indexOf(miniFilterUpperCase) >= 0) {
                        this.displayedValues.push(uniqueValue);
                    }
                }
            };
            SetFilterModel.prototype.getDisplayedValueCount = function () {
                return this.displayedValues.length;
            };
            SetFilterModel.prototype.getDisplayedValue = function (index) {
                return this.displayedValues[index];
            };
            SetFilterModel.prototype.selectEverything = function () {
                var count = this.uniqueValues.length;
                for (var i = 0; i < count; i++) {
                    var value = this.uniqueValues[i];
                    this.selectedValuesMap[value] = null;
                }
                this.selectedValuesCount = count;
            };
            SetFilterModel.prototype.isFilterActive = function () {
                return this.uniqueValues.length !== this.selectedValuesCount;
            };
            SetFilterModel.prototype.selectNothing = function () {
                this.selectedValuesMap = {};
                this.selectedValuesCount = 0;
            };
            SetFilterModel.prototype.getUniqueValueCount = function () {
                return this.uniqueValues.length;
            };
            SetFilterModel.prototype.getUniqueValue = function (index) {
                return this.uniqueValues[index];
            };
            SetFilterModel.prototype.unselectValue = function (value) {
                if (this.selectedValuesMap[value] !== undefined) {
                    delete this.selectedValuesMap[value];
                    this.selectedValuesCount--;
                }
            };
            SetFilterModel.prototype.selectValue = function (value) {
                if (this.selectedValuesMap[value] === undefined) {
                    this.selectedValuesMap[value] = null;
                    this.selectedValuesCount++;
                }
            };
            SetFilterModel.prototype.isValueSelected = function (value) {
                return this.selectedValuesMap[value] !== undefined;
            };
            SetFilterModel.prototype.isEverythingSelected = function () {
                return this.uniqueValues.length === this.selectedValuesCount;
            };
            SetFilterModel.prototype.isNothingSelected = function () {
                return this.uniqueValues.length === 0;
            };
            SetFilterModel.prototype.getModel = function () {
                if (!this.isFilterActive()) {
                    return null;
                }
                var selectedValues = [];
                utils.iterateObject(this.selectedValuesMap, function (key) {
                    selectedValues.push(key);
                });
                return selectedValues;
            };
            SetFilterModel.prototype.setModel = function (model) {
                if (model) {
                    this.selectNothing();
                    for (var i = 0; i < model.length; i++) {
                        var newValue = model[i];
                        if (this.uniqueValues.indexOf(newValue) >= 0) {
                            this.selectValue(model[i]);
                        }
                        else {
                            console.warn('Value ' + newValue + ' is not a valid value for filter');
                        }
                    }
                }
                else {
                    this.selectEverything();
                }
            };
            return SetFilterModel;
        })();
        grid.SetFilterModel = SetFilterModel;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
/// <reference path="setFilterModel.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var template = '<div>' + '<div class="ag-filter-header-container">' + '<input class="ag-filter-filter" type="text" placeholder="[SEARCH...]"/>' + '</div>' + '<div class="ag-filter-header-container">' + '<label>' + '<input id="selectAll" type="checkbox" class="ag-filter-checkbox"/>' + '([SELECT ALL])' + '</label>' + '</div>' + '<div class="ag-filter-list-viewport">' + '<div class="ag-filter-list-container">' + '<div id="itemForRepeat" class="ag-filter-item">' + '<label>' + '<input type="checkbox" class="ag-filter-checkbox" filter-checkbox="true"/>' + '<span class="ag-filter-value"></span>' + '</label>' + '</div>' + '</div>' + '</div>' + '</div>';
        var DEFAULT_ROW_HEIGHT = 20;
        var SetFilter = (function () {
            function SetFilter(params) {
                this.filterParams = params.filterParams;
                this.rowHeight = (this.filterParams && this.filterParams.cellHeight) ? this.filterParams.cellHeight : DEFAULT_ROW_HEIGHT;
                this.model = new grid.SetFilterModel(params.colDef, params.rowModel, params.valueGetter);
                this.filterChangedCallback = params.filterChangedCallback;
                this.valueGetter = params.valueGetter;
                this.rowsInBodyContainer = {};
                this.colDef = params.colDef;
                this.localeTextFunc = params.localeTextFunc;
                if (this.filterParams) {
                    this.cellRenderer = this.filterParams.cellRenderer;
                }
                this.createGui();
                this.addScrollListener();
                this.createApi();
            }
            // we need to have the gui attached before we can draw the virtual rows, as the
            // virtual row logic needs info about the gui state
            /* public */
            SetFilter.prototype.afterGuiAttached = function () {
                this.drawVirtualRows();
            };
            /* public */
            SetFilter.prototype.isFilterActive = function () {
                return this.model.isFilterActive();
            };
            /* public */
            SetFilter.prototype.doesFilterPass = function (node) {
                //if no filter, always pass
                if (this.model.isEverythingSelected()) {
                    return true;
                }
                //if nothing selected in filter, always fail
                if (this.model.isNothingSelected()) {
                    return false;
                }
                var value = this.valueGetter(node);
                value = utils.makeNull(value);
                var filterPassed = this.model.isValueSelected(value);
                return filterPassed;
            };
            /* public */
            SetFilter.prototype.getGui = function () {
                return this.eGui;
            };
            /* public */
            SetFilter.prototype.onNewRowsLoaded = function () {
                var keepSelection = this.filterParams && this.filterParams.newRowsAction === 'keep';
                // default is reset
                this.model.refreshUniqueValues(keepSelection);
                this.setContainerHeight();
                this.refreshVirtualRows();
            };
            SetFilter.prototype.createTemplate = function () {
                return template.replace('[SELECT ALL]', this.localeTextFunc('selectAll', 'Select All')).replace('[SEARCH...]', this.localeTextFunc('searchOoo', 'Search...'));
            };
            SetFilter.prototype.createGui = function () {
                var _this = this;
                this.eGui = utils.loadTemplate(this.createTemplate());
                this.eListContainer = this.eGui.querySelector(".ag-filter-list-container");
                this.eFilterValueTemplate = this.eGui.querySelector("#itemForRepeat");
                this.eSelectAll = this.eGui.querySelector("#selectAll");
                this.eListViewport = this.eGui.querySelector(".ag-filter-list-viewport");
                this.eMiniFilter = this.eGui.querySelector(".ag-filter-filter");
                this.eListContainer.style.height = (this.model.getUniqueValueCount() * this.rowHeight) + "px";
                this.setContainerHeight();
                this.eMiniFilter.value = this.model.getMiniFilter();
                utils.addChangeListener(this.eMiniFilter, function () {
                    _this.onMiniFilterChanged();
                });
                utils.removeAllChildren(this.eListContainer);
                this.eSelectAll.onclick = this.onSelectAll.bind(this);
                if (this.model.isEverythingSelected()) {
                    this.eSelectAll.indeterminate = false;
                    this.eSelectAll.checked = true;
                }
                else if (this.model.isNothingSelected()) {
                    this.eSelectAll.indeterminate = false;
                    this.eSelectAll.checked = false;
                }
                else {
                    this.eSelectAll.indeterminate = true;
                }
            };
            SetFilter.prototype.setContainerHeight = function () {
                this.eListContainer.style.height = (this.model.getDisplayedValueCount() * this.rowHeight) + "px";
            };
            SetFilter.prototype.drawVirtualRows = function () {
                var topPixel = this.eListViewport.scrollTop;
                var bottomPixel = topPixel + this.eListViewport.offsetHeight;
                var firstRow = Math.floor(topPixel / this.rowHeight);
                var lastRow = Math.floor(bottomPixel / this.rowHeight);
                this.ensureRowsRendered(firstRow, lastRow);
            };
            SetFilter.prototype.ensureRowsRendered = function (start, finish) {
                var _this = this;
                //at the end, this array will contain the items we need to remove
                var rowsToRemove = Object.keys(this.rowsInBodyContainer);
                for (var rowIndex = start; rowIndex <= finish; rowIndex++) {
                    //see if item already there, and if yes, take it out of the 'to remove' array
                    if (rowsToRemove.indexOf(rowIndex.toString()) >= 0) {
                        rowsToRemove.splice(rowsToRemove.indexOf(rowIndex.toString()), 1);
                        continue;
                    }
                    //check this row actually exists (in case overflow buffer window exceeds real data)
                    if (this.model.getDisplayedValueCount() > rowIndex) {
                        var value = this.model.getDisplayedValue(rowIndex);
                        _this.insertRow(value, rowIndex);
                    }
                }
                //at this point, everything in our 'rowsToRemove' . . .
                this.removeVirtualRows(rowsToRemove);
            };
            //takes array of row id's
            SetFilter.prototype.removeVirtualRows = function (rowsToRemove) {
                var _this = this;
                rowsToRemove.forEach(function (indexToRemove) {
                    var eRowToRemove = _this.rowsInBodyContainer[indexToRemove];
                    _this.eListContainer.removeChild(eRowToRemove);
                    delete _this.rowsInBodyContainer[indexToRemove];
                });
            };
            SetFilter.prototype.insertRow = function (value, rowIndex) {
                var _this = this;
                var eFilterValue = this.eFilterValueTemplate.cloneNode(true);
                var valueElement = eFilterValue.querySelector(".ag-filter-value");
                if (this.cellRenderer) {
                    //renderer provided, so use it
                    var resultFromRenderer = this.cellRenderer({
                        value: value
                    });
                    if (utils.isNode(resultFromRenderer)) {
                        //a dom node or element was returned, so add child
                        valueElement.appendChild(resultFromRenderer);
                    }
                    else {
                        //otherwise assume it was html, so just insert
                        valueElement.innerHTML = resultFromRenderer;
                    }
                }
                else {
                    //otherwise display as a string
                    var blanksText = '(' + this.localeTextFunc('blanks', 'Blanks') + ')';
                    var displayNameOfValue = value === null ? blanksText : value;
                    valueElement.innerHTML = displayNameOfValue;
                }
                var eCheckbox = eFilterValue.querySelector("input");
                eCheckbox.checked = this.model.isValueSelected(value);
                eCheckbox.onclick = function () {
                    _this.onCheckboxClicked(eCheckbox, value);
                };
                eFilterValue.style.top = (this.rowHeight * rowIndex) + "px";
                this.eListContainer.appendChild(eFilterValue);
                this.rowsInBodyContainer[rowIndex] = eFilterValue;
            };
            SetFilter.prototype.onCheckboxClicked = function (eCheckbox, value) {
                var checked = eCheckbox.checked;
                if (checked) {
                    this.model.selectValue(value);
                    if (this.model.isEverythingSelected()) {
                        this.eSelectAll.indeterminate = false;
                        this.eSelectAll.checked = true;
                    }
                    else {
                        this.eSelectAll.indeterminate = true;
                    }
                }
                else {
                    this.model.unselectValue(value);
                    //if set is empty, nothing is selected
                    if (this.model.isNothingSelected()) {
                        this.eSelectAll.indeterminate = false;
                        this.eSelectAll.checked = false;
                    }
                    else {
                        this.eSelectAll.indeterminate = true;
                    }
                }
                this.filterChangedCallback();
            };
            SetFilter.prototype.onMiniFilterChanged = function () {
                var miniFilterChanged = this.model.setMiniFilter(this.eMiniFilter.value);
                if (miniFilterChanged) {
                    this.setContainerHeight();
                    this.refreshVirtualRows();
                }
            };
            SetFilter.prototype.refreshVirtualRows = function () {
                this.clearVirtualRows();
                this.drawVirtualRows();
            };
            SetFilter.prototype.clearVirtualRows = function () {
                var rowsToRemove = Object.keys(this.rowsInBodyContainer);
                this.removeVirtualRows(rowsToRemove);
            };
            SetFilter.prototype.onSelectAll = function () {
                var checked = this.eSelectAll.checked;
                if (checked) {
                    this.model.selectEverything();
                }
                else {
                    this.model.selectNothing();
                }
                this.updateAllCheckboxes(checked);
                this.filterChangedCallback();
            };
            SetFilter.prototype.updateAllCheckboxes = function (checked) {
                var currentlyDisplayedCheckboxes = this.eListContainer.querySelectorAll("[filter-checkbox=true]");
                for (var i = 0, l = currentlyDisplayedCheckboxes.length; i < l; i++) {
                    currentlyDisplayedCheckboxes[i].checked = checked;
                }
            };
            SetFilter.prototype.addScrollListener = function () {
                var _this = this;
                this.eListViewport.addEventListener("scroll", function () {
                    _this.drawVirtualRows();
                });
            };
            SetFilter.prototype.getApi = function () {
                return this.api;
            };
            SetFilter.prototype.createApi = function () {
                var model = this.model;
                var that = this;
                this.api = {
                    setMiniFilter: function (newMiniFilter) {
                        model.setMiniFilter(newMiniFilter);
                    },
                    getMiniFilter: function () {
                        return model.getMiniFilter();
                    },
                    selectEverything: function () {
                        model.selectEverything();
                    },
                    isFilterActive: function () {
                        return model.isFilterActive();
                    },
                    selectNothing: function () {
                        model.selectNothing();
                    },
                    unselectValue: function (value) {
                        model.unselectValue(value);
                        that.refreshVirtualRows();
                    },
                    selectValue: function (value) {
                        model.selectValue(value);
                        that.refreshVirtualRows();
                    },
                    isValueSelected: function (value) {
                        return model.isValueSelected(value);
                    },
                    isEverythingSelected: function () {
                        return model.isEverythingSelected();
                    },
                    isNothingSelected: function () {
                        return model.isNothingSelected();
                    },
                    getUniqueValueCount: function () {
                        return model.getUniqueValueCount();
                    },
                    getUniqueValue: function (index) {
                        return model.getUniqueValue(index);
                    },
                    getModel: function () {
                        return model.getModel();
                    },
                    setModel: function (dataModel) {
                        model.setModel(dataModel);
                        that.refreshVirtualRows();
                    }
                };
            };
            return SetFilter;
        })();
        grid.SetFilter = SetFilter;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var _ = grid.Utils;
        var PopupService = (function () {
            function PopupService() {
            }
            PopupService.getInstance = function () {
                if (!this.theInstance) {
                    this.theInstance = new PopupService();
                }
                return this.theInstance;
            };
            PopupService.prototype.init = function (ePopupParent) {
                this.ePopupParent = ePopupParent;
            };
            PopupService.prototype.positionPopup = function (eventSource, ePopup, minWidth) {
                var sourceRect = eventSource.getBoundingClientRect();
                var parentRect = this.ePopupParent.getBoundingClientRect();
                var x = sourceRect.left - parentRect.left;
                var y = sourceRect.top - parentRect.top + sourceRect.height;
                // if popup is overflowing to the right, move it left
                if (minWidth > 0) {
                    var widthOfParent = parentRect.right - parentRect.left;
                    var maxX = widthOfParent - minWidth;
                    if (x > maxX) {
                        x = maxX;
                    }
                    if (x < 0) {
                        x = 0;
                    }
                }
                ePopup.style.left = x + "px";
                ePopup.style.top = y + "px";
            };
            //adds an element to a div, but also listens to background checking for clicks,
            //so that when the background is clicked, the child is removed again, giving
            //a model look to popups.
            PopupService.prototype.addAsModalPopup = function (eChild) {
                var eBody = document.body;
                if (!eBody) {
                    console.warn('ag-grid: could not find the body of the document, document.body is empty');
                    return;
                }
                var popupAlreadyShown = _.isVisible(eChild);
                if (popupAlreadyShown) {
                    return;
                }
                this.ePopupParent.appendChild(eChild);
                // if we add these listeners now, then the current mouse
                // click will be included, which we don't want
                setTimeout(function () {
                    eBody.addEventListener('click', hidePopup);
                    eChild.addEventListener('click', consumeClick);
                }, 0);
                var eventFromChild = null;
                var that = this;
                function hidePopup(event) {
                    if (event && event === eventFromChild) {
                        return;
                    }
                    that.ePopupParent.removeChild(eChild);
                    eBody.removeEventListener('click', hidePopup);
                    eChild.removeEventListener('click', consumeClick);
                }
                function consumeClick(event) {
                    eventFromChild = event;
                }
                return hidePopup;
            };
            return PopupService;
        })();
        grid.PopupService = PopupService;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
/// <reference path="textFilter.ts" />
/// <reference path="numberFilter.ts" />
/// <reference path="setFilter.ts" />
/// <reference path="../widgets/agPopupService.ts" />
var awk;
(function (awk) {
    var grid;
    (function (_grid) {
        var agPopupService = _grid.PopupService.getInstance();
        var utils = _grid.Utils;
        var FilterManager = (function () {
            function FilterManager() {
            }
            FilterManager.prototype.init = function (grid, gridOptionsWrapper, $compile, $scope, expressionService, columnModel) {
                this.$compile = $compile;
                this.$scope = $scope;
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.grid = grid;
                this.allFilters = {};
                this.expressionService = expressionService;
                this.columnModel = columnModel;
            };
            FilterManager.prototype.setFilterModel = function (model) {
                var that = this;
                if (model) {
                    // mark the filters as we set them, so any active filters left over we stop
                    var processedFields = Object.keys(model);
                    utils.iterateObject(this.allFilters, function (key, filterWrapper) {
                        var field = filterWrapper.column.colDef.field;
                        utils.removeFromArray(processedFields, field);
                        if (field) {
                            var newModel = model[field];
                            that.setModelOnFilterWrapper(filterWrapper.filter, newModel);
                        }
                        else {
                            console.warn('Warning ag-grid - no field found for column while doing setFilterModel');
                        }
                    });
                    // at this point, processedFields contains data for which we don't have a filter working yet
                    utils.iterateArray(processedFields, function (field) {
                        var column = that.columnModel.getColumn(field);
                        if (!column) {
                            console.warn('Warning ag-grid - no column found for field ' + field);
                            return;
                        }
                        var filterWrapper = that.getOrCreateFilterWrapper(column);
                        that.setModelOnFilterWrapper(filterWrapper.filter, model[field]);
                    });
                }
                else {
                    utils.iterateObject(this.allFilters, function (key, filterWrapper) {
                        that.setModelOnFilterWrapper(filterWrapper.filter, null);
                    });
                }
            };
            FilterManager.prototype.setModelOnFilterWrapper = function (filter, newModel) {
                // because user can provide filters, we provide useful error checking and messages
                if (typeof filter.getApi !== 'function') {
                    console.warn('Warning ag-grid - filter missing getApi method, which is needed for getFilterModel');
                    return;
                }
                var filterApi = filter.getApi();
                if (typeof filterApi.setModel !== 'function') {
                    console.warn('Warning ag-grid - filter API missing setModel method, which is needed for setFilterModel');
                    return;
                }
                filterApi.setModel(newModel);
            };
            FilterManager.prototype.getFilterModel = function () {
                var result = {};
                utils.iterateObject(this.allFilters, function (key, filterWrapper) {
                    // because user can provide filters, we provide useful error checking and messages
                    if (typeof filterWrapper.filter.getApi !== 'function') {
                        console.warn('Warning ag-grid - filter missing getApi method, which is needed for getFilterModel');
                        return;
                    }
                    var filterApi = filterWrapper.filter.getApi();
                    if (typeof filterApi.getModel !== 'function') {
                        console.warn('Warning ag-grid - filter API missing getModel method, which is needed for getFilterModel');
                        return;
                    }
                    var model = filterApi.getModel();
                    if (model) {
                        var field = filterWrapper.column.colDef.field;
                        if (!field) {
                            console.warn('Warning ag-grid - cannot get filter model when no field value present for column');
                        }
                        else {
                            result[field] = model;
                        }
                    }
                });
                return result;
            };
            FilterManager.prototype.setRowModel = function (rowModel) {
                this.rowModel = rowModel;
            };
            // returns true if at least one filter is active
            FilterManager.prototype.isFilterPresent = function () {
                var atLeastOneActive = false;
                var that = this;
                var keys = Object.keys(this.allFilters);
                keys.forEach(function (key) {
                    var filterWrapper = that.allFilters[key];
                    if (!filterWrapper.filter.isFilterActive) {
                        console.error('Filter is missing method isFilterActive');
                    }
                    if (filterWrapper.filter.isFilterActive()) {
                        atLeastOneActive = true;
                    }
                });
                return atLeastOneActive;
            };
            // returns true if given col has a filter active
            FilterManager.prototype.isFilterPresentForCol = function (colId) {
                var filterWrapper = this.allFilters[colId];
                if (!filterWrapper) {
                    return false;
                }
                if (!filterWrapper.filter.isFilterActive) {
                    console.error('Filter is missing method isFilterActive');
                }
                var filterPresent = filterWrapper.filter.isFilterActive();
                return filterPresent;
            };
            FilterManager.prototype.doesFilterPass = function (node) {
                var data = node.data;
                var colKeys = Object.keys(this.allFilters);
                for (var i = 0, l = colKeys.length; i < l; i++) {
                    var colId = colKeys[i];
                    var filterWrapper = this.allFilters[colId];
                    // if no filter, always pass
                    if (filterWrapper === undefined) {
                        continue;
                    }
                    if (!filterWrapper.filter.doesFilterPass) {
                        console.error('Filter is missing method doesFilterPass');
                    }
                    var params = {
                        node: node,
                        data: data
                    };
                    if (!filterWrapper.filter.doesFilterPass(params)) {
                        return false;
                    }
                }
                // all filters passed
                return true;
            };
            FilterManager.prototype.onNewRowsLoaded = function () {
                var that = this;
                Object.keys(this.allFilters).forEach(function (field) {
                    var filter = that.allFilters[field].filter;
                    if (filter.onNewRowsLoaded) {
                        filter.onNewRowsLoaded();
                    }
                });
            };
            FilterManager.prototype.createValueGetter = function (colDef) {
                var that = this;
                return function valueGetter(node) {
                    var api = that.gridOptionsWrapper.getApi();
                    var context = that.gridOptionsWrapper.getContext();
                    return utils.getValue(that.expressionService, node.data, colDef, node, api, context);
                };
            };
            FilterManager.prototype.getFilterApi = function (column) {
                var filterWrapper = this.getOrCreateFilterWrapper(column);
                if (filterWrapper) {
                    if (typeof filterWrapper.filter.getApi === 'function') {
                        return filterWrapper.filter.getApi();
                    }
                }
            };
            FilterManager.prototype.getOrCreateFilterWrapper = function (column) {
                var filterWrapper = this.allFilters[column.colId];
                if (!filterWrapper) {
                    filterWrapper = this.createFilterWrapper(column);
                    this.allFilters[column.colId] = filterWrapper;
                }
                return filterWrapper;
            };
            FilterManager.prototype.createFilterWrapper = function (column) {
                var colDef = column.colDef;
                var filterWrapper = {
                    column: column,
                    filter: null,
                    scope: null,
                    gui: null
                };
                var filterChangedCallback = this.grid.onFilterChanged.bind(this.grid);
                var filterParams = colDef.filterParams;
                var params = {
                    colDef: colDef,
                    rowModel: this.rowModel,
                    filterChangedCallback: filterChangedCallback,
                    filterParams: filterParams,
                    localeTextFunc: this.gridOptionsWrapper.getLocaleTextFunc(),
                    valueGetter: this.createValueGetter(colDef),
                    $scope: null
                };
                if (typeof colDef.filter === 'function') {
                    // if user provided a filter, just use it
                    // first up, create child scope if needed
                    if (this.gridOptionsWrapper.isAngularCompileFilters()) {
                        var scope = this.$scope.$new();
                        filterWrapper.scope = scope;
                        params.$scope = scope;
                    }
                    // now create filter
                    filterWrapper.filter = new colDef.filter(params);
                }
                else if (colDef.filter === 'text') {
                    filterWrapper.filter = new _grid.TextFilter(params);
                }
                else if (colDef.filter === 'number') {
                    filterWrapper.filter = new _grid.NumberFilter(params);
                }
                else {
                    filterWrapper.filter = new _grid.SetFilter(params);
                }
                if (!filterWrapper.filter.getGui) {
                    throw 'Filter is missing method getGui';
                }
                var eFilterGui = document.createElement('div');
                eFilterGui.className = 'ag-filter';
                var guiFromFilter = filterWrapper.filter.getGui();
                if (utils.isNodeOrElement(guiFromFilter)) {
                    //a dom node or element was returned, so add child
                    eFilterGui.appendChild(guiFromFilter);
                }
                else {
                    //otherwise assume it was html, so just insert
                    var eTextSpan = document.createElement('span');
                    eTextSpan.innerHTML = guiFromFilter;
                    eFilterGui.appendChild(eTextSpan);
                }
                if (filterWrapper.scope) {
                    filterWrapper.gui = this.$compile(eFilterGui)(filterWrapper.scope)[0];
                }
                else {
                    filterWrapper.gui = eFilterGui;
                }
                return filterWrapper;
            };
            FilterManager.prototype.showFilter = function (column, eventSource) {
                var filterWrapper = this.getOrCreateFilterWrapper(column);
                agPopupService.positionPopup(eventSource, filterWrapper.gui, 200);
                agPopupService.addAsModalPopup(filterWrapper.gui);
                if (filterWrapper.filter.afterGuiAttached) {
                    filterWrapper.filter.afterGuiAttached();
                }
            };
            return FilterManager;
        })();
        _grid.FilterManager = FilterManager;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="utils.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        // these constants are used for determining if groups should
        // be selected or deselected when selecting groups, and the group
        // then selects the children.
        var SELECTED = 0;
        var UNSELECTED = 1;
        var MIXED = 2;
        var DO_NOT_CARE = 3;
        var SelectionController = (function () {
            function SelectionController() {
            }
            SelectionController.prototype.init = function (angularGrid, gridPanel, gridOptionsWrapper, $scope, rowRenderer) {
                this.eRowsParent = gridPanel.getRowsParent();
                this.angularGrid = angularGrid;
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.$scope = $scope;
                this.rowRenderer = rowRenderer;
                this.initSelectedNodesById();
                this.selectedRows = [];
                gridOptionsWrapper.setSelectedRows(this.selectedRows);
            };
            SelectionController.prototype.initSelectedNodesById = function () {
                this.selectedNodesById = {};
                this.gridOptionsWrapper.setSelectedNodesById(this.selectedNodesById);
            };
            SelectionController.prototype.getSelectedNodes = function () {
                var selectedNodes = [];
                var keys = Object.keys(this.selectedNodesById);
                for (var i = 0; i < keys.length; i++) {
                    var id = keys[i];
                    var selectedNode = this.selectedNodesById[id];
                    selectedNodes.push(selectedNode);
                }
                return selectedNodes;
            };
            // returns a list of all nodes at 'best cost' - a feature to be used
            // with groups / trees. if a group has all it's children selected,
            // then the group appears in the result, but not the children.
            // Designed for use with 'children' as the group selection type,
            // where groups don't actually appear in the selection normally.
            SelectionController.prototype.getBestCostNodeSelection = function () {
                if (typeof this.rowModel.getTopLevelNodes !== 'function') {
                    throw 'selectAll not available when rows are on the server';
                }
                var topLevelNodes = this.rowModel.getTopLevelNodes();
                var result = [];
                var that = this;
                // recursive function, to find the selected nodes
                function traverse(nodes) {
                    for (var i = 0, l = nodes.length; i < l; i++) {
                        var node = nodes[i];
                        if (that.isNodeSelected(node)) {
                            result.push(node);
                        }
                        else {
                            // if not selected, then if it's a group, and the group
                            // has children, continue to search for selections
                            if (node.group && node.children) {
                                traverse(node.children);
                            }
                        }
                    }
                }
                traverse(topLevelNodes);
                return result;
            };
            SelectionController.prototype.setRowModel = function (rowModel) {
                this.rowModel = rowModel;
            };
            // public - this clears the selection, but doesn't clear down the css - when it is called, the
            // caller then gets the grid to refresh.
            SelectionController.prototype.deselectAll = function () {
                this.initSelectedNodesById();
                //var keys = Object.keys(this.selectedNodesById);
                //for (var i = 0; i < keys.length; i++) {
                //    delete this.selectedNodesById[keys[i]];
                //}
                this.syncSelectedRowsAndCallListener();
            };
            // public - this selects everything, but doesn't clear down the css - when it is called, the
            // caller then gets the grid to refresh.
            SelectionController.prototype.selectAll = function () {
                if (typeof this.rowModel.getTopLevelNodes !== 'function') {
                    throw 'selectAll not available when rows are on the server';
                }
                var selectedNodesById = this.selectedNodesById;
                // if the selection is "don't include groups", then we don't include them!
                var includeGroups = !this.gridOptionsWrapper.isGroupSelectsChildren();
                function recursivelySelect(nodes) {
                    if (nodes) {
                        for (var i = 0; i < nodes.length; i++) {
                            var node = nodes[i];
                            if (node.group) {
                                recursivelySelect(node.children);
                                if (includeGroups) {
                                    selectedNodesById[node.id] = node;
                                }
                            }
                            else {
                                selectedNodesById[node.id] = node;
                            }
                        }
                    }
                }
                var topLevelNodes = this.rowModel.getTopLevelNodes();
                recursivelySelect(topLevelNodes);
                this.syncSelectedRowsAndCallListener();
            };
            // public
            SelectionController.prototype.selectNode = function (node, tryMulti, suppressEvents) {
                var multiSelect = this.gridOptionsWrapper.isRowSelectionMulti() && tryMulti;
                // if the node is a group, then selecting this is the same as selecting the parent,
                // so to have only one flow through the below, we always select the header parent
                // (which then has the side effect of selecting the child).
                var nodeToSelect;
                if (node.footer) {
                    nodeToSelect = node.sibling;
                }
                else {
                    nodeToSelect = node;
                }
                // at the end, if this is true, we inform the callback
                var atLeastOneItemUnselected = false;
                var atLeastOneItemSelected = false;
                // see if rows to be deselected
                if (!multiSelect) {
                    atLeastOneItemUnselected = this.doWorkOfDeselectAllNodes();
                }
                if (this.gridOptionsWrapper.isGroupSelectsChildren() && nodeToSelect.group) {
                    // don't select the group, select the children instead
                    atLeastOneItemSelected = this.recursivelySelectAllChildren(nodeToSelect);
                }
                else {
                    // see if row needs to be selected
                    atLeastOneItemSelected = this.doWorkOfSelectNode(nodeToSelect, suppressEvents);
                }
                if (atLeastOneItemUnselected || atLeastOneItemSelected) {
                    this.syncSelectedRowsAndCallListener(suppressEvents);
                }
                this.updateGroupParentsIfNeeded();
            };
            SelectionController.prototype.recursivelySelectAllChildren = function (node, suppressEvents) {
                var atLeastOne = false;
                if (node.children) {
                    for (var i = 0; i < node.children.length; i++) {
                        var child = node.children[i];
                        if (child.group) {
                            if (this.recursivelySelectAllChildren(child)) {
                                atLeastOne = true;
                            }
                        }
                        else {
                            if (this.doWorkOfSelectNode(child, suppressEvents)) {
                                atLeastOne = true;
                            }
                        }
                    }
                }
                return atLeastOne;
            };
            SelectionController.prototype.recursivelyDeselectAllChildren = function (node) {
                if (node.children) {
                    for (var i = 0; i < node.children.length; i++) {
                        var child = node.children[i];
                        if (child.group) {
                            this.recursivelyDeselectAllChildren(child);
                        }
                        else {
                            this.deselectRealNode(child);
                        }
                    }
                }
            };
            // private
            // 1 - selects a node
            // 2 - updates the UI
            // 3 - calls callbacks
            SelectionController.prototype.doWorkOfSelectNode = function (node, suppressEvents) {
                if (this.selectedNodesById[node.id]) {
                    return false;
                }
                this.selectedNodesById[node.id] = node;
                this.addCssClassForNode_andInformVirtualRowListener(node);
                // also color in the footer if there is one
                if (node.group && node.expanded && node.sibling) {
                    this.addCssClassForNode_andInformVirtualRowListener(node.sibling);
                }
                // inform the rowSelected listener, if any
                if (!suppressEvents && typeof this.gridOptionsWrapper.getRowSelected() === "function") {
                    this.gridOptionsWrapper.getRowSelected()(node.data, node);
                }
                return true;
            };
            // private
            // 1 - selects a node
            // 2 - updates the UI
            // 3 - calls callbacks
            // wow - what a big name for a method, exception case, it's saying what the method does
            SelectionController.prototype.addCssClassForNode_andInformVirtualRowListener = function (node) {
                var virtualRenderedRowIndex = this.rowRenderer.getIndexOfRenderedNode(node);
                if (virtualRenderedRowIndex >= 0) {
                    utils.querySelectorAll_addCssClass(this.eRowsParent, '[row="' + virtualRenderedRowIndex + '"]', 'ag-row-selected');
                    // inform virtual row listener
                    this.angularGrid.onVirtualRowSelected(virtualRenderedRowIndex, true);
                }
            };
            // private
            // 1 - un-selects a node
            // 2 - updates the UI
            // 3 - calls callbacks
            SelectionController.prototype.doWorkOfDeselectAllNodes = function (nodeToKeepSelected) {
                // not doing multi-select, so deselect everything other than the 'just selected' row
                var atLeastOneSelectionChange;
                var selectedNodeKeys = Object.keys(this.selectedNodesById);
                for (var i = 0; i < selectedNodeKeys.length; i++) {
                    // skip the 'just selected' row
                    var key = selectedNodeKeys[i];
                    var nodeToDeselect = this.selectedNodesById[key];
                    if (nodeToDeselect === nodeToKeepSelected) {
                        continue;
                    }
                    else {
                        this.deselectRealNode(nodeToDeselect);
                        atLeastOneSelectionChange = true;
                    }
                }
                return atLeastOneSelectionChange;
            };
            // private
            SelectionController.prototype.deselectRealNode = function (node) {
                // deselect the css
                this.removeCssClassForNode(node);
                // if node is a header, and if it has a sibling footer, deselect the footer also
                if (node.group && node.expanded && node.sibling) {
                    this.removeCssClassForNode(node.sibling);
                }
                // remove the row
                delete this.selectedNodesById[node.id];
            };
            // private
            SelectionController.prototype.removeCssClassForNode = function (node) {
                var virtualRenderedRowIndex = this.rowRenderer.getIndexOfRenderedNode(node);
                if (virtualRenderedRowIndex >= 0) {
                    utils.querySelectorAll_removeCssClass(this.eRowsParent, '[row="' + virtualRenderedRowIndex + '"]', 'ag-row-selected');
                    // inform virtual row listener
                    this.angularGrid.onVirtualRowSelected(virtualRenderedRowIndex, false);
                }
            };
            // public (selectionRendererFactory)
            SelectionController.prototype.deselectIndex = function (rowIndex) {
                var node = this.rowModel.getVirtualRow(rowIndex);
                this.deselectNode(node);
            };
            // public (api)
            SelectionController.prototype.deselectNode = function (node) {
                if (node) {
                    if (this.gridOptionsWrapper.isGroupSelectsChildren() && node.group) {
                        // want to deselect children, not this node, so recursively deselect
                        this.recursivelyDeselectAllChildren(node);
                    }
                    else {
                        this.deselectRealNode(node);
                    }
                }
                this.syncSelectedRowsAndCallListener();
                this.updateGroupParentsIfNeeded();
            };
            // public (selectionRendererFactory & api)
            SelectionController.prototype.selectIndex = function (index, tryMulti, suppressEvents) {
                var node = this.rowModel.getVirtualRow(index);
                this.selectNode(node, tryMulti, suppressEvents);
            };
            // private
            // updates the selectedRows with the selectedNodes and calls selectionChanged listener
            SelectionController.prototype.syncSelectedRowsAndCallListener = function (suppressEvents) {
                // update selected rows
                var selectedRows = this.selectedRows;
                var oldCount = selectedRows.length;
                // clear selected rows
                selectedRows.length = 0;
                var keys = Object.keys(this.selectedNodesById);
                for (var i = 0; i < keys.length; i++) {
                    if (this.selectedNodesById[keys[i]] !== undefined) {
                        var selectedNode = this.selectedNodesById[keys[i]];
                        selectedRows.push(selectedNode.data);
                    }
                }
                // this stope the event firing the very first the time grid is initialised. without this, the documentation
                // page had a popup in the 'selection' page as soon as the page was loaded!!
                var nothingChangedMustBeInitialising = oldCount === 0 && selectedRows.length === 0;
                if (!nothingChangedMustBeInitialising && !suppressEvents && typeof this.gridOptionsWrapper.getSelectionChanged() === "function") {
                    this.gridOptionsWrapper.getSelectionChanged()();
                }
                var that = this;
                if (this.$scope) {
                    setTimeout(function () {
                        that.$scope.$apply();
                    }, 0);
                }
            };
            // private
            SelectionController.prototype.recursivelyCheckIfSelected = function (node) {
                var foundSelected = false;
                var foundUnselected = false;
                if (node.children) {
                    for (var i = 0; i < node.children.length; i++) {
                        var child = node.children[i];
                        var result;
                        if (child.group) {
                            result = this.recursivelyCheckIfSelected(child);
                            switch (result) {
                                case SELECTED:
                                    foundSelected = true;
                                    break;
                                case UNSELECTED:
                                    foundUnselected = true;
                                    break;
                                case MIXED:
                                    foundSelected = true;
                                    foundUnselected = true;
                                    break;
                            }
                        }
                        else {
                            if (this.isNodeSelected(child)) {
                                foundSelected = true;
                            }
                            else {
                                foundUnselected = true;
                            }
                        }
                        if (foundSelected && foundUnselected) {
                            // if mixed, then no need to go further, just return up the chain
                            return MIXED;
                        }
                    }
                }
                // got this far, so no conflicts, either all children selected, unselected, or neither
                if (foundSelected) {
                    return SELECTED;
                }
                else if (foundUnselected) {
                    return UNSELECTED;
                }
                else {
                    return DO_NOT_CARE;
                }
            };
            // public (selectionRendererFactory)
            // returns:
            // true: if selected
            // false: if unselected
            // undefined: if it's a group and 'children selection' is used and 'children' are a mix of selected and unselected
            SelectionController.prototype.isNodeSelected = function (node) {
                if (this.gridOptionsWrapper.isGroupSelectsChildren() && node.group) {
                    // doing child selection, we need to traverse the children
                    var resultOfChildren = this.recursivelyCheckIfSelected(node);
                    switch (resultOfChildren) {
                        case SELECTED:
                            return true;
                        case UNSELECTED:
                            return false;
                        default:
                            return undefined;
                    }
                }
                else {
                    return this.selectedNodesById[node.id] !== undefined;
                }
            };
            SelectionController.prototype.updateGroupParentsIfNeeded = function () {
                // we only do this if parent nodes are responsible
                // for selecting their children.
                if (!this.gridOptionsWrapper.isGroupSelectsChildren()) {
                    return;
                }
                var firstRow = this.rowRenderer.getFirstVirtualRenderedRow();
                var lastRow = this.rowRenderer.getLastVirtualRenderedRow();
                for (var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) {
                    // see if node is a group
                    var node = this.rowModel.getVirtualRow(rowIndex);
                    if (node.group) {
                        var selected = this.isNodeSelected(node);
                        this.angularGrid.onVirtualRowSelected(rowIndex, selected);
                        if (selected) {
                            utils.querySelectorAll_addCssClass(this.eRowsParent, '[row="' + rowIndex + '"]', 'ag-row-selected');
                        }
                        else {
                            utils.querySelectorAll_removeCssClass(this.eRowsParent, '[row="' + rowIndex + '"]', 'ag-row-selected');
                        }
                    }
                }
            };
            return SelectionController;
        })();
        grid.SelectionController = SelectionController;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var SelectionRendererFactory = (function () {
            function SelectionRendererFactory() {
            }
            SelectionRendererFactory.prototype.init = function (angularGrid, selectionController) {
                this.angularGrid = angularGrid;
                this.selectionController = selectionController;
            };
            SelectionRendererFactory.prototype.createCheckboxColDef = function () {
                return {
                    width: 30,
                    suppressMenu: true,
                    suppressSorting: true,
                    headerCellRenderer: function () {
                        var eCheckbox = document.createElement('input');
                        eCheckbox.type = 'checkbox';
                        eCheckbox.name = 'name';
                        return eCheckbox;
                    },
                    cellRenderer: this.createCheckboxRenderer()
                };
            };
            SelectionRendererFactory.prototype.createCheckboxRenderer = function () {
                var that = this;
                return function (params) {
                    return that.createSelectionCheckbox(params.node, params.rowIndex);
                };
            };
            SelectionRendererFactory.prototype.createSelectionCheckbox = function (node, rowIndex) {
                var eCheckbox = document.createElement('input');
                eCheckbox.type = "checkbox";
                eCheckbox.name = "name";
                eCheckbox.className = 'ag-selection-checkbox';
                setCheckboxState(eCheckbox, this.selectionController.isNodeSelected(node));
                var that = this;
                eCheckbox.onclick = function (event) {
                    event.stopPropagation();
                };
                eCheckbox.onchange = function () {
                    var newValue = eCheckbox.checked;
                    if (newValue) {
                        that.selectionController.selectIndex(rowIndex, true);
                    }
                    else {
                        that.selectionController.deselectIndex(rowIndex);
                    }
                };
                this.angularGrid.addVirtualRowListener(rowIndex, {
                    rowSelected: function (selected) {
                        setCheckboxState(eCheckbox, selected);
                    },
                    rowRemoved: function () {
                    }
                });
                return eCheckbox;
            };
            return SelectionRendererFactory;
        })();
        grid.SelectionRendererFactory = SelectionRendererFactory;
        function setCheckboxState(eCheckbox, state) {
            if (typeof state === 'boolean') {
                eCheckbox.checked = state;
                eCheckbox.indeterminate = false;
            }
            else {
                // isNodeSelected returns back undefined if it's a group and the children
                // are a mix of selected and unselected
                eCheckbox.indeterminate = true;
            }
        }
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var SVG_NS = "http://www.w3.org/2000/svg";
        var SvgFactory = (function () {
            function SvgFactory() {
            }
            SvgFactory.getInstance = function () {
                if (!this.theInstance) {
                    this.theInstance = new SvgFactory();
                }
                return this.theInstance;
            };
            SvgFactory.prototype.createFilterSvg = function () {
                var eSvg = createIconSvg();
                var eFunnel = document.createElementNS(SVG_NS, "polygon");
                eFunnel.setAttribute("points", "0,0 4,4 4,10 6,10 6,4 10,0");
                eFunnel.setAttribute("class", "ag-header-icon");
                eSvg.appendChild(eFunnel);
                return eSvg;
            };
            SvgFactory.prototype.createColumnShowingSvg = function () {
                return createCircle(true);
            };
            SvgFactory.prototype.createColumnHiddenSvg = function () {
                return createCircle(false);
            };
            SvgFactory.prototype.createMenuSvg = function () {
                var eSvg = document.createElementNS(SVG_NS, "svg");
                var size = "12";
                eSvg.setAttribute("width", size);
                eSvg.setAttribute("height", size);
                ["0", "5", "10"].forEach(function (y) {
                    var eLine = document.createElementNS(SVG_NS, "rect");
                    eLine.setAttribute("y", y);
                    eLine.setAttribute("width", size);
                    eLine.setAttribute("height", "2");
                    eLine.setAttribute("class", "ag-header-icon");
                    eSvg.appendChild(eLine);
                });
                return eSvg;
            };
            SvgFactory.prototype.createArrowUpSvg = function () {
                return createPolygonSvg("0,10 5,0 10,10");
            };
            SvgFactory.prototype.createArrowLeftSvg = function () {
                return createPolygonSvg("10,0 0,5 10,10");
            };
            SvgFactory.prototype.createArrowDownSvg = function () {
                return createPolygonSvg("0,0 5,10 10,0");
            };
            SvgFactory.prototype.createArrowRightSvg = function () {
                return createPolygonSvg("0,0 10,5 0,10");
            };
            SvgFactory.prototype.createSmallArrowDownSvg = function () {
                return createPolygonSvg("0,0 3,6 6,0", 6);
            };
            // UnSort Icon SVG
            SvgFactory.prototype.createArrowUpDownSvg = function () {
                var svg = createIconSvg();
                var eAscIcon = document.createElementNS(SVG_NS, "polygon");
                eAscIcon.setAttribute("points", '0,4 5,0 10,4');
                svg.appendChild(eAscIcon);
                var eDescIcon = document.createElementNS(SVG_NS, "polygon");
                eDescIcon.setAttribute("points", '0,6 5,10 10,6');
                svg.appendChild(eDescIcon);
                return svg;
            };
            return SvgFactory;
        })();
        grid.SvgFactory = SvgFactory;
        function createPolygonSvg(points, width) {
            var eSvg = createIconSvg(width);
            var eDescIcon = document.createElementNS(SVG_NS, "polygon");
            eDescIcon.setAttribute("points", points);
            eSvg.appendChild(eDescIcon);
            return eSvg;
        }
        // util function for the above
        function createIconSvg(width) {
            var eSvg = document.createElementNS(SVG_NS, "svg");
            if (width > 0) {
                eSvg.setAttribute("width", width);
                eSvg.setAttribute("height", width);
            }
            else {
                eSvg.setAttribute("width", "10");
                eSvg.setAttribute("height", "10");
            }
            return eSvg;
        }
        function createCircle(fill) {
            var eSvg = createIconSvg();
            var eCircle = document.createElementNS(SVG_NS, "circle");
            eCircle.setAttribute("cx", "5");
            eCircle.setAttribute("cy", "5");
            eCircle.setAttribute("r", "5");
            eCircle.setAttribute("stroke", "black");
            eCircle.setAttribute("stroke-width", "2");
            if (fill) {
                eCircle.setAttribute("fill", "black");
            }
            else {
                eCircle.setAttribute("fill", "none");
            }
            eSvg.appendChild(eCircle);
            return eSvg;
        }
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../svgFactory.ts" />
/// <reference path="../utils.ts" />
/// <reference path="../constants.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var svgFactory = grid.SvgFactory.getInstance();
        var utils = grid.Utils;
        var constants = grid.Constants;
        function groupCellRendererFactory(gridOptionsWrapper, selectionRendererFactory) {
            return function groupCellRenderer(params) {
                var eGroupCell = document.createElement('span');
                var node = params.node;
                var cellExpandable = node.group && !node.footer;
                if (cellExpandable) {
                    addExpandAndContract(eGroupCell, params);
                }
                var checkboxNeeded = params.colDef && params.colDef.cellRenderer && params.colDef.cellRenderer.checkbox && !node.footer;
                if (checkboxNeeded) {
                    var eCheckbox = selectionRendererFactory.createSelectionCheckbox(node, params.rowIndex);
                    eGroupCell.appendChild(eCheckbox);
                }
                if (params.colDef && params.colDef.cellRenderer && params.colDef.cellRenderer.innerRenderer) {
                    createFromInnerRenderer(eGroupCell, params, params.colDef.cellRenderer.innerRenderer);
                }
                else if (node.footer) {
                    createFooterCell(eGroupCell, params);
                }
                else if (node.group) {
                    createGroupCell(eGroupCell, params);
                }
                else {
                    createLeafCell(eGroupCell, params);
                }
                // only do this if an indent - as this overwrites the padding that
                // the theme set, which will make things look 'not aligned' for the
                // first group level.
                if (node.footer || node.level > 0) {
                    var paddingFactor;
                    if (params.colDef && params.colDef.cellRenderer && params.colDef.cellRenderer.padding >= 0) {
                        paddingFactor = params.colDef.cellRenderer.padding;
                    }
                    else {
                        paddingFactor = 10;
                    }
                    var paddingPx = node.level * paddingFactor;
                    if (node.footer) {
                        paddingPx += 10;
                    }
                    else if (!node.group) {
                        paddingPx += 5;
                    }
                    eGroupCell.style.paddingLeft = paddingPx + 'px';
                }
                return eGroupCell;
            };
            function addExpandAndContract(eGroupCell, params) {
                var eExpandIcon = createGroupExpandIcon(true);
                var eContractIcon = createGroupExpandIcon(false);
                eGroupCell.appendChild(eExpandIcon);
                eGroupCell.appendChild(eContractIcon);
                eExpandIcon.addEventListener('click', expandOrContract);
                eContractIcon.addEventListener('click', expandOrContract);
                eGroupCell.addEventListener('dblclick', expandOrContract);
                showAndHideExpandAndContract(eExpandIcon, eContractIcon, params.node.expanded);
                // if parent cell was passed, then we can listen for when focus is on the cell,
                // and then expand / contract as the user hits enter or space-bar
                if (params.eGridCell) {
                    params.eGridCell.addEventListener('keydown', function (event) {
                        if (utils.isKeyPressed(event, constants.KEY_ENTER)) {
                            expandOrContract();
                            event.preventDefault();
                        }
                    });
                }
                function expandOrContract() {
                    expandGroup(eExpandIcon, eContractIcon, params);
                }
            }
            function showAndHideExpandAndContract(eExpandIcon, eContractIcon, expanded) {
                utils.setVisible(eExpandIcon, !expanded);
                utils.setVisible(eContractIcon, expanded);
            }
            function createFromInnerRenderer(eGroupCell, params, renderer) {
                utils.useRenderer(eGroupCell, renderer, params);
            }
            function expandGroup(eExpandIcon, eContractIcon, params) {
                params.node.expanded = !params.node.expanded;
                params.api.onGroupExpandedOrCollapsed(params.rowIndex + 1);
                showAndHideExpandAndContract(eExpandIcon, eContractIcon, params.node.expanded);
            }
            function createGroupExpandIcon(expanded) {
                var eIcon;
                if (expanded) {
                    eIcon = utils.createIcon('groupContracted', gridOptionsWrapper, null, svgFactory.createArrowRightSvg);
                }
                else {
                    eIcon = utils.createIcon('groupExpanded', gridOptionsWrapper, null, svgFactory.createArrowDownSvg);
                }
                utils.addCssClass(eIcon, 'ag-group-expand');
                return eIcon;
            }
            // creates cell with 'Total {{key}}' for a group
            function createFooterCell(eGroupCell, params) {
                var textToDisplay = "Total " + getGroupName(params);
                var eText = document.createTextNode(textToDisplay);
                eGroupCell.appendChild(eText);
            }
            function getGroupName(params) {
                var cellRenderer = params.colDef.cellRenderer;
                if (cellRenderer && cellRenderer.keyMap && typeof cellRenderer.keyMap === 'object' && params.colDef.cellRenderer !== null) {
                    var valueFromMap = cellRenderer.keyMap[params.node.key];
                    if (valueFromMap) {
                        return valueFromMap;
                    }
                    else {
                        return params.node.key;
                    }
                }
                else {
                    return params.node.key;
                }
            }
            // creates cell with '{{key}} ({{childCount}})' for a group
            function createGroupCell(eGroupCell, params) {
                var groupName = getGroupName(params);
                var colDefOfGroupedCol = params.api.getColumnDef(params.node.field);
                if (colDefOfGroupedCol && typeof colDefOfGroupedCol.cellRenderer === 'function') {
                    params.value = groupName;
                    utils.useRenderer(eGroupCell, colDefOfGroupedCol.cellRenderer, params);
                }
                else {
                    eGroupCell.appendChild(document.createTextNode(groupName));
                }
                // only include the child count if it's included, eg if user doing custom aggregation,
                // then this could be left out, or set to -1, ie no child count
                var suppressCount = params.colDef.cellRenderer && params.colDef.cellRenderer.suppressCount;
                if (!suppressCount && params.node.allChildrenCount >= 0) {
                    eGroupCell.appendChild(document.createTextNode(" (" + params.node.allChildrenCount + ")"));
                }
            }
            // creates cell with '{{key}} ({{childCount}})' for a group
            function createLeafCell(eParent, params) {
                if (params.value) {
                    var eText = document.createTextNode(' ' + params.value);
                    eParent.appendChild(eText);
                }
            }
        }
        grid.groupCellRendererFactory = groupCellRendererFactory;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="utils.ts" />
/// <reference path="constants.ts" />
/// <reference path="cellRenderers/groupCellRendererFactory.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var constants = grid.Constants;
        var RowRenderer = (function () {
            function RowRenderer() {
            }
            RowRenderer.prototype.init = function (gridOptions, columnModel, gridOptionsWrapper, gridPanel, angularGrid, selectionRendererFactory, $compile, $scope, selectionController, expressionService, templateService) {
                this.gridOptions = gridOptions;
                this.columnModel = columnModel;
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.angularGrid = angularGrid;
                this.selectionRendererFactory = selectionRendererFactory;
                this.gridPanel = gridPanel;
                this.$compile = $compile;
                this.$scope = $scope;
                this.selectionController = selectionController;
                this.expressionService = expressionService;
                this.templateService = templateService;
                this.findAllElements(gridPanel);
                this.cellRendererMap = {
                    'group': grid.groupCellRendererFactory(gridOptionsWrapper, selectionRendererFactory)
                };
                // map of row ids to row objects. keeps track of which elements
                // are rendered for which rows in the dom. each row object has:
                // [scope, bodyRow, pinnedRow, rowData]
                this.renderedRows = {};
                this.renderedRowStartEditingListeners = {};
                this.editingCell = false; //gets set to true when editing a cell
            };
            RowRenderer.prototype.setRowModel = function (rowModel) {
                this.rowModel = rowModel;
            };
            RowRenderer.prototype.setMainRowWidths = function () {
                var mainRowWidth = this.columnModel.getBodyContainerWidth() + "px";
                var unpinnedRows = this.eBodyContainer.querySelectorAll(".ag-row");
                for (var i = 0; i < unpinnedRows.length; i++) {
                    unpinnedRows[i].style.width = mainRowWidth;
                }
            };
            RowRenderer.prototype.findAllElements = function (gridPanel) {
                this.eBodyContainer = gridPanel.getBodyContainer();
                this.eBodyViewport = gridPanel.getBodyViewport();
                this.ePinnedColsContainer = gridPanel.getPinnedColsContainer();
                this.eParentOfRows = gridPanel.getRowsParent();
            };
            RowRenderer.prototype.refreshView = function (refreshFromIndex) {
                if (!this.gridOptionsWrapper.isDontUseScrolls()) {
                    var rowCount = this.rowModel.getVirtualRowCount();
                    var containerHeight = this.gridOptionsWrapper.getRowHeight() * rowCount;
                    this.eBodyContainer.style.height = containerHeight + "px";
                    this.ePinnedColsContainer.style.height = containerHeight + "px";
                }
                this.refreshAllVirtualRows(refreshFromIndex);
            };
            RowRenderer.prototype.softRefreshView = function () {
                var first = this.firstVirtualRenderedRow;
                var last = this.lastVirtualRenderedRow;
                var columns = this.columnModel.getDisplayedColumns();
                // if no cols, don't draw row
                if (!columns || columns.length === 0) {
                    return;
                }
                for (var rowIndex = first; rowIndex <= last; rowIndex++) {
                    var node = this.rowModel.getVirtualRow(rowIndex);
                    if (node) {
                        for (var colIndex = 0; colIndex < columns.length; colIndex++) {
                            var column = columns[colIndex];
                            var renderedRow = this.renderedRows[rowIndex];
                            var eGridCell = renderedRow.eVolatileCells[column.colId];
                            if (!eGridCell) {
                                continue;
                            }
                            var isFirstColumn = colIndex === 0;
                            var scope = renderedRow.scope;
                            this.softRefreshCell(eGridCell, isFirstColumn, node, column, scope, rowIndex);
                        }
                    }
                }
            };
            RowRenderer.prototype.softRefreshCell = function (eGridCell, isFirstColumn, node, column, scope, rowIndex) {
                utils.removeAllChildren(eGridCell);
                var data = this.getDataForNode(node);
                var valueGetter = this.createValueGetter(data, column.colDef, node);
                var value;
                if (valueGetter) {
                    value = valueGetter();
                }
                this.populateAndStyleGridCell(valueGetter, value, eGridCell, isFirstColumn, node, column, rowIndex, scope);
                // if angular compiling, then need to also compile the cell again (angular compiling sucks, please wait...)
                if (this.gridOptionsWrapper.isAngularCompileRows()) {
                    this.$compile(eGridCell)(scope);
                }
            };
            RowRenderer.prototype.rowDataChanged = function (rows) {
                // we only need to be worried about rendered rows, as this method is
                // called to whats rendered. if the row isn't rendered, we don't care
                var indexesToRemove = [];
                var renderedRows = this.renderedRows;
                Object.keys(renderedRows).forEach(function (key) {
                    var renderedRow = renderedRows[key];
                    // see if the rendered row is in the list of rows we have to update
                    var rowNeedsUpdating = rows.indexOf(renderedRow.node.data) >= 0;
                    if (rowNeedsUpdating) {
                        indexesToRemove.push(key);
                    }
                });
                // remove the rows
                this.removeVirtualRows(indexesToRemove);
                // add draw them again
                this.drawVirtualRows();
            };
            RowRenderer.prototype.refreshAllVirtualRows = function (fromIndex) {
                // remove all current virtual rows, as they have old data
                var rowsToRemove = Object.keys(this.renderedRows);
                this.removeVirtualRows(rowsToRemove, fromIndex);
                // add in new rows
                this.drawVirtualRows();
            };
            // public - removes the group rows and then redraws them again
            RowRenderer.prototype.refreshGroupRows = function () {
                // find all the group rows
                var rowsToRemove = [];
                var that = this;
                Object.keys(this.renderedRows).forEach(function (key) {
                    var renderedRow = that.renderedRows[key];
                    var node = renderedRow.node;
                    if (node.group) {
                        rowsToRemove.push(key);
                    }
                });
                // remove the rows
                this.removeVirtualRows(rowsToRemove);
                // and draw them back again
                this.ensureRowsRendered();
            };
            // takes array of row indexes
            RowRenderer.prototype.removeVirtualRows = function (rowsToRemove, fromIndex) {
                var that = this;
                // if no fromIndex then set to -1, which will refresh everything
                var realFromIndex = (typeof fromIndex === 'number') ? fromIndex : -1;
                rowsToRemove.forEach(function (indexToRemove) {
                    if (indexToRemove >= realFromIndex) {
                        that.removeVirtualRow(indexToRemove);
                        // if the row was last to have focus, we remove the fact that it has focus
                        if (that.focusedCell && that.focusedCell.rowIndex == indexToRemove) {
                            that.focusedCell = null;
                        }
                    }
                });
            };
            RowRenderer.prototype.removeVirtualRow = function (indexToRemove) {
                var renderedRow = this.renderedRows[indexToRemove];
                if (renderedRow.pinnedElement && this.ePinnedColsContainer) {
                    this.ePinnedColsContainer.removeChild(renderedRow.pinnedElement);
                }
                if (renderedRow.bodyElement) {
                    this.eBodyContainer.removeChild(renderedRow.bodyElement);
                }
                if (renderedRow.scope) {
                    renderedRow.scope.$destroy();
                }
                if (this.gridOptionsWrapper.getVirtualRowRemoved()) {
                    this.gridOptionsWrapper.getVirtualRowRemoved()(renderedRow.data, indexToRemove);
                }
                this.angularGrid.onVirtualRowRemoved(indexToRemove);
                delete this.renderedRows[indexToRemove];
                delete this.renderedRowStartEditingListeners[indexToRemove];
            };
            RowRenderer.prototype.drawVirtualRows = function () {
                var first;
                var last;
                var rowCount = this.rowModel.getVirtualRowCount();
                if (this.gridOptionsWrapper.isDontUseScrolls()) {
                    first = 0;
                    last = rowCount;
                }
                else {
                    var topPixel = this.eBodyViewport.scrollTop;
                    var bottomPixel = topPixel + this.eBodyViewport.offsetHeight;
                    first = Math.floor(topPixel / this.gridOptionsWrapper.getRowHeight());
                    last = Math.floor(bottomPixel / this.gridOptionsWrapper.getRowHeight());
                    //add in buffer
                    var buffer = this.gridOptionsWrapper.getRowBuffer() || constants.ROW_BUFFER_SIZE;
                    first = first - buffer;
                    last = last + buffer;
                    // adjust, in case buffer extended actual size
                    if (first < 0) {
                        first = 0;
                    }
                    if (last > rowCount - 1) {
                        last = rowCount - 1;
                    }
                }
                this.firstVirtualRenderedRow = first;
                this.lastVirtualRenderedRow = last;
                this.ensureRowsRendered();
            };
            RowRenderer.prototype.getFirstVirtualRenderedRow = function () {
                return this.firstVirtualRenderedRow;
            };
            RowRenderer.prototype.getLastVirtualRenderedRow = function () {
                return this.lastVirtualRenderedRow;
            };
            RowRenderer.prototype.ensureRowsRendered = function () {
                var mainRowWidth = this.columnModel.getBodyContainerWidth();
                var that = this;
                // at the end, this array will contain the items we need to remove
                var rowsToRemove = Object.keys(this.renderedRows);
                for (var rowIndex = this.firstVirtualRenderedRow; rowIndex <= this.lastVirtualRenderedRow; rowIndex++) {
                    // see if item already there, and if yes, take it out of the 'to remove' array
                    if (rowsToRemove.indexOf(rowIndex.toString()) >= 0) {
                        rowsToRemove.splice(rowsToRemove.indexOf(rowIndex.toString()), 1);
                        continue;
                    }
                    // check this row actually exists (in case overflow buffer window exceeds real data)
                    var node = this.rowModel.getVirtualRow(rowIndex);
                    if (node) {
                        that.insertRow(node, rowIndex, mainRowWidth);
                    }
                }
                // at this point, everything in our 'rowsToRemove' . . .
                this.removeVirtualRows(rowsToRemove);
                // if we are doing angular compiling, then do digest the scope here
                if (this.gridOptionsWrapper.isAngularCompileRows()) {
                    // we do it in a timeout, in case we are already in an apply
                    setTimeout(function () {
                        that.$scope.$apply();
                    }, 0);
                }
            };
            RowRenderer.prototype.insertRow = function (node, rowIndex, mainRowWidth) {
                var columns = this.columnModel.getDisplayedColumns();
                // if no cols, don't draw row
                if (!columns || columns.length == 0) {
                    return;
                }
                // var rowData = node.rowData;
                var rowIsAGroup = node.group;
                // try compiling as we insert rows
                var newChildScope = this.createChildScopeOrNull(node.data);
                var ePinnedRow = this.createRowContainer(rowIndex, node, rowIsAGroup, newChildScope);
                var eMainRow = this.createRowContainer(rowIndex, node, rowIsAGroup, newChildScope);
                var that = this;
                eMainRow.style.width = mainRowWidth + "px";
                var renderedRow = {
                    scope: newChildScope,
                    node: node,
                    rowIndex: rowIndex,
                    eCells: {},
                    eVolatileCells: {},
                    pinnedElement: null,
                    bodyElement: null
                };
                this.renderedRows[rowIndex] = renderedRow;
                this.renderedRowStartEditingListeners[rowIndex] = {};
                // if group item, insert the first row
                var groupHeaderTakesEntireRow = this.gridOptionsWrapper.isGroupUseEntireRow();
                var drawGroupRow = rowIsAGroup && groupHeaderTakesEntireRow;
                if (drawGroupRow) {
                    var firstColumn = columns[0];
                    var eGroupRow = that.createGroupElement(node, rowIndex, false);
                    if (firstColumn.pinned) {
                        ePinnedRow.appendChild(eGroupRow);
                        var eGroupRowPadding = that.createGroupElement(node, rowIndex, true);
                        eMainRow.appendChild(eGroupRowPadding);
                    }
                    else {
                        eMainRow.appendChild(eGroupRow);
                    }
                }
                else {
                    columns.forEach(function (column, index) {
                        var firstCol = index === 0;
                        var data = that.getDataForNode(node);
                        var valueGetter = that.createValueGetter(data, column.colDef, node);
                        that.createCellFromColDef(firstCol, column, valueGetter, node, rowIndex, eMainRow, ePinnedRow, newChildScope, renderedRow);
                    });
                }
                //try compiling as we insert rows
                renderedRow.pinnedElement = this.compileAndAdd(this.ePinnedColsContainer, rowIndex, ePinnedRow, newChildScope);
                renderedRow.bodyElement = this.compileAndAdd(this.eBodyContainer, rowIndex, eMainRow, newChildScope);
            };
            // if group is a footer, always show the data.
            // if group is a header, only show data if not expanded
            RowRenderer.prototype.getDataForNode = function (node) {
                if (node.footer) {
                    // if footer, we always show the data
                    return node.data;
                }
                else if (node.group) {
                    // if header and header is expanded, we show data in footer only
                    var footersEnabled = this.gridOptionsWrapper.isGroupIncludeFooter();
                    return (node.expanded && footersEnabled) ? undefined : node.data;
                }
                else {
                    // otherwise it's a normal node, just return data as normal
                    return node.data;
                }
            };
            RowRenderer.prototype.createValueGetter = function (data, colDef, node) {
                var that = this;
                return function () {
                    var api = that.gridOptionsWrapper.getApi();
                    var context = that.gridOptionsWrapper.getContext();
                    return utils.getValue(that.expressionService, data, colDef, node, api, context);
                };
            };
            RowRenderer.prototype.createChildScopeOrNull = function (data) {
                if (this.gridOptionsWrapper.isAngularCompileRows()) {
                    var newChildScope = this.$scope.$new();
                    newChildScope.data = data;
                    return newChildScope;
                }
                else {
                    return null;
                }
            };
            RowRenderer.prototype.compileAndAdd = function (container, rowIndex, element, scope) {
                if (scope) {
                    var eElementCompiled = this.$compile(element)(scope);
                    if (container) {
                        container.appendChild(eElementCompiled[0]);
                    }
                    return eElementCompiled[0];
                }
                else {
                    if (container) {
                        container.appendChild(element);
                    }
                    return element;
                }
            };
            RowRenderer.prototype.createCellFromColDef = function (isFirstColumn, column, valueGetter, node, rowIndex, eMainRow, ePinnedRow, $childScope, renderedRow) {
                var eGridCell = this.createCell(isFirstColumn, column, valueGetter, node, rowIndex, $childScope);
                if (column.colDef.volatile) {
                    renderedRow.eVolatileCells[column.colId] = eGridCell;
                }
                renderedRow.eCells[column.colId] = eGridCell;
                if (column.pinned) {
                    ePinnedRow.appendChild(eGridCell);
                }
                else {
                    eMainRow.appendChild(eGridCell);
                }
            };
            RowRenderer.prototype.addClassesToRow = function (rowIndex, node, eRow) {
                var classesList = ["ag-row"];
                classesList.push(rowIndex % 2 == 0 ? "ag-row-even" : "ag-row-odd");
                if (this.selectionController.isNodeSelected(node)) {
                    classesList.push("ag-row-selected");
                }
                if (node.group) {
                    // if a group, put the level of the group in
                    classesList.push("ag-row-level-" + node.level);
                }
                else {
                    // if a leaf, and a parent exists, put a level of the parent, else put level of 0 for top level item
                    if (node.parent) {
                        classesList.push("ag-row-level-" + (node.parent.level + 1));
                    }
                    else {
                        classesList.push("ag-row-level-0");
                    }
                }
                if (node.group) {
                    classesList.push("ag-row-group");
                }
                if (node.group && !node.footer && node.expanded) {
                    classesList.push("ag-row-group-expanded");
                }
                if (node.group && !node.footer && !node.expanded) {
                    // opposite of expanded is contracted according to the internet.
                    classesList.push("ag-row-group-contracted");
                }
                if (node.group && node.footer) {
                    classesList.push("ag-row-footer");
                }
                // add in extra classes provided by the config
                if (this.gridOptionsWrapper.getRowClass()) {
                    var gridOptionsRowClass = this.gridOptionsWrapper.getRowClass();
                    var classToUse;
                    if (typeof gridOptionsRowClass === 'function') {
                        var params = {
                            node: node,
                            data: node.data,
                            rowIndex: rowIndex,
                            context: this.gridOptionsWrapper.getContext(),
                            api: this.gridOptionsWrapper.getApi()
                        };
                        classToUse = gridOptionsRowClass(params);
                    }
                    else {
                        classToUse = gridOptionsRowClass;
                    }
                    if (classToUse) {
                        if (typeof classToUse === 'string') {
                            classesList.push(classToUse);
                        }
                        else if (Array.isArray(classToUse)) {
                            classToUse.forEach(function (classItem) {
                                classesList.push(classItem);
                            });
                        }
                    }
                }
                var classes = classesList.join(" ");
                eRow.className = classes;
            };
            RowRenderer.prototype.createRowContainer = function (rowIndex, node, groupRow, $scope) {
                var eRow = document.createElement("div");
                this.addClassesToRow(rowIndex, node, eRow);
                eRow.setAttribute('row', rowIndex);
                // if showing scrolls, position on the container
                if (!this.gridOptionsWrapper.isDontUseScrolls()) {
                    eRow.style.top = (this.gridOptionsWrapper.getRowHeight() * rowIndex) + "px";
                }
                eRow.style.height = (this.gridOptionsWrapper.getRowHeight()) + "px";
                if (this.gridOptionsWrapper.getRowStyle()) {
                    var cssToUse;
                    var rowStyle = this.gridOptionsWrapper.getRowStyle();
                    if (typeof rowStyle === 'function') {
                        var params = {
                            data: node.data,
                            node: node,
                            api: this.gridOptionsWrapper.getApi(),
                            context: this.gridOptionsWrapper.getContext(),
                            $scope: $scope
                        };
                        cssToUse = rowStyle(params);
                    }
                    else {
                        cssToUse = rowStyle;
                    }
                    if (cssToUse) {
                        Object.keys(cssToUse).forEach(function (key) {
                            eRow.style[key] = cssToUse[key];
                        });
                    }
                }
                var _this = this;
                eRow.addEventListener("click", function (event) {
                    _this.angularGrid.onRowClicked(event, Number(this.getAttribute("row")), node);
                });
                return eRow;
            };
            RowRenderer.prototype.getIndexOfRenderedNode = function (node) {
                var renderedRows = this.renderedRows;
                var keys = Object.keys(renderedRows);
                for (var i = 0; i < keys.length; i++) {
                    if (renderedRows[keys[i]].node === node) {
                        return renderedRows[keys[i]].rowIndex;
                    }
                }
                return -1;
            };
            RowRenderer.prototype.createGroupElement = function (node, rowIndex, padding) {
                var eRow;
                // padding means we are on the right hand side of a pinned table, ie
                // in the main body.
                if (padding) {
                    eRow = document.createElement('span');
                }
                else {
                    var params = {
                        node: node,
                        data: node.data,
                        rowIndex: rowIndex,
                        api: this.gridOptionsWrapper.getApi(),
                        colDef: {
                            cellRenderer: {
                                renderer: 'group',
                                innerRenderer: this.gridOptionsWrapper.getGroupRowInnerRenderer()
                            }
                        }
                    };
                    eRow = this.cellRendererMap['group'](params);
                }
                if (node.footer) {
                    utils.addCssClass(eRow, 'ag-footer-cell-entire-row');
                }
                else {
                    utils.addCssClass(eRow, 'ag-group-cell-entire-row');
                }
                return eRow;
            };
            RowRenderer.prototype.putDataIntoCell = function (column, value, valueGetter, node, $childScope, eSpanWithValue, eGridCell, rowIndex, refreshCellFunction) {
                // template gets preference, then cellRenderer, then do it ourselves
                var colDef = column.colDef;
                if (colDef.template) {
                    eSpanWithValue.innerHTML = colDef.template;
                }
                else if (colDef.templateUrl) {
                    var template = this.templateService.getTemplate(colDef.templateUrl, refreshCellFunction);
                    if (template) {
                        eSpanWithValue.innerHTML = template;
                    }
                }
                else if (colDef.cellRenderer) {
                    this.useCellRenderer(column, value, node, $childScope, eSpanWithValue, rowIndex, refreshCellFunction, valueGetter, eGridCell);
                }
                else {
                    // if we insert undefined, then it displays as the string 'undefined', ugly!
                    if (value !== undefined && value !== null && value !== '') {
                        eSpanWithValue.innerHTML = value;
                    }
                }
            };
            RowRenderer.prototype.useCellRenderer = function (column, value, node, $childScope, eSpanWithValue, rowIndex, refreshCellFunction, valueGetter, eGridCell) {
                var colDef = column.colDef;
                var rendererParams = {
                    value: value,
                    valueGetter: valueGetter,
                    data: node.data,
                    node: node,
                    colDef: colDef,
                    column: column,
                    $scope: $childScope,
                    rowIndex: rowIndex,
                    api: this.gridOptionsWrapper.getApi(),
                    context: this.gridOptionsWrapper.getContext(),
                    refreshCell: refreshCellFunction,
                    eGridCell: eGridCell
                };
                var cellRenderer;
                if (typeof colDef.cellRenderer === 'object' && colDef.cellRenderer !== null) {
                    cellRenderer = this.cellRendererMap[colDef.cellRenderer.renderer];
                    if (!cellRenderer) {
                        throw 'Cell renderer ' + colDef.cellRenderer + ' not found, available are ' + Object.keys(this.cellRendererMap);
                    }
                }
                else if (typeof colDef.cellRenderer === 'function') {
                    cellRenderer = colDef.cellRenderer;
                }
                else {
                    throw 'Cell Renderer must be String or Function';
                }
                var resultFromRenderer = cellRenderer(rendererParams);
                if (utils.isNodeOrElement(resultFromRenderer)) {
                    // a dom node or element was returned, so add child
                    eSpanWithValue.appendChild(resultFromRenderer);
                }
                else {
                    // otherwise assume it was html, so just insert
                    eSpanWithValue.innerHTML = resultFromRenderer;
                }
            };
            RowRenderer.prototype.addStylesFromCollDef = function (column, value, node, $childScope, eGridCell) {
                var colDef = column.colDef;
                if (colDef.cellStyle) {
                    var cssToUse;
                    if (typeof colDef.cellStyle === 'function') {
                        var cellStyleParams = {
                            value: value,
                            data: node.data,
                            node: node,
                            colDef: colDef,
                            column: column,
                            $scope: $childScope,
                            context: this.gridOptionsWrapper.getContext(),
                            api: this.gridOptionsWrapper.getApi()
                        };
                        cssToUse = colDef.cellStyle(cellStyleParams);
                    }
                    else {
                        cssToUse = colDef.cellStyle;
                    }
                    if (cssToUse) {
                        utils.addStylesToElement(eGridCell, cssToUse);
                    }
                }
            };
            RowRenderer.prototype.addClassesFromCollDef = function (colDef, value, node, $childScope, eGridCell) {
                if (colDef.cellClass) {
                    var classToUse;
                    if (typeof colDef.cellClass === 'function') {
                        var cellClassParams = {
                            value: value,
                            data: node.data,
                            node: node,
                            colDef: colDef,
                            $scope: $childScope,
                            context: this.gridOptionsWrapper.getContext(),
                            api: this.gridOptionsWrapper.getApi()
                        };
                        classToUse = colDef.cellClass(cellClassParams);
                    }
                    else {
                        classToUse = colDef.cellClass;
                    }
                    if (typeof classToUse === 'string') {
                        utils.addCssClass(eGridCell, classToUse);
                    }
                    else if (Array.isArray(classToUse)) {
                        classToUse.forEach(function (cssClassItem) {
                            utils.addCssClass(eGridCell, cssClassItem);
                        });
                    }
                }
            };
            RowRenderer.prototype.addClassesToCell = function (column, node, eGridCell) {
                var classes = ['ag-cell', 'ag-cell-no-focus', 'cell-col-' + column.index];
                if (node.group) {
                    if (node.footer) {
                        classes.push('ag-footer-cell');
                    }
                    else {
                        classes.push('ag-group-cell');
                    }
                }
                eGridCell.className = classes.join(' ');
            };
            RowRenderer.prototype.addClassesFromRules = function (colDef, eGridCell, value, node, rowIndex) {
                var classRules = colDef.cellClassRules;
                if (typeof classRules === 'object' && classRules !== null) {
                    var params = {
                        value: value,
                        data: node.data,
                        node: node,
                        colDef: colDef,
                        rowIndex: rowIndex,
                        api: this.gridOptionsWrapper.getApi(),
                        context: this.gridOptionsWrapper.getContext()
                    };
                    var classNames = Object.keys(classRules);
                    for (var i = 0; i < classNames.length; i++) {
                        var className = classNames[i];
                        var rule = classRules[className];
                        var resultOfRule;
                        if (typeof rule === 'string') {
                            resultOfRule = this.expressionService.evaluate(rule, params);
                        }
                        else if (typeof rule === 'function') {
                            resultOfRule = rule(params);
                        }
                        if (resultOfRule) {
                            utils.addCssClass(eGridCell, className);
                        }
                        else {
                            utils.removeCssClass(eGridCell, className);
                        }
                    }
                }
            };
            RowRenderer.prototype.createCell = function (isFirstColumn, column, valueGetter, node, rowIndex, $childScope) {
                var that = this;
                var eGridCell = document.createElement("div");
                eGridCell.setAttribute("col", column.index);
                // only set tab index if cell selection is enabled
                if (!this.gridOptionsWrapper.isSuppressCellSelection()) {
                    eGridCell.setAttribute("tabindex", "-1");
                }
                var value;
                if (valueGetter) {
                    value = valueGetter();
                }
                // these are the grid styles, don't change between soft refreshes
                this.addClassesToCell(column, node, eGridCell);
                this.populateAndStyleGridCell(valueGetter, value, eGridCell, isFirstColumn, node, column, rowIndex, $childScope);
                this.addCellClickedHandler(eGridCell, node, column, value, rowIndex);
                this.addCellDoubleClickedHandler(eGridCell, node, column, value, rowIndex, $childScope, isFirstColumn, valueGetter);
                this.addCellNavigationHandler(eGridCell, rowIndex, column, node);
                eGridCell.style.width = utils.formatWidth(column.actualWidth);
                // add the 'start editing' call to the chain of editors
                this.renderedRowStartEditingListeners[rowIndex][column.colId] = function () {
                    if (that.isCellEditable(column.colDef, node)) {
                        that.startEditing(eGridCell, column, node, $childScope, rowIndex, isFirstColumn, valueGetter);
                        return true;
                    }
                    else {
                        return false;
                    }
                };
                return eGridCell;
            };
            RowRenderer.prototype.addCellNavigationHandler = function (eGridCell, rowIndex, column, node) {
                var that = this;
                eGridCell.addEventListener('keydown', function (event) {
                    if (that.editingCell) {
                        return;
                    }
                    // only interested on key presses that are directly on this element, not any children elements. this
                    // stops navigation if the user is in, for example, a text field inside the cell, and user hits
                    // on of the keys we are looking for.
                    if (event.target !== eGridCell) {
                        return;
                    }
                    var key = event.which || event.keyCode;
                    var startNavigation = key === constants.KEY_DOWN || key === constants.KEY_UP || key === constants.KEY_LEFT || key === constants.KEY_RIGHT;
                    if (startNavigation) {
                        event.preventDefault();
                        that.navigateToNextCell(key, rowIndex, column);
                    }
                    var startEdit = key === constants.KEY_ENTER;
                    if (startEdit) {
                        var startEditingFunc = that.renderedRowStartEditingListeners[rowIndex][column.colId];
                        if (startEditingFunc) {
                            var editingStarted = startEditingFunc();
                            if (editingStarted) {
                                // if we don't prevent default, then the editor that get displayed also picks up the 'enter key'
                                // press, and stops editing immediately, hence giving he user experience that nothing happened
                                event.preventDefault();
                            }
                        }
                    }
                    var selectRow = key === constants.KEY_SPACE;
                    if (selectRow && that.gridOptionsWrapper.isRowSelection()) {
                        var selected = that.selectionController.isNodeSelected(node);
                        if (selected) {
                            that.selectionController.deselectNode(node);
                        }
                        else {
                            that.selectionController.selectNode(node, true);
                        }
                        event.preventDefault();
                    }
                });
            };
            // we use index for rows, but column object for columns, as the next column (by index) might not
            // be visible (header grouping) so it's not reliable, so using the column object instead.
            RowRenderer.prototype.navigateToNextCell = function (key, rowIndex, column) {
                var cellToFocus = { rowIndex: rowIndex, column: column };
                var renderedRow;
                var eCell;
                while (!eCell) {
                    cellToFocus = this.getNextCellToFocus(key, cellToFocus);
                    // no next cell means we have reached a grid boundary, eg left, right, top or bottom of grid
                    if (!cellToFocus) {
                        return;
                    }
                    // see if the next cell is selectable, if yes, use it, if not, skip it
                    renderedRow = this.renderedRows[cellToFocus.rowIndex];
                    eCell = renderedRow.eCells[cellToFocus.column.colId];
                }
                // this scrolls the row into view
                this.gridPanel.ensureIndexVisible(renderedRow.rowIndex);
                // this changes the css on the cell
                this.focusCell(eCell, cellToFocus.rowIndex, cellToFocus.column.index, true);
            };
            RowRenderer.prototype.getNextCellToFocus = function (key, lastCellToFocus) {
                var lastRowIndex = lastCellToFocus.rowIndex;
                var lastColumn = lastCellToFocus.column;
                var nextRowToFocus;
                var nextColumnToFocus;
                switch (key) {
                    case constants.KEY_UP:
                        // if already on top row, do nothing
                        if (lastRowIndex === this.firstVirtualRenderedRow) {
                            return null;
                        }
                        nextRowToFocus = lastRowIndex - 1;
                        nextColumnToFocus = lastColumn;
                        break;
                    case constants.KEY_DOWN:
                        // if already on bottom, do nothing
                        if (lastRowIndex === this.lastVirtualRenderedRow) {
                            return null;
                        }
                        nextRowToFocus = lastRowIndex + 1;
                        nextColumnToFocus = lastColumn;
                        break;
                    case constants.KEY_RIGHT:
                        var colToRight = this.columnModel.getVisibleColAfter(lastColumn);
                        // if already on right, do nothing
                        if (!colToRight) {
                            return null;
                        }
                        nextRowToFocus = lastRowIndex;
                        nextColumnToFocus = colToRight;
                        break;
                    case constants.KEY_LEFT:
                        var colToLeft = this.columnModel.getVisibleColBefore(lastColumn);
                        // if already on left, do nothing
                        if (!colToLeft) {
                            return null;
                        }
                        nextRowToFocus = lastRowIndex;
                        nextColumnToFocus = colToLeft;
                        break;
                }
                return {
                    rowIndex: nextRowToFocus,
                    column: nextColumnToFocus
                };
            };
            // called internally
            RowRenderer.prototype.focusCell = function (eCell, rowIndex, colIndex, forceBrowserFocus) {
                // do nothing if cell selection is off
                if (this.gridOptionsWrapper.isSuppressCellSelection()) {
                    return;
                }
                // remove any previous focus
                utils.querySelectorAll_replaceCssClass(this.eParentOfRows, '.ag-cell-focus', 'ag-cell-focus', 'ag-cell-no-focus');
                var selectorForCell = '[row="' + rowIndex + '"] [col="' + colIndex + '"]';
                utils.querySelectorAll_replaceCssClass(this.eParentOfRows, selectorForCell, 'ag-cell-no-focus', 'ag-cell-focus');
                this.focusedCell = { rowIndex: rowIndex, colIndex: colIndex, node: this.rowModel.getVirtualRow(rowIndex) };
                // this puts the browser focus on the cell (so it gets key presses)
                if (forceBrowserFocus) {
                    eCell.focus();
                }
                if (typeof this.gridOptionsWrapper.getCellFocused() === 'function') {
                    this.gridOptionsWrapper.getCellFocused()(this.focusedCell);
                }
            };
            // for API
            RowRenderer.prototype.getFocusedCell = function () {
                return this.focusedCell;
            };
            // called via API
            RowRenderer.prototype.setFocusedCell = function (rowIndex, colIndex) {
                var renderedRow = this.renderedRows[rowIndex];
                var column = this.columnModel.getDisplayedColumns()[colIndex];
                if (renderedRow && column) {
                    var eCell = renderedRow.eCells[column.colId];
                    this.focusCell(eCell, rowIndex, colIndex, true);
                }
            };
            RowRenderer.prototype.populateAndStyleGridCell = function (valueGetter, value, eGridCell, isFirstColumn, node, column, rowIndex, $childScope) {
                var colDef = column.colDef;
                // populate
                this.populateGridCell(eGridCell, isFirstColumn, node, column, rowIndex, value, valueGetter, $childScope);
                // style
                this.addStylesFromCollDef(column, value, node, $childScope, eGridCell);
                this.addClassesFromCollDef(colDef, value, node, $childScope, eGridCell);
                this.addClassesFromRules(colDef, eGridCell, value, node, rowIndex);
            };
            RowRenderer.prototype.populateGridCell = function (eGridCell, isFirstColumn, node, column, rowIndex, value, valueGetter, $childScope) {
                var eCellWrapper = document.createElement('span');
                utils.addCssClass(eCellWrapper, "ag-cell-wrapper");
                eGridCell.appendChild(eCellWrapper);
                var colDef = column.colDef;
                if (colDef.checkboxSelection) {
                    var eCheckbox = this.selectionRendererFactory.createSelectionCheckbox(node, rowIndex);
                    eCellWrapper.appendChild(eCheckbox);
                }
                // eventually we call eSpanWithValue.innerHTML = xxx, so cannot include the checkbox (above) in this span
                var eSpanWithValue = document.createElement("span");
                utils.addCssClass(eSpanWithValue, "ag-cell-value");
                eCellWrapper.appendChild(eSpanWithValue);
                var that = this;
                var refreshCellFunction = function () {
                    that.softRefreshCell(eGridCell, isFirstColumn, node, column, $childScope, rowIndex);
                };
                this.putDataIntoCell(column, value, valueGetter, node, $childScope, eSpanWithValue, eGridCell, rowIndex, refreshCellFunction);
            };
            RowRenderer.prototype.addCellDoubleClickedHandler = function (eGridCell, node, column, value, rowIndex, $childScope, isFirstColumn, valueGetter) {
                var that = this;
                var colDef = column.colDef;
                eGridCell.addEventListener('dblclick', function (event) {
                    if (that.gridOptionsWrapper.getCellDoubleClicked()) {
                        var paramsForGrid = {
                            node: node,
                            data: node.data,
                            value: value,
                            rowIndex: rowIndex,
                            colDef: colDef,
                            event: event,
                            eventSource: this,
                            api: that.gridOptionsWrapper.getApi()
                        };
                        that.gridOptionsWrapper.getCellDoubleClicked()(paramsForGrid);
                    }
                    if (colDef.cellDoubleClicked) {
                        var paramsForColDef = {
                            node: node,
                            data: node.data,
                            value: value,
                            rowIndex: rowIndex,
                            colDef: colDef,
                            event: event,
                            eventSource: this,
                            api: that.gridOptionsWrapper.getApi()
                        };
                        colDef.cellDoubleClicked(paramsForColDef);
                    }
                    if (that.isCellEditable(colDef, node)) {
                        that.startEditing(eGridCell, column, node, $childScope, rowIndex, isFirstColumn, valueGetter);
                    }
                });
            };
            RowRenderer.prototype.addCellClickedHandler = function (eGridCell, node, column, value, rowIndex) {
                var colDef = column.colDef;
                var that = this;
                eGridCell.addEventListener("click", function (event) {
                    // we pass false to focusCell, as we don't want the cell to focus
                    // also get the browser focus. if we did, then the cellRenderer could
                    // have a text field in it, for example, and as the user clicks on the
                    // text field, the text field, the focus doesn't get to the text
                    // field, instead to goes to the div behind, making it impossible to
                    // select the text field.
                    that.focusCell(eGridCell, rowIndex, column.index, false);
                    if (that.gridOptionsWrapper.getCellClicked()) {
                        var paramsForGrid = {
                            node: node,
                            data: node.data,
                            value: value,
                            rowIndex: rowIndex,
                            colDef: colDef,
                            event: event,
                            eventSource: this,
                            api: that.gridOptionsWrapper.getApi()
                        };
                        that.gridOptionsWrapper.getCellClicked()(paramsForGrid);
                    }
                    if (colDef.cellClicked) {
                        var paramsForColDef = {
                            node: node,
                            data: node.data,
                            value: value,
                            rowIndex: rowIndex,
                            colDef: colDef,
                            event: event,
                            eventSource: this,
                            api: that.gridOptionsWrapper.getApi()
                        };
                        colDef.cellClicked(paramsForColDef);
                    }
                });
            };
            RowRenderer.prototype.isCellEditable = function (colDef, node) {
                if (this.editingCell) {
                    return false;
                }
                // never allow editing of groups
                if (node.group) {
                    return false;
                }
                // if boolean set, then just use it
                if (typeof colDef.editable === 'boolean') {
                    return colDef.editable;
                }
                // if function, then call the function to find out
                if (typeof colDef.editable === 'function') {
                    // should change this, so it gets passed params with nice useful values
                    return colDef.editable(node.data);
                }
                return false;
            };
            RowRenderer.prototype.stopEditing = function (eGridCell, column, node, $childScope, eInput, blurListener, rowIndex, isFirstColumn, valueGetter) {
                this.editingCell = false;
                var newValue = eInput.value;
                var colDef = column.colDef;
                //If we don't remove the blur listener first, we get:
                //Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is no longer a child of this node. Perhaps it was moved in a 'blur' event handler?
                eInput.removeEventListener('blur', blurListener);
                utils.removeAllChildren(eGridCell);
                var paramsForCallbacks = {
                    node: node,
                    data: node.data,
                    oldValue: node.data[colDef.field],
                    newValue: newValue,
                    rowIndex: rowIndex,
                    colDef: colDef,
                    api: this.gridOptionsWrapper.getApi(),
                    context: this.gridOptionsWrapper.getContext()
                };
                if (colDef.newValueHandler) {
                    colDef.newValueHandler(paramsForCallbacks);
                }
                else {
                    node.data[colDef.field] = newValue;
                }
                // at this point, the value has been updated
                var newValue;
                if (valueGetter) {
                    newValue = valueGetter();
                }
                paramsForCallbacks.newValue = newValue;
                if (typeof colDef.cellValueChanged === 'function') {
                    colDef.cellValueChanged(paramsForCallbacks);
                }
                if (typeof this.gridOptionsWrapper.getCellValueChanged() === 'function') {
                    this.gridOptionsWrapper.getCellValueChanged()(paramsForCallbacks);
                }
                this.populateAndStyleGridCell(valueGetter, newValue, eGridCell, isFirstColumn, node, column, rowIndex, $childScope);
            };
            RowRenderer.prototype.startEditing = function (eGridCell, column, node, $childScope, rowIndex, isFirstColumn, valueGetter) {
                var that = this;
                this.editingCell = true;
                utils.removeAllChildren(eGridCell);
                var eInput = document.createElement('input');
                eInput.type = 'text';
                utils.addCssClass(eInput, 'ag-cell-edit-input');
                if (valueGetter) {
                    var value = valueGetter();
                    if (value !== null && value !== undefined) {
                        eInput.value = value;
                    }
                }
                eInput.style.width = (column.actualWidth - 14) + 'px';
                eGridCell.appendChild(eInput);
                eInput.focus();
                eInput.select();
                var blurListener = function () {
                    that.stopEditing(eGridCell, column, node, $childScope, eInput, blurListener, rowIndex, isFirstColumn, valueGetter);
                };
                //stop entering if we loose focus
                eInput.addEventListener("blur", blurListener);
                //stop editing if enter pressed
                eInput.addEventListener('keypress', function (event) {
                    var key = event.which || event.keyCode;
                    // 13 is enter
                    if (key == constants.KEY_ENTER) {
                        that.stopEditing(eGridCell, column, node, $childScope, eInput, blurListener, rowIndex, isFirstColumn, valueGetter);
                        that.focusCell(eGridCell, rowIndex, column.index, true);
                    }
                });
                // tab key doesn't generate keypress, so need keydown to listen for that
                eInput.addEventListener('keydown', function (event) {
                    var key = event.which || event.keyCode;
                    if (key == constants.KEY_TAB) {
                        that.stopEditing(eGridCell, column, node, $childScope, eInput, blurListener, rowIndex, isFirstColumn, valueGetter);
                        that.startEditingNextCell(rowIndex, column, event.shiftKey);
                        // we don't want the default tab action, so return false, this stops the event from bubbling
                        event.preventDefault();
                        return false;
                    }
                });
            };
            RowRenderer.prototype.startEditingNextCell = function (rowIndex, column, shiftKey) {
                var firstRowToCheck = this.firstVirtualRenderedRow;
                var lastRowToCheck = this.lastVirtualRenderedRow;
                var currentRowIndex = rowIndex;
                var visibleColumns = this.columnModel.getDisplayedColumns();
                var currentCol = column;
                while (true) {
                    var indexOfCurrentCol = visibleColumns.indexOf(currentCol);
                    // move backward
                    if (shiftKey) {
                        // move along to the previous cell
                        currentCol = visibleColumns[indexOfCurrentCol - 1];
                        // check if end of the row, and if so, go back a row
                        if (!currentCol) {
                            currentCol = visibleColumns[visibleColumns.length - 1];
                            currentRowIndex--;
                        }
                        // if got to end of rendered rows, then quit looking
                        if (currentRowIndex < firstRowToCheck) {
                            return;
                        }
                    }
                    else {
                        // move along to the next cell
                        currentCol = visibleColumns[indexOfCurrentCol + 1];
                        // check if end of the row, and if so, go forward a row
                        if (!currentCol) {
                            currentCol = visibleColumns[0];
                            currentRowIndex++;
                        }
                        // if got to end of rendered rows, then quit looking
                        if (currentRowIndex > lastRowToCheck) {
                            return;
                        }
                    }
                    var nextFunc = this.renderedRowStartEditingListeners[currentRowIndex][currentCol.colId];
                    if (nextFunc) {
                        // see if the next cell is editable, and if so, we have come to
                        // the end of our search, so stop looking for the next cell
                        var nextCellAcceptedEdit = nextFunc();
                        if (nextCellAcceptedEdit) {
                            return;
                        }
                    }
                }
            };
            return RowRenderer;
        })();
        grid.RowRenderer = RowRenderer;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="utils.ts" />
/// <reference path="constants.ts" />
/// <reference path="svgFactory.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var constants = grid.Constants;
        var svgFactory = grid.SvgFactory.getInstance();
        var HeaderRenderer = (function () {
            function HeaderRenderer() {
            }
            HeaderRenderer.prototype.init = function (gridOptionsWrapper, columnController, columnModel, gridPanel, angularGrid, filterManager, $scope, $compile, expressionService) {
                this.expressionService = expressionService;
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.columnModel = columnModel;
                this.columnController = columnController;
                this.angularGrid = angularGrid;
                this.filterManager = filterManager;
                this.$scope = $scope;
                this.$compile = $compile;
                this.findAllElements(gridPanel);
            };
            HeaderRenderer.prototype.findAllElements = function (gridPanel) {
                this.ePinnedHeader = gridPanel.getPinnedHeader();
                this.eHeaderContainer = gridPanel.getHeaderContainer();
                this.eHeader = gridPanel.getHeader();
                this.eRoot = gridPanel.getRoot();
            };
            HeaderRenderer.prototype.refreshHeader = function () {
                utils.removeAllChildren(this.ePinnedHeader);
                utils.removeAllChildren(this.eHeaderContainer);
                if (this.childScopes) {
                    this.childScopes.forEach(function (childScope) {
                        childScope.$destroy();
                    });
                }
                this.childScopes = [];
                if (this.gridOptionsWrapper.isGroupHeaders()) {
                    this.insertHeadersWithGrouping();
                }
                else {
                    this.insertHeadersWithoutGrouping();
                }
            };
            HeaderRenderer.prototype.insertHeadersWithGrouping = function () {
                var groups = this.columnModel.getHeaderGroups();
                var that = this;
                groups.forEach(function (group) {
                    var eHeaderCell = that.createGroupedHeaderCell(group);
                    var eContainerToAddTo = group.pinned ? that.ePinnedHeader : that.eHeaderContainer;
                    eContainerToAddTo.appendChild(eHeaderCell);
                });
            };
            HeaderRenderer.prototype.createGroupedHeaderCell = function (group) {
                var eHeaderGroup = document.createElement('div');
                eHeaderGroup.className = 'ag-header-group';
                var eHeaderGroupCell = document.createElement('div');
                group.eHeaderGroupCell = eHeaderGroupCell;
                var classNames = ['ag-header-group-cell'];
                // having different classes below allows the style to not have a bottom border
                // on the group header, if no group is specified
                if (group.name) {
                    classNames.push('ag-header-group-cell-with-group');
                }
                else {
                    classNames.push('ag-header-group-cell-no-group');
                }
                eHeaderGroupCell.className = classNames.join(' ');
                if (this.gridOptionsWrapper.isEnableColResize()) {
                    var eHeaderCellResize = document.createElement("div");
                    eHeaderCellResize.className = "ag-header-cell-resize";
                    eHeaderGroupCell.appendChild(eHeaderCellResize);
                    group.eHeaderCellResize = eHeaderCellResize;
                    var dragCallback = this.groupDragCallbackFactory(group);
                    this.addDragHandler(eHeaderCellResize, dragCallback);
                }
                // no renderer, default text render
                var groupName = group.name;
                if (groupName && groupName !== '') {
                    var eGroupCellLabel = document.createElement("div");
                    eGroupCellLabel.className = 'ag-header-group-cell-label';
                    eHeaderGroupCell.appendChild(eGroupCellLabel);
                    var eInnerText = document.createElement("span");
                    eInnerText.className = 'ag-header-group-text';
                    eInnerText.innerHTML = groupName;
                    eGroupCellLabel.appendChild(eInnerText);
                    if (group.expandable) {
                        this.addGroupExpandIcon(group, eGroupCellLabel, group.expanded);
                    }
                }
                eHeaderGroup.appendChild(eHeaderGroupCell);
                var that = this;
                group.displayedColumns.forEach(function (column) {
                    var eHeaderCell = that.createHeaderCell(column, true, group);
                    eHeaderGroup.appendChild(eHeaderCell);
                });
                that.setWidthOfGroupHeaderCell(group);
                return eHeaderGroup;
            };
            HeaderRenderer.prototype.addGroupExpandIcon = function (group, eHeaderGroup, expanded) {
                var eGroupIcon;
                if (expanded) {
                    eGroupIcon = utils.createIcon('headerGroupOpened', this.gridOptionsWrapper, null, svgFactory.createArrowLeftSvg);
                }
                else {
                    eGroupIcon = utils.createIcon('headerGroupClosed', this.gridOptionsWrapper, null, svgFactory.createArrowRightSvg);
                }
                eGroupIcon.className = 'ag-header-expand-icon';
                eHeaderGroup.appendChild(eGroupIcon);
                var that = this;
                eGroupIcon.onclick = function () {
                    that.columnController.headerGroupOpened(group);
                };
            };
            HeaderRenderer.prototype.addDragHandler = function (eDraggableElement, dragCallback) {
                var that = this;
                eDraggableElement.addEventListener('mousedown', function (downEvent) {
                    dragCallback.onDragStart();
                    that.eRoot.style.cursor = "col-resize";
                    that.dragStartX = downEvent.clientX;
                    var listenersToRemove = {};
                    listenersToRemove.mousemove = function (moveEvent) {
                        var newX = moveEvent.clientX;
                        var change = newX - that.dragStartX;
                        dragCallback.onDragging(change);
                    };
                    listenersToRemove.mouseup = function () {
                        that.stopDragging(listenersToRemove);
                    };
                    listenersToRemove.mouseleave = function () {
                        that.stopDragging(listenersToRemove);
                    };
                    that.eRoot.addEventListener('mousemove', listenersToRemove.mousemove);
                    that.eRoot.addEventListener('mouseup', listenersToRemove.mouseup);
                    that.eRoot.addEventListener('mouseleave', listenersToRemove.mouseleave);
                });
            };
            HeaderRenderer.prototype.setWidthOfGroupHeaderCell = function (headerGroup) {
                var totalWidth = 0;
                headerGroup.displayedColumns.forEach(function (column) {
                    totalWidth += column.actualWidth;
                });
                headerGroup.eHeaderGroupCell.style.width = utils.formatWidth(totalWidth);
                headerGroup.actualWidth = totalWidth;
            };
            HeaderRenderer.prototype.insertHeadersWithoutGrouping = function () {
                var ePinnedHeader = this.ePinnedHeader;
                var eHeaderContainer = this.eHeaderContainer;
                var that = this;
                this.columnModel.getDisplayedColumns().forEach(function (column) {
                    // only include the first x cols
                    var headerCell = that.createHeaderCell(column, false);
                    if (column.pinned) {
                        ePinnedHeader.appendChild(headerCell);
                    }
                    else {
                        eHeaderContainer.appendChild(headerCell);
                    }
                });
            };
            HeaderRenderer.prototype.createHeaderCell = function (column, grouped, headerGroup) {
                var that = this;
                var colDef = column.colDef;
                var eHeaderCell = document.createElement("div");
                // stick the header cell in column, as we access it when group is re-sized
                column.eHeaderCell = eHeaderCell;
                var newChildScope;
                if (this.gridOptionsWrapper.isAngularCompileHeaders()) {
                    newChildScope = this.$scope.$new();
                    newChildScope.colDef = colDef;
                    newChildScope.colIndex = colDef.index;
                    newChildScope.colDefWrapper = column;
                    this.childScopes.push(newChildScope);
                }
                var headerCellClasses = ['ag-header-cell'];
                if (grouped) {
                    headerCellClasses.push('ag-header-cell-grouped'); // this takes 50% height
                }
                else {
                    headerCellClasses.push('ag-header-cell-not-grouped'); // this takes 100% height
                }
                eHeaderCell.className = headerCellClasses.join(' ');
                this.addHeaderClassesFromCollDef(colDef, newChildScope, eHeaderCell);
                // add tooltip if exists
                if (colDef.headerTooltip) {
                    eHeaderCell.title = colDef.headerTooltip;
                }
                if (this.gridOptionsWrapper.isEnableColResize() && !colDef.suppressResize) {
                    var headerCellResize = document.createElement("div");
                    headerCellResize.className = "ag-header-cell-resize";
                    eHeaderCell.appendChild(headerCellResize);
                    var dragCallback = this.headerDragCallbackFactory(eHeaderCell, column, headerGroup);
                    this.addDragHandler(headerCellResize, dragCallback);
                }
                // filter button
                var showMenu = this.gridOptionsWrapper.isEnableFilter() && !colDef.suppressMenu;
                if (showMenu) {
                    var eMenuButton = utils.createIcon('menu', this.gridOptionsWrapper, column, svgFactory.createMenuSvg);
                    utils.addCssClass(eMenuButton, 'ag-header-icon');
                    eMenuButton.setAttribute("class", "ag-header-cell-menu-button");
                    eMenuButton.onclick = function () {
                        that.filterManager.showFilter(column, this);
                    };
                    eHeaderCell.appendChild(eMenuButton);
                    eHeaderCell.onmouseenter = function () {
                        eMenuButton.style.opacity = '1';
                    };
                    eHeaderCell.onmouseleave = function () {
                        eMenuButton.style.opacity = '0';
                    };
                    eMenuButton.style.opacity = '0';
                    eMenuButton.style['transition'] = 'opacity 0.5s, border 0.2s';
                    var style = eMenuButton.style;
                    style['-webkit-transition'] = 'opacity 0.5s, border 0.2s';
                }
                // label div
                var headerCellLabel = document.createElement("div");
                headerCellLabel.className = "ag-header-cell-label";
                // add in sort icons
                if (this.gridOptionsWrapper.isEnableSorting() && !colDef.suppressSorting) {
                    column.eSortAsc = utils.createIcon('sortAscending', this.gridOptionsWrapper, column, svgFactory.createArrowUpSvg);
                    column.eSortDesc = utils.createIcon('sortDescending', this.gridOptionsWrapper, column, svgFactory.createArrowDownSvg);
                    utils.addCssClass(column.eSortAsc, 'ag-header-icon ag-sort-ascending-icon');
                    utils.addCssClass(column.eSortDesc, 'ag-header-icon ag-sort-descending-icon');
                    headerCellLabel.appendChild(column.eSortAsc);
                    headerCellLabel.appendChild(column.eSortDesc);
                    // 'no sort' icon
                    if (colDef.unSortIcon || this.gridOptionsWrapper.isUnSortIcon()) {
                        column.eSortNone = utils.createIcon('sortUnSort', this.gridOptionsWrapper, column, svgFactory.createArrowUpDownSvg);
                        utils.addCssClass(column.eSortNone, 'ag-header-icon ag-sort-none-icon');
                        headerCellLabel.appendChild(column.eSortNone);
                    }
                    column.eSortAsc.style.display = 'none';
                    column.eSortDesc.style.display = 'none';
                    this.addSortHandling(headerCellLabel, column);
                }
                // add in filter icon
                column.eFilterIcon = utils.createIcon('filter', this.gridOptionsWrapper, column, svgFactory.createFilterSvg);
                utils.addCssClass(column.eFilterIcon, 'ag-header-icon');
                headerCellLabel.appendChild(column.eFilterIcon);
                // render the cell, use a renderer if one is provided
                var headerCellRenderer;
                if (colDef.headerCellRenderer) {
                    headerCellRenderer = colDef.headerCellRenderer;
                }
                else if (this.gridOptionsWrapper.getHeaderCellRenderer()) {
                    headerCellRenderer = this.gridOptionsWrapper.getHeaderCellRenderer();
                }
                var headerNameValue = this.columnModel.getDisplayNameForCol(column);
                if (headerCellRenderer) {
                    // renderer provided, use it
                    var cellRendererParams = {
                        colDef: colDef,
                        $scope: newChildScope,
                        context: this.gridOptionsWrapper.getContext(),
                        value: headerNameValue,
                        api: this.gridOptionsWrapper.getApi()
                    };
                    var cellRendererResult = headerCellRenderer(cellRendererParams);
                    var childToAppend;
                    if (utils.isNodeOrElement(cellRendererResult)) {
                        // a dom node or element was returned, so add child
                        childToAppend = cellRendererResult;
                    }
                    else {
                        // otherwise assume it was html, so just insert
                        var eTextSpan = document.createElement("span");
                        eTextSpan.innerHTML = cellRendererResult;
                        childToAppend = eTextSpan;
                    }
                    // angular compile header if option is turned on
                    if (this.gridOptionsWrapper.isAngularCompileHeaders()) {
                        var childToAppendCompiled = this.$compile(childToAppend)(newChildScope)[0];
                        headerCellLabel.appendChild(childToAppendCompiled);
                    }
                    else {
                        headerCellLabel.appendChild(childToAppend);
                    }
                }
                else {
                    // no renderer, default text render
                    var eInnerText = document.createElement("span");
                    eInnerText.className = 'ag-header-cell-text';
                    eInnerText.innerHTML = headerNameValue;
                    headerCellLabel.appendChild(eInnerText);
                }
                eHeaderCell.appendChild(headerCellLabel);
                eHeaderCell.style.width = utils.formatWidth(column.actualWidth);
                return eHeaderCell;
            };
            HeaderRenderer.prototype.addHeaderClassesFromCollDef = function (colDef, $childScope, eHeaderCell) {
                if (colDef.headerClass) {
                    var classToUse;
                    if (typeof colDef.headerClass === 'function') {
                        var params = {
                            colDef: colDef,
                            $scope: $childScope,
                            context: this.gridOptionsWrapper.getContext(),
                            api: this.gridOptionsWrapper.getApi()
                        };
                        classToUse = colDef.headerClass(params);
                    }
                    else {
                        classToUse = colDef.headerClass;
                    }
                    if (typeof classToUse === 'string') {
                        utils.addCssClass(eHeaderCell, classToUse);
                    }
                    else if (Array.isArray(classToUse)) {
                        classToUse.forEach(function (cssClassItem) {
                            utils.addCssClass(eHeaderCell, cssClassItem);
                        });
                    }
                }
            };
            HeaderRenderer.prototype.getNextSortDirection = function (direction) {
                var suppressUnSort = this.gridOptionsWrapper.isSuppressUnSort();
                var suppressDescSort = this.gridOptionsWrapper.isSuppressDescSort();
                switch (direction) {
                    case constants.DESC:
                        if (suppressUnSort) {
                            return constants.ASC;
                        }
                        else {
                            return null;
                        }
                    case constants.ASC:
                        if (suppressUnSort && suppressDescSort) {
                            return constants.ASC;
                        }
                        else if (suppressDescSort) {
                            return null;
                        }
                        else {
                            return constants.DESC;
                        }
                    default:
                        return constants.ASC;
                }
            };
            HeaderRenderer.prototype.addSortHandling = function (headerCellLabel, column) {
                var that = this;
                headerCellLabel.addEventListener("click", function (e) {
                    // update sort on current col
                    column.sort = that.getNextSortDirection(column.sort);
                    // sortedAt used for knowing order of cols when multi-col sort
                    if (column.sort) {
                        column.sortedAt = new Date().valueOf();
                    }
                    else {
                        column.sortedAt = null;
                    }
                    var doingMultiSort = !that.gridOptionsWrapper.isSuppressMultiSort() && e.shiftKey;
                    // clear sort on all columns except this one, and update the icons
                    that.columnModel.getAllColumns().forEach(function (columnToClear) {
                        // Do not clear if either holding shift, or if column in question was clicked
                        if (!(doingMultiSort || columnToClear === column)) {
                            columnToClear.sort = null;
                        }
                    });
                    that.angularGrid.onSortingChanged();
                });
            };
            HeaderRenderer.prototype.updateSortIcons = function () {
                this.columnModel.getAllColumns().forEach(function (column) {
                    // update visibility of icons
                    var sortAscending = column.sort === constants.ASC;
                    var sortDescending = column.sort === constants.DESC;
                    var unSort = column.sort !== constants.DESC && column.sort !== constants.ASC;
                    if (column.eSortAsc) {
                        utils.setVisible(column.eSortAsc, sortAscending);
                    }
                    if (column.eSortDesc) {
                        utils.setVisible(column.eSortDesc, sortDescending);
                    }
                    // UnSort Icon
                    if (column.eSortNone) {
                        utils.setVisible(column.eSortNone, unSort);
                    }
                });
            };
            HeaderRenderer.prototype.groupDragCallbackFactory = function (currentGroup) {
                var parent = this;
                var displayedColumns = currentGroup.displayedColumns;
                return {
                    onDragStart: function () {
                        this.groupWidthStart = currentGroup.actualWidth;
                        this.childrenWidthStarts = [];
                        var that = this;
                        displayedColumns.forEach(function (colDefWrapper) {
                            that.childrenWidthStarts.push(colDefWrapper.actualWidth);
                        });
                        this.minWidth = displayedColumns.length * constants.MIN_COL_WIDTH;
                    },
                    onDragging: function (dragChange) {
                        var newWidth = this.groupWidthStart + dragChange;
                        if (newWidth < this.minWidth) {
                            newWidth = this.minWidth;
                        }
                        // set the new width to the group header
                        var newWidthPx = newWidth + "px";
                        currentGroup.eHeaderGroupCell.style.width = newWidthPx;
                        currentGroup.actualWidth = newWidth;
                        // distribute the new width to the child headers
                        var changeRatio = newWidth / this.groupWidthStart;
                        // keep track of pixels used, and last column gets the remaining,
                        // to cater for rounding errors, and min width adjustments
                        var pixelsToDistribute = newWidth;
                        var that = this;
                        currentGroup.displayedColumns.forEach(function (colDefWrapper, index) {
                            var notLastCol = index !== (displayedColumns.length - 1);
                            var newChildSize;
                            if (notLastCol) {
                                // if not the last col, calculate the column width as normal
                                var startChildSize = that.childrenWidthStarts[index];
                                newChildSize = startChildSize * changeRatio;
                                if (newChildSize < constants.MIN_COL_WIDTH) {
                                    newChildSize = constants.MIN_COL_WIDTH;
                                }
                                pixelsToDistribute -= newChildSize;
                            }
                            else {
                                // if last col, give it the remaining pixels
                                newChildSize = pixelsToDistribute;
                            }
                            var eHeaderCell = displayedColumns[index].eHeaderCell;
                            parent.adjustColumnWidth(newChildSize, colDefWrapper, eHeaderCell);
                        });
                        // should not be calling these here, should do something else
                        if (currentGroup.pinned) {
                            parent.angularGrid.updatePinnedColContainerWidthAfterColResize();
                        }
                        else {
                            parent.angularGrid.updateBodyContainerWidthAfterColResize();
                        }
                    }
                };
            };
            HeaderRenderer.prototype.adjustColumnWidth = function (newWidth, column, eHeaderCell) {
                var newWidthPx = newWidth + "px";
                var selectorForAllColsInCell = ".cell-col-" + column.index;
                var cellsForThisCol = this.eRoot.querySelectorAll(selectorForAllColsInCell);
                for (var i = 0; i < cellsForThisCol.length; i++) {
                    cellsForThisCol[i].style.width = newWidthPx;
                }
                eHeaderCell.style.width = newWidthPx;
                column.actualWidth = newWidth;
            };
            // gets called when a header (not a header group) gets resized
            HeaderRenderer.prototype.headerDragCallbackFactory = function (headerCell, column, headerGroup) {
                var parent = this;
                return {
                    onDragStart: function () {
                        this.startWidth = column.actualWidth;
                    },
                    onDragging: function (dragChange) {
                        var newWidth = this.startWidth + dragChange;
                        if (newWidth < constants.MIN_COL_WIDTH) {
                            newWidth = constants.MIN_COL_WIDTH;
                        }
                        parent.adjustColumnWidth(newWidth, column, headerCell);
                        if (headerGroup) {
                            parent.setWidthOfGroupHeaderCell(headerGroup);
                        }
                        // should not be calling these here, should do something else
                        if (column.pinned) {
                            parent.angularGrid.updatePinnedColContainerWidthAfterColResize();
                        }
                        else {
                            parent.angularGrid.updateBodyContainerWidthAfterColResize();
                        }
                    }
                };
            };
            HeaderRenderer.prototype.stopDragging = function (listenersToRemove) {
                this.eRoot.style.cursor = "";
                var that = this;
                utils.iterateObject(listenersToRemove, function (key, listener) {
                    that.eRoot.removeEventListener(key, listener);
                });
            };
            HeaderRenderer.prototype.updateFilterIcons = function () {
                var that = this;
                this.columnModel.getDisplayedColumns().forEach(function (column) {
                    // todo: need to change this, so only updates if column is visible
                    if (column.eFilterIcon) {
                        var filterPresent = that.filterManager.isFilterPresentForCol(column.colId);
                        var displayStyle = filterPresent ? 'inline' : 'none';
                        column.eFilterIcon.style.display = displayStyle;
                    }
                });
            };
            return HeaderRenderer;
        })();
        grid.HeaderRenderer = HeaderRenderer;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var GroupCreator = (function () {
            function GroupCreator() {
            }
            GroupCreator.getInstance = function () {
                if (!this.theInstance) {
                    this.theInstance = new GroupCreator();
                }
                return this.theInstance;
            };
            GroupCreator.prototype.group = function (rowNodes, groupedCols, expandByDefault) {
                var topMostGroup = {
                    level: -1,
                    children: [],
                    childrenMap: {}
                };
                var allGroups = [];
                allGroups.push(topMostGroup);
                var levelToInsertChild = groupedCols.length - 1;
                var i;
                var currentLevel;
                var node;
                var data;
                var currentGroup;
                var groupByField;
                var groupKey;
                var nextGroup;
                // start at -1 and go backwards, as all the positive indexes
                // are already used by the nodes.
                var index = -1;
                for (i = 0; i < rowNodes.length; i++) {
                    node = rowNodes[i];
                    data = node.data;
                    // all leaf nodes have the same level in this grouping, which is one level after the last group
                    node.level = levelToInsertChild + 1;
                    for (currentLevel = 0; currentLevel < groupedCols.length; currentLevel++) {
                        groupByField = groupedCols[currentLevel].colDef.field;
                        groupKey = data[groupByField];
                        if (currentLevel == 0) {
                            currentGroup = topMostGroup;
                        }
                        // if group doesn't exist yet, create it
                        nextGroup = currentGroup.childrenMap[groupKey];
                        if (!nextGroup) {
                            nextGroup = {
                                group: true,
                                field: groupByField,
                                id: index--,
                                key: groupKey,
                                expanded: this.isExpanded(expandByDefault, currentLevel),
                                children: [],
                                // for top most level, parent is null
                                parent: currentGroup === topMostGroup ? null : currentGroup,
                                allChildrenCount: 0,
                                level: currentGroup.level + 1,
                                childrenMap: {} //this is a temporary map, we remove at the end of this method
                            };
                            currentGroup.childrenMap[groupKey] = nextGroup;
                            currentGroup.children.push(nextGroup);
                            allGroups.push(nextGroup);
                        }
                        nextGroup.allChildrenCount++;
                        if (currentLevel == levelToInsertChild) {
                            node.parent = nextGroup === topMostGroup ? null : nextGroup;
                            nextGroup.children.push(node);
                        }
                        else {
                            currentGroup = nextGroup;
                        }
                    }
                }
                for (i = 0; i < allGroups.length; i++) {
                    delete allGroups[i].childrenMap;
                }
                return topMostGroup.children;
            };
            GroupCreator.prototype.isExpanded = function (expandByDefault, level) {
                if (typeof expandByDefault === 'number') {
                    return level < expandByDefault;
                }
                else {
                    return expandByDefault === true || expandByDefault === 'true';
                }
            };
            return GroupCreator;
        })();
        grid.GroupCreator = GroupCreator;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
/// <reference path="../constants.ts" />
/// <reference path="../groupCreator.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var constants = grid.Constants;
        var groupCreator = grid.GroupCreator.getInstance();
        var InMemoryRowController = (function () {
            function InMemoryRowController() {
                this.createModel();
            }
            InMemoryRowController.prototype.init = function (gridOptionsWrapper, columnModel, angularGrid, filterManager, $scope, expressionService) {
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.columnModel = columnModel;
                this.angularGrid = angularGrid;
                this.filterManager = filterManager;
                this.$scope = $scope;
                this.expressionService = expressionService;
                this.allRows = null;
                this.rowsAfterGroup = null;
                this.rowsAfterFilter = null;
                this.rowsAfterSort = null;
                this.rowsAfterMap = null;
            };
            // private
            InMemoryRowController.prototype.createModel = function () {
                var that = this;
                this.model = {
                    // this method is implemented by the inMemory model only,
                    // it gives the top level of the selection. used by the selection
                    // controller, when it needs to do a full traversal
                    getTopLevelNodes: function () {
                        return that.rowsAfterGroup;
                    },
                    getVirtualRow: function (index) {
                        return that.rowsAfterMap[index];
                    },
                    getVirtualRowCount: function () {
                        if (that.rowsAfterMap) {
                            return that.rowsAfterMap.length;
                        }
                        else {
                            return 0;
                        }
                    },
                    forEachInMemory: function (callback) {
                        that.forEachInMemory(callback);
                    }
                };
            };
            // public
            InMemoryRowController.prototype.getModel = function () {
                return this.model;
            };
            // public
            InMemoryRowController.prototype.forEachInMemory = function (callback) {
                // iterates through each item in memory, and calls the callback function
                function doCallback(list) {
                    if (list) {
                        for (var i = 0; i < list.length; i++) {
                            var item = list[i];
                            callback(item);
                            if (item.group && item.group.children) {
                                doCallback(item.group.children);
                            }
                        }
                    }
                }
                doCallback(this.rowsAfterGroup);
            };
            // public
            InMemoryRowController.prototype.updateModel = function (step) {
                switch (step) {
                    case constants.STEP_EVERYTHING:
                    case constants.STEP_FILTER:
                        this.doFilter();
                        this.doAggregate();
                    case constants.STEP_SORT:
                        this.doSort();
                    case constants.STEP_MAP:
                        this.doGroupMapping();
                }
                if (typeof this.gridOptionsWrapper.getModelUpdated() === 'function') {
                    this.gridOptionsWrapper.getModelUpdated()();
                    var $scope = this.$scope;
                    if ($scope) {
                        setTimeout(function () {
                            $scope.$apply();
                        }, 0);
                    }
                }
            };
            // private
            InMemoryRowController.prototype.defaultGroupAggFunctionFactory = function (valueColumns, valueKeys) {
                return function groupAggFunction(rows) {
                    var result = {};
                    if (valueKeys) {
                        for (var i = 0; i < valueKeys.length; i++) {
                            var valueKey = valueKeys[i];
                            // at this point, if no values were numbers, the result is null (not zero)
                            result[valueKey] = aggregateColumn(rows, constants.SUM, valueKey);
                        }
                    }
                    if (valueColumns) {
                        for (var j = 0; j < valueColumns.length; j++) {
                            var valueColumn = valueColumns[j];
                            var colKey = valueColumn.colDef.field;
                            // at this point, if no values were numbers, the result is null (not zero)
                            result[colKey] = aggregateColumn(rows, valueColumn.aggFunc, colKey);
                        }
                    }
                    return result;
                };
                function aggregateColumn(rows, aggFunc, colKey) {
                    var resultForColumn = null;
                    for (var i = 0; i < rows.length; i++) {
                        var row = rows[i];
                        var thisColumnValue = row.data[colKey];
                        // only include if the value is a number
                        if (typeof thisColumnValue === 'number') {
                            switch (aggFunc) {
                                case constants.SUM:
                                    resultForColumn += thisColumnValue;
                                    break;
                                case constants.MIN:
                                    if (resultForColumn === null) {
                                        resultForColumn = thisColumnValue;
                                    }
                                    else if (resultForColumn > thisColumnValue) {
                                        resultForColumn = thisColumnValue;
                                    }
                                    break;
                                case constants.MAX:
                                    if (resultForColumn === null) {
                                        resultForColumn = thisColumnValue;
                                    }
                                    else if (resultForColumn < thisColumnValue) {
                                        resultForColumn = thisColumnValue;
                                    }
                                    break;
                            }
                        }
                    }
                    return resultForColumn;
                }
            };
            // private
            InMemoryRowController.prototype.getValue = function (data, colDef, node) {
                var api = this.gridOptionsWrapper.getApi();
                var context = this.gridOptionsWrapper.getContext();
                return utils.getValue(this.expressionService, data, colDef, node, api, context);
            };
            // public - it's possible to recompute the aggregate without doing the other parts
            InMemoryRowController.prototype.doAggregate = function () {
                var groupAggFunction = this.gridOptionsWrapper.getGroupAggFunction();
                if (typeof groupAggFunction === 'function') {
                    this.recursivelyCreateAggData(this.rowsAfterFilter, groupAggFunction);
                    return;
                }
                var valueColumns = this.columnModel.getValueColumns();
                var valueKeys = this.gridOptionsWrapper.getGroupAggFields();
                if ((valueColumns && valueColumns.length > 0) || (valueKeys && valueKeys.length > 0)) {
                    var defaultAggFunction = this.defaultGroupAggFunctionFactory(valueColumns, valueKeys);
                    this.recursivelyCreateAggData(this.rowsAfterFilter, defaultAggFunction);
                }
                else {
                    // if no agg data, need to clear out any previous items, when can be left behind
                    // if use is creating / removing columns using the tool panel.
                    // one exception - don't do this if already grouped, as this breaks the File Explorer example!!
                    // to fix another day - how to we reset when the user provided the data??
                    if (!this.gridOptionsWrapper.isRowsAlreadyGrouped()) {
                        this.recursivelyClearAggData(this.rowsAfterFilter);
                    }
                }
            };
            // public
            InMemoryRowController.prototype.expandOrCollapseAll = function (expand, rowNodes) {
                // if first call in recursion, we set list to parent list
                if (rowNodes === null) {
                    rowNodes = this.rowsAfterGroup;
                }
                if (!rowNodes) {
                    return;
                }
                var _this = this;
                rowNodes.forEach(function (node) {
                    if (node.group) {
                        node.expanded = expand;
                        _this.expandOrCollapseAll(expand, node.children);
                    }
                });
            };
            // private
            InMemoryRowController.prototype.recursivelyClearAggData = function (nodes) {
                for (var i = 0, l = nodes.length; i < l; i++) {
                    var node = nodes[i];
                    if (node.group) {
                        // agg function needs to start at the bottom, so traverse first
                        this.recursivelyClearAggData(node.childrenAfterFilter);
                        node.data = null;
                    }
                }
            };
            // private
            InMemoryRowController.prototype.recursivelyCreateAggData = function (nodes, groupAggFunction) {
                for (var i = 0, l = nodes.length; i < l; i++) {
                    var node = nodes[i];
                    if (node.group) {
                        // agg function needs to start at the bottom, so traverse first
                        this.recursivelyCreateAggData(node.childrenAfterFilter, groupAggFunction);
                        // after traversal, we can now do the agg at this level
                        var data = groupAggFunction(node.childrenAfterFilter);
                        node.data = data;
                        // if we are grouping, then it's possible there is a sibling footer
                        // to the group, so update the data here also if there is one
                        if (node.sibling) {
                            node.sibling.data = data;
                        }
                    }
                }
            };
            // private
            InMemoryRowController.prototype.doSort = function () {
                var sorting;
                // if the sorting is already done by the server, then we should not do it here
                if (this.gridOptionsWrapper.isEnableServerSideSorting()) {
                    sorting = false;
                }
                else {
                    //see if there is a col we are sorting by
                    var sortingOptions = [];
                    this.columnModel.getAllColumns().forEach(function (column) {
                        if (column.sort) {
                            var ascending = column.sort === constants.ASC;
                            sortingOptions.push({
                                inverter: ascending ? 1 : -1,
                                sortedAt: column.sortedAt,
                                colDef: column.colDef
                            });
                        }
                    });
                    if (sortingOptions.length > 0) {
                        sorting = true;
                    }
                }
                var rowNodesReadyForSorting = this.rowsAfterFilter ? this.rowsAfterFilter.slice(0) : null;
                if (sorting) {
                    // The columns are to be sorted in the order that the user selected them:
                    sortingOptions.sort(function (optionA, optionB) {
                        return optionA.sortedAt - optionB.sortedAt;
                    });
                    this.sortList(rowNodesReadyForSorting, sortingOptions);
                }
                else {
                    // if no sorting, set all group children after sort to the original list.
                    // note: it is important to do this, even if doing server side sorting,
                    // to allow the rows to pass to the next stage (ie set the node value
                    // childrenAfterSort)
                    this.recursivelyResetSort(rowNodesReadyForSorting);
                }
                this.rowsAfterSort = rowNodesReadyForSorting;
            };
            // private
            InMemoryRowController.prototype.recursivelyResetSort = function (rowNodes) {
                if (!rowNodes) {
                    return;
                }
                for (var i = 0, l = rowNodes.length; i < l; i++) {
                    var item = rowNodes[i];
                    if (item.group && item.children) {
                        item.childrenAfterSort = item.childrenAfterFilter;
                        this.recursivelyResetSort(item.children);
                    }
                }
            };
            // private
            InMemoryRowController.prototype.sortList = function (nodes, sortOptions) {
                for (var i = 0, l = nodes.length; i < l; i++) {
                    var node = nodes[i];
                    if (node.group && node.children) {
                        node.childrenAfterSort = node.childrenAfterFilter.slice(0);
                        this.sortList(node.childrenAfterSort, sortOptions);
                    }
                }
                var that = this;
                function compare(objA, objB, colDef) {
                    var valueA = that.getValue(objA.data, colDef, objA);
                    var valueB = that.getValue(objB.data, colDef, objB);
                    if (colDef.comparator) {
                        //if comparator provided, use it
                        return colDef.comparator(valueA, valueB, objA, objB);
                    }
                    else {
                        //otherwise do our own comparison
                        return utils.defaultComparator(valueA, valueB);
                    }
                }
                nodes.sort(function (objA, objB) {
                    for (var i = 0, len = sortOptions.length; i < len; i++) {
                        var sortOption = sortOptions[i];
                        var compared = compare(objA, objB, sortOption.colDef);
                        if (compared !== 0) {
                            return compared * sortOption.inverter;
                        }
                    }
                    // All matched, these are identical as far as the sort is concerned:
                    return 0;
                });
            };
            // private
            InMemoryRowController.prototype.doGrouping = function () {
                var rowsAfterGroup;
                var groupedCols = this.columnModel.getGroupedColumns();
                var rowsAlreadyGrouped = this.gridOptionsWrapper.isRowsAlreadyGrouped();
                var doingGrouping = !rowsAlreadyGrouped && groupedCols.length > 0;
                if (doingGrouping) {
                    var expandByDefault = this.gridOptionsWrapper.getGroupDefaultExpanded();
                    rowsAfterGroup = groupCreator.group(this.allRows, groupedCols, expandByDefault);
                }
                else {
                    rowsAfterGroup = this.allRows;
                }
                this.rowsAfterGroup = rowsAfterGroup;
            };
            // private
            InMemoryRowController.prototype.doFilter = function () {
                var doingFilter;
                if (this.gridOptionsWrapper.isEnableServerSideFilter()) {
                    doingFilter = false;
                }
                else {
                    var quickFilterPresent = this.angularGrid.getQuickFilter() !== null;
                    var advancedFilterPresent = this.filterManager.isFilterPresent();
                    doingFilter = quickFilterPresent || advancedFilterPresent;
                }
                var rowsAfterFilter;
                if (doingFilter) {
                    rowsAfterFilter = this.filterItems(this.rowsAfterGroup, quickFilterPresent, advancedFilterPresent);
                }
                else {
                    // do it here
                    rowsAfterFilter = this.rowsAfterGroup;
                    this.recursivelyResetFilter(this.rowsAfterGroup);
                }
                this.rowsAfterFilter = rowsAfterFilter;
            };
            // private
            InMemoryRowController.prototype.filterItems = function (rowNodes, quickFilterPresent, advancedFilterPresent) {
                var result = [];
                for (var i = 0, l = rowNodes.length; i < l; i++) {
                    var node = rowNodes[i];
                    if (node.group) {
                        // deal with group
                        node.childrenAfterFilter = this.filterItems(node.children, quickFilterPresent, advancedFilterPresent);
                        if (node.childrenAfterFilter.length > 0) {
                            node.allChildrenCount = this.getTotalChildCount(node.childrenAfterFilter);
                            result.push(node);
                        }
                    }
                    else {
                        if (this.doesRowPassFilter(node, quickFilterPresent, advancedFilterPresent)) {
                            result.push(node);
                        }
                    }
                }
                return result;
            };
            // private
            InMemoryRowController.prototype.recursivelyResetFilter = function (nodes) {
                if (!nodes) {
                    return;
                }
                for (var i = 0, l = nodes.length; i < l; i++) {
                    var node = nodes[i];
                    if (node.group && node.children) {
                        node.childrenAfterFilter = node.children;
                        this.recursivelyResetFilter(node.children);
                        node.allChildrenCount = this.getTotalChildCount(node.childrenAfterFilter);
                    }
                }
            };
            // private
            // rows: the rows to put into the model
            // firstId: the first id to use, used for paging, where we are not on the first page
            InMemoryRowController.prototype.setAllRows = function (rows, firstId) {
                var nodes;
                if (this.gridOptionsWrapper.isRowsAlreadyGrouped()) {
                    nodes = rows;
                    this.recursivelyCheckUserProvidedNodes(nodes, null, 0);
                }
                else {
                    // place each row into a wrapper
                    var nodes = [];
                    if (rows) {
                        for (var i = 0; i < rows.length; i++) {
                            nodes.push({
                                data: rows[i]
                            });
                        }
                    }
                }
                // if firstId provided, use it, otherwise start at 0
                var firstIdToUse = firstId ? firstId : 0;
                this.recursivelyAddIdToNodes(nodes, firstIdToUse);
                this.allRows = nodes;
                // aggregate here, so filters have the agg data ready
                this.doGrouping();
            };
            // add in index - this is used by the selectionController - so quick
            // to look up selected rows
            InMemoryRowController.prototype.recursivelyAddIdToNodes = function (nodes, index) {
                if (!nodes) {
                    return;
                }
                for (var i = 0; i < nodes.length; i++) {
                    var node = nodes[i];
                    node.id = index++;
                    if (node.group && node.children) {
                        index = this.recursivelyAddIdToNodes(node.children, index);
                    }
                }
                return index;
            };
            // add in index - this is used by the selectionController - so quick
            // to look up selected rows
            InMemoryRowController.prototype.recursivelyCheckUserProvidedNodes = function (nodes, parent, level) {
                if (!nodes) {
                    return;
                }
                for (var i = 0; i < nodes.length; i++) {
                    var node = nodes[i];
                    if (parent) {
                        node.parent = parent;
                    }
                    node.level = level;
                    if (node.group && node.children) {
                        this.recursivelyCheckUserProvidedNodes(node.children, node, level + 1);
                    }
                }
            };
            // private
            InMemoryRowController.prototype.getTotalChildCount = function (rowNodes) {
                var count = 0;
                for (var i = 0, l = rowNodes.length; i < l; i++) {
                    var item = rowNodes[i];
                    if (item.group) {
                        count += item.allChildrenCount;
                    }
                    else {
                        count++;
                    }
                }
                return count;
            };
            // private
            InMemoryRowController.prototype.doGroupMapping = function () {
                // even if not doing grouping, we do the mapping, as the client might
                // of passed in data that already has a grouping in it somewhere
                var rowsAfterMap = [];
                this.addToMap(rowsAfterMap, this.rowsAfterSort);
                this.rowsAfterMap = rowsAfterMap;
            };
            // private
            InMemoryRowController.prototype.addToMap = function (mappedData, originalNodes) {
                if (!originalNodes) {
                    return;
                }
                for (var i = 0; i < originalNodes.length; i++) {
                    var node = originalNodes[i];
                    mappedData.push(node);
                    if (node.group && node.expanded) {
                        this.addToMap(mappedData, node.childrenAfterSort);
                        // put a footer in if user is looking for it
                        if (this.gridOptionsWrapper.isGroupIncludeFooter()) {
                            var footerNode = this.createFooterNode(node);
                            mappedData.push(footerNode);
                        }
                    }
                }
            };
            // private
            InMemoryRowController.prototype.createFooterNode = function (groupNode) {
                var footerNode = {};
                Object.keys(groupNode).forEach(function (key) {
                    footerNode[key] = groupNode[key];
                });
                footerNode.footer = true;
                // get both header and footer to reference each other as siblings. this is never undone,
                // only overwritten. so if a group is expanded, then contracted, it will have a ghost
                // sibling - but that's fine, as we can ignore this if the header is contracted.
                footerNode.sibling = groupNode;
                groupNode.sibling = footerNode;
                return footerNode;
            };
            // private
            InMemoryRowController.prototype.doesRowPassFilter = function (node, quickFilterPresent, advancedFilterPresent) {
                //first up, check quick filter
                if (quickFilterPresent) {
                    if (!node.quickFilterAggregateText) {
                        this.aggregateRowForQuickFilter(node);
                    }
                    if (node.quickFilterAggregateText.indexOf(this.angularGrid.getQuickFilter()) < 0) {
                        //quick filter fails, so skip item
                        return false;
                    }
                }
                //second, check advanced filter
                if (advancedFilterPresent) {
                    if (!this.filterManager.doesFilterPass(node)) {
                        return false;
                    }
                }
                //got this far, all filters pass
                return true;
            };
            // private
            InMemoryRowController.prototype.aggregateRowForQuickFilter = function (node) {
                var aggregatedText = '';
                this.columnModel.getAllColumns().forEach(function (colDefWrapper) {
                    var data = node.data;
                    var value = data ? data[colDefWrapper.colDef.field] : null;
                    if (value && value !== '') {
                        aggregatedText = aggregatedText + value.toString().toUpperCase() + "_";
                    }
                });
                node.quickFilterAggregateText = aggregatedText;
            };
            return InMemoryRowController;
        })();
        grid.InMemoryRowController = InMemoryRowController;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
/*
 * This row controller is used for infinite scrolling only. For normal 'in memory' table,
 * or standard pagination, the inMemoryRowController is used.
 */
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var logging = false;
        var VirtualPageRowController = (function () {
            function VirtualPageRowController() {
            }
            VirtualPageRowController.prototype.init = function (rowRenderer, gridOptionsWrapper, angularGrid) {
                this.rowRenderer = rowRenderer;
                this.datasourceVersion = 0;
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.angularGrid = angularGrid;
            };
            VirtualPageRowController.prototype.setDatasource = function (datasource) {
                this.datasource = datasource;
                if (!datasource) {
                    // only continue if we have a valid datasource to working with
                    return;
                }
                this.reset();
            };
            VirtualPageRowController.prototype.reset = function () {
                // see if datasource knows how many rows there are
                if (typeof this.datasource.rowCount === 'number' && this.datasource.rowCount >= 0) {
                    this.virtualRowCount = this.datasource.rowCount;
                    this.foundMaxRow = true;
                }
                else {
                    this.virtualRowCount = 0;
                    this.foundMaxRow = false;
                }
                // in case any daemon requests coming from datasource, we know it ignore them
                this.datasourceVersion++;
                // map of page numbers to rows in that page
                this.pageCache = {};
                this.pageCacheSize = 0;
                // if a number is in this array, it means we are pending a load from it
                this.pageLoadsInProgress = [];
                this.pageLoadsQueued = [];
                this.pageAccessTimes = {}; // keeps a record of when each page was last viewed, used for LRU cache
                this.accessTime = 0; // rather than using the clock, we use this counter
                // the number of concurrent loads we are allowed to the server
                if (typeof this.datasource.maxConcurrentRequests === 'number' && this.datasource.maxConcurrentRequests > 0) {
                    this.maxConcurrentDatasourceRequests = this.datasource.maxConcurrentRequests;
                }
                else {
                    this.maxConcurrentDatasourceRequests = 2;
                }
                // the number of pages to keep in browser cache
                if (typeof this.datasource.maxPagesInCache === 'number' && this.datasource.maxPagesInCache > 0) {
                    this.maxPagesInCache = this.datasource.maxPagesInCache;
                }
                else {
                    // null is default, means don't  have any max size on the cache
                    this.maxPagesInCache = null;
                }
                this.pageSize = this.datasource.pageSize; // take a copy of page size, we don't want it changing
                this.overflowSize = this.datasource.overflowSize; // take a copy of page size, we don't want it changing
                this.doLoadOrQueue(0);
            };
            VirtualPageRowController.prototype.createNodesFromRows = function (pageNumber, rows) {
                var nodes = [];
                if (rows) {
                    for (var i = 0, j = rows.length; i < j; i++) {
                        var virtualRowIndex = (pageNumber * this.pageSize) + i;
                        nodes.push({
                            data: rows[i],
                            id: virtualRowIndex
                        });
                    }
                }
                return nodes;
            };
            VirtualPageRowController.prototype.removeFromLoading = function (pageNumber) {
                var index = this.pageLoadsInProgress.indexOf(pageNumber);
                this.pageLoadsInProgress.splice(index, 1);
            };
            VirtualPageRowController.prototype.pageLoadFailed = function (pageNumber) {
                this.removeFromLoading(pageNumber);
                this.checkQueueForNextLoad();
            };
            VirtualPageRowController.prototype.pageLoaded = function (pageNumber, rows, lastRow) {
                this.putPageIntoCacheAndPurge(pageNumber, rows);
                this.checkMaxRowAndInformRowRenderer(pageNumber, lastRow);
                this.removeFromLoading(pageNumber);
                this.checkQueueForNextLoad();
            };
            VirtualPageRowController.prototype.putPageIntoCacheAndPurge = function (pageNumber, rows) {
                this.pageCache[pageNumber] = this.createNodesFromRows(pageNumber, rows);
                this.pageCacheSize++;
                if (logging) {
                    console.log('adding page ' + pageNumber);
                }
                var needToPurge = this.maxPagesInCache && this.maxPagesInCache < this.pageCacheSize;
                if (needToPurge) {
                    // find the LRU page
                    var youngestPageIndex = this.findLeastRecentlyAccessedPage(Object.keys(this.pageCache));
                    if (logging) {
                        console.log('purging page ' + youngestPageIndex + ' from cache ' + Object.keys(this.pageCache));
                    }
                    delete this.pageCache[youngestPageIndex];
                    this.pageCacheSize--;
                }
            };
            VirtualPageRowController.prototype.checkMaxRowAndInformRowRenderer = function (pageNumber, lastRow) {
                if (!this.foundMaxRow) {
                    // if we know the last row, use if
                    if (typeof lastRow === 'number' && lastRow >= 0) {
                        this.virtualRowCount = lastRow;
                        this.foundMaxRow = true;
                    }
                    else {
                        // otherwise, see if we need to add some virtual rows
                        var thisPagePlusBuffer = ((pageNumber + 1) * this.pageSize) + this.overflowSize;
                        if (this.virtualRowCount < thisPagePlusBuffer) {
                            this.virtualRowCount = thisPagePlusBuffer;
                        }
                    }
                    // if rowCount changes, refreshView, otherwise just refreshAllVirtualRows
                    this.rowRenderer.refreshView();
                }
                else {
                    this.rowRenderer.refreshAllVirtualRows();
                }
            };
            VirtualPageRowController.prototype.isPageAlreadyLoading = function (pageNumber) {
                var result = this.pageLoadsInProgress.indexOf(pageNumber) >= 0 || this.pageLoadsQueued.indexOf(pageNumber) >= 0;
                return result;
            };
            VirtualPageRowController.prototype.doLoadOrQueue = function (pageNumber) {
                // if we already tried to load this page, then ignore the request,
                // otherwise server would be hit 50 times just to display one page, the
                // first row to find the page missing is enough.
                if (this.isPageAlreadyLoading(pageNumber)) {
                    return;
                }
                // try the page load - if not already doing a load, then we can go ahead
                if (this.pageLoadsInProgress.length < this.maxConcurrentDatasourceRequests) {
                    // go ahead, load the page
                    this.loadPage(pageNumber);
                }
                else {
                    // otherwise, queue the request
                    this.addToQueueAndPurgeQueue(pageNumber);
                }
            };
            VirtualPageRowController.prototype.addToQueueAndPurgeQueue = function (pageNumber) {
                if (logging) {
                    console.log('queueing ' + pageNumber + ' - ' + this.pageLoadsQueued);
                }
                this.pageLoadsQueued.push(pageNumber);
                // see if there are more pages queued that are actually in our cache, if so there is
                // no point in loading them all as some will be purged as soon as loaded
                var needToPurge = this.maxPagesInCache && this.maxPagesInCache < this.pageLoadsQueued.length;
                if (needToPurge) {
                    // find the LRU page
                    var youngestPageIndex = this.findLeastRecentlyAccessedPage(this.pageLoadsQueued);
                    if (logging) {
                        console.log('de-queueing ' + pageNumber + ' - ' + this.pageLoadsQueued);
                    }
                    var indexToRemove = this.pageLoadsQueued.indexOf(youngestPageIndex);
                    this.pageLoadsQueued.splice(indexToRemove, 1);
                }
            };
            VirtualPageRowController.prototype.findLeastRecentlyAccessedPage = function (pageIndexes) {
                var youngestPageIndex = -1;
                var youngestPageAccessTime = Number.MAX_VALUE;
                var that = this;
                pageIndexes.forEach(function (pageIndex) {
                    var accessTimeThisPage = that.pageAccessTimes[pageIndex];
                    if (accessTimeThisPage < youngestPageAccessTime) {
                        youngestPageAccessTime = accessTimeThisPage;
                        youngestPageIndex = pageIndex;
                    }
                });
                return youngestPageIndex;
            };
            VirtualPageRowController.prototype.checkQueueForNextLoad = function () {
                if (this.pageLoadsQueued.length > 0) {
                    // take from the front of the queue
                    var pageToLoad = this.pageLoadsQueued[0];
                    this.pageLoadsQueued.splice(0, 1);
                    if (logging) {
                        console.log('dequeueing ' + pageToLoad + ' - ' + this.pageLoadsQueued);
                    }
                    this.loadPage(pageToLoad);
                }
            };
            VirtualPageRowController.prototype.loadPage = function (pageNumber) {
                this.pageLoadsInProgress.push(pageNumber);
                var startRow = pageNumber * this.pageSize;
                var endRow = (pageNumber + 1) * this.pageSize;
                var that = this;
                var datasourceVersionCopy = this.datasourceVersion;
                var sortModel;
                if (this.gridOptionsWrapper.isEnableServerSideSorting()) {
                    sortModel = this.angularGrid.getSortModel();
                }
                var filterModel;
                if (this.gridOptionsWrapper.isEnableServerSideFilter()) {
                    filterModel = this.angularGrid.getFilterModel();
                }
                var params = {
                    startRow: startRow,
                    endRow: endRow,
                    successCallback: successCallback,
                    failCallback: failCallback,
                    sortModel: sortModel,
                    filterModel: filterModel
                };
                // check if old version of datasource used
                var getRowsParams = utils.getFunctionParameters(this.datasource.getRows);
                if (getRowsParams.length > 1) {
                    console.warn('ag-grid: It looks like your paging datasource is of the old type, taking more than one parameter.');
                    console.warn('ag-grid: From ag-grid 1.9.0, now the getRows takes one parameter. See the documentation for details.');
                }
                this.datasource.getRows(params);
                function successCallback(rows, lastRowIndex) {
                    if (that.requestIsDaemon(datasourceVersionCopy)) {
                        return;
                    }
                    that.pageLoaded(pageNumber, rows, lastRowIndex);
                }
                function failCallback() {
                    if (that.requestIsDaemon(datasourceVersionCopy)) {
                        return;
                    }
                    that.pageLoadFailed(pageNumber);
                }
            };
            // check that the datasource has not changed since the lats time we did a request
            VirtualPageRowController.prototype.requestIsDaemon = function (datasourceVersionCopy) {
                return this.datasourceVersion !== datasourceVersionCopy;
            };
            VirtualPageRowController.prototype.getVirtualRow = function (rowIndex) {
                if (rowIndex > this.virtualRowCount) {
                    return null;
                }
                var pageNumber = Math.floor(rowIndex / this.pageSize);
                var page = this.pageCache[pageNumber];
                // for LRU cache, track when this page was last hit
                this.pageAccessTimes[pageNumber] = this.accessTime++;
                if (!page) {
                    this.doLoadOrQueue(pageNumber);
                    // return back an empty row, so table can at least render empty cells
                    return {
                        data: {},
                        id: rowIndex
                    };
                }
                else {
                    var indexInThisPage = rowIndex % this.pageSize;
                    return page[indexInThisPage];
                }
            };
            VirtualPageRowController.prototype.forEachInMemory = function (callback) {
                var pageKeys = Object.keys(this.pageCache);
                for (var i = 0; i < pageKeys.length; i++) {
                    var pageKey = pageKeys[i];
                    var page = this.pageCache[pageKey];
                    for (var j = 0; j < page.length; j++) {
                        var node = page[j];
                        callback(node);
                    }
                }
            };
            VirtualPageRowController.prototype.getModel = function () {
                var that = this;
                return {
                    getVirtualRow: function (index) {
                        return that.getVirtualRow(index);
                    },
                    getVirtualRowCount: function () {
                        return that.virtualRowCount;
                    },
                    forEachInMemory: function (callback) {
                        that.forEachInMemory(callback);
                    }
                };
            };
            return VirtualPageRowController;
        })();
        grid.VirtualPageRowController = VirtualPageRowController;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var template = '<div class="ag-paging-panel">' + '<span id="pageRowSummaryPanel" class="ag-paging-row-summary-panel">' + '<span id="firstRowOnPage"></span>' + ' [TO] ' + '<span id="lastRowOnPage"></span>' + ' [OF] ' + '<span id="recordCount"></span>' + '</span>' + '<span class="ag-paging-page-summary-panel">' + '<button class="ag-paging-button" id="btFirst">[FIRST]</button>' + '<button class="ag-paging-button" id="btPrevious">[PREVIOUS]</button>' + '[PAGE] ' + '<span id="current"></span>' + ' [OF] ' + '<span id="total"></span>' + '<button class="ag-paging-button" id="btNext">[NEXT]</button>' + '<button class="ag-paging-button" id="btLast">[LAST]</button>' + '</span>' + '</div>';
        var PaginationController = (function () {
            function PaginationController() {
            }
            PaginationController.prototype.init = function (angularGrid, gridOptionsWrapper) {
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.angularGrid = angularGrid;
                this.setupComponents();
                this.callVersion = 0;
            };
            PaginationController.prototype.setDatasource = function (datasource) {
                this.datasource = datasource;
                if (!datasource) {
                    // only continue if we have a valid datasource to work with
                    return;
                }
                this.reset();
            };
            PaginationController.prototype.reset = function () {
                // copy pageSize, to guard against it changing the the datasource between calls
                if (this.datasource.pageSize && typeof this.datasource.pageSize !== 'number') {
                    console.warn('datasource.pageSize should be a number');
                }
                this.pageSize = this.datasource.pageSize;
                // see if we know the total number of pages, or if it's 'to be decided'
                if (typeof this.datasource.rowCount === 'number' && this.datasource.rowCount >= 0) {
                    this.rowCount = this.datasource.rowCount;
                    this.foundMaxRow = true;
                    this.calculateTotalPages();
                }
                else {
                    this.rowCount = 0;
                    this.foundMaxRow = false;
                    this.totalPages = null;
                }
                this.currentPage = 0;
                // hide the summary panel until something is loaded
                this.ePageRowSummaryPanel.style.visibility = 'hidden';
                this.setTotalLabels();
                this.loadPage();
            };
            PaginationController.prototype.setTotalLabels = function () {
                if (this.foundMaxRow) {
                    this.lbTotal.innerHTML = this.totalPages.toLocaleString();
                    this.lbRecordCount.innerHTML = this.rowCount.toLocaleString();
                }
                else {
                    var moreText = this.gridOptionsWrapper.getLocaleTextFunc()('more', 'more');
                    this.lbTotal.innerHTML = moreText;
                    this.lbRecordCount.innerHTML = moreText;
                }
            };
            PaginationController.prototype.calculateTotalPages = function () {
                this.totalPages = Math.floor((this.rowCount - 1) / this.pageSize) + 1;
            };
            PaginationController.prototype.pageLoaded = function (rows, lastRowIndex) {
                var firstId = this.currentPage * this.pageSize;
                this.angularGrid.setRows(rows, firstId);
                // see if we hit the last row
                if (!this.foundMaxRow && typeof lastRowIndex === 'number' && lastRowIndex >= 0) {
                    this.foundMaxRow = true;
                    this.rowCount = lastRowIndex;
                    this.calculateTotalPages();
                    this.setTotalLabels();
                    // if overshot pages, go back
                    if (this.currentPage > this.totalPages) {
                        this.currentPage = this.totalPages - 1;
                        this.loadPage();
                    }
                }
                this.enableOrDisableButtons();
                this.updateRowLabels();
            };
            PaginationController.prototype.updateRowLabels = function () {
                var startRow;
                var endRow;
                if (this.isZeroPagesToDisplay()) {
                    startRow = 0;
                    endRow = 0;
                }
                else {
                    startRow = (this.pageSize * this.currentPage) + 1;
                    endRow = startRow + this.pageSize - 1;
                    if (this.foundMaxRow && endRow > this.rowCount) {
                        endRow = this.rowCount;
                    }
                }
                this.lbFirstRowOnPage.innerHTML = (startRow).toLocaleString();
                this.lbLastRowOnPage.innerHTML = (endRow).toLocaleString();
                // show the summary panel, when first shown, this is blank
                this.ePageRowSummaryPanel.style.visibility = null;
            };
            PaginationController.prototype.loadPage = function () {
                this.enableOrDisableButtons();
                var startRow = this.currentPage * this.datasource.pageSize;
                var endRow = (this.currentPage + 1) * this.datasource.pageSize;
                this.lbCurrent.innerHTML = (this.currentPage + 1).toLocaleString();
                this.callVersion++;
                var callVersionCopy = this.callVersion;
                var that = this;
                this.angularGrid.showLoadingPanel(true);
                var sortModel;
                if (this.gridOptionsWrapper.isEnableServerSideSorting()) {
                    sortModel = this.angularGrid.getSortModel();
                }
                var filterModel;
                if (this.gridOptionsWrapper.isEnableServerSideFilter()) {
                    filterModel = this.angularGrid.getFilterModel();
                }
                var params = {
                    startRow: startRow,
                    endRow: endRow,
                    successCallback: successCallback,
                    failCallback: failCallback,
                    sortModel: sortModel,
                    filterModel: filterModel
                };
                // check if old version of datasource used
                var getRowsParams = utils.getFunctionParameters(this.datasource.getRows);
                if (getRowsParams.length > 1) {
                    console.warn('ag-grid: It looks like your paging datasource is of the old type, taking more than one parameter.');
                    console.warn('ag-grid: From ag-grid 1.9.0, now the getRows takes one parameter. See the documentation for details.');
                }
                this.datasource.getRows(params);
                function successCallback(rows, lastRowIndex) {
                    if (that.isCallDaemon(callVersionCopy)) {
                        return;
                    }
                    that.pageLoaded(rows, lastRowIndex);
                }
                function failCallback() {
                    if (that.isCallDaemon(callVersionCopy)) {
                        return;
                    }
                    // set in an empty set of rows, this will at
                    // least get rid of the loading panel, and
                    // stop blocking things
                    that.angularGrid.setRows([]);
                }
            };
            PaginationController.prototype.isCallDaemon = function (versionCopy) {
                return versionCopy !== this.callVersion;
            };
            PaginationController.prototype.onBtNext = function () {
                this.currentPage++;
                this.loadPage();
            };
            PaginationController.prototype.onBtPrevious = function () {
                this.currentPage--;
                this.loadPage();
            };
            PaginationController.prototype.onBtFirst = function () {
                this.currentPage = 0;
                this.loadPage();
            };
            PaginationController.prototype.onBtLast = function () {
                this.currentPage = this.totalPages - 1;
                this.loadPage();
            };
            PaginationController.prototype.isZeroPagesToDisplay = function () {
                return this.foundMaxRow && this.totalPages === 0;
            };
            PaginationController.prototype.enableOrDisableButtons = function () {
                var disablePreviousAndFirst = this.currentPage === 0;
                this.btPrevious.disabled = disablePreviousAndFirst;
                this.btFirst.disabled = disablePreviousAndFirst;
                var zeroPagesToDisplay = this.isZeroPagesToDisplay();
                var onLastPage = this.foundMaxRow && this.currentPage === (this.totalPages - 1);
                var disableNext = onLastPage || zeroPagesToDisplay;
                this.btNext.disabled = disableNext;
                var disableLast = !this.foundMaxRow || zeroPagesToDisplay || this.currentPage === (this.totalPages - 1);
                this.btLast.disabled = disableLast;
            };
            PaginationController.prototype.createTemplate = function () {
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                return template.replace('[PAGE]', localeTextFunc('page', 'Page')).replace('[TO]', localeTextFunc('to', 'to')).replace('[OF]', localeTextFunc('of', 'of')).replace('[OF]', localeTextFunc('of', 'of')).replace('[FIRST]', localeTextFunc('first', 'First')).replace('[PREVIOUS]', localeTextFunc('previous', 'Previous')).replace('[NEXT]', localeTextFunc('next', 'Next')).replace('[LAST]', localeTextFunc('last', 'Last'));
            };
            PaginationController.prototype.getGui = function () {
                return this.eGui;
            };
            PaginationController.prototype.setupComponents = function () {
                this.eGui = utils.loadTemplate(this.createTemplate());
                this.btNext = this.eGui.querySelector('#btNext');
                this.btPrevious = this.eGui.querySelector('#btPrevious');
                this.btFirst = this.eGui.querySelector('#btFirst');
                this.btLast = this.eGui.querySelector('#btLast');
                this.lbCurrent = this.eGui.querySelector('#current');
                this.lbTotal = this.eGui.querySelector('#total');
                this.lbRecordCount = this.eGui.querySelector('#recordCount');
                this.lbFirstRowOnPage = this.eGui.querySelector('#firstRowOnPage');
                this.lbLastRowOnPage = this.eGui.querySelector('#lastRowOnPage');
                this.ePageRowSummaryPanel = this.eGui.querySelector('#pageRowSummaryPanel');
                var that = this;
                this.btNext.addEventListener('click', function () {
                    that.onBtNext();
                });
                this.btPrevious.addEventListener('click', function () {
                    that.onBtPrevious();
                });
                this.btFirst.addEventListener('click', function () {
                    that.onBtFirst();
                });
                this.btLast.addEventListener('click', function () {
                    that.onBtLast();
                });
            };
            return PaginationController;
        })();
        grid.PaginationController = PaginationController;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var TemplateService = (function () {
            function TemplateService() {
                this.templateCache = {};
                this.waitingCallbacks = {};
            }
            TemplateService.prototype.init = function ($scope) {
                this.$scope = $scope;
            };
            // returns the template if it is loaded, or null if it is not loaded
            // but will call the callback when it is loaded
            TemplateService.prototype.getTemplate = function (url, callback) {
                var templateFromCache = this.templateCache[url];
                if (templateFromCache) {
                    return templateFromCache;
                }
                var callbackList = this.waitingCallbacks[url];
                var that = this;
                if (!callbackList) {
                    // first time this was called, so need a new list for callbacks
                    callbackList = [];
                    this.waitingCallbacks[url] = callbackList;
                    // and also need to do the http request
                    var client = new XMLHttpRequest();
                    client.onload = function () {
                        that.handleHttpResult(this, url);
                    };
                    client.open("GET", url);
                    client.send();
                }
                // add this callback
                if (callback) {
                    callbackList.push(callback);
                }
                // caller needs to wait for template to load, so return null
                return null;
            };
            TemplateService.prototype.handleHttpResult = function (httpResult, url) {
                if (httpResult.status !== 200 || httpResult.response === null) {
                    console.warn('Unable to get template error ' + httpResult.status + ' - ' + url);
                    return;
                }
                // response success, so process it
                this.templateCache[url] = httpResult.response;
                // inform all listeners that this is now in the cache
                var callbacks = this.waitingCallbacks[url];
                for (var i = 0; i < callbacks.length; i++) {
                    var callback = callbacks[i];
                    // we could pass the callback the response, however we know the client of this code
                    // is the cell renderer, and it passes the 'cellRefresh' method in as the callback
                    // which doesn't take any parameters.
                    callback();
                }
                if (this.$scope) {
                    var that = this;
                    setTimeout(function () {
                        that.$scope.$apply();
                    }, 0);
                }
            };
            return TemplateService;
        })();
        grid.TemplateService = TemplateService;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var _ = grid.Utils;
        var BorderLayout = (function () {
            function BorderLayout(params) {
                this.isLayoutPanel = true;
                this.fullHeight = !params.north && !params.south;
                var template;
                if (!params.dontFill) {
                    if (this.fullHeight) {
                        template = '<div style="height: 100%; overflow: auto; position: relative;">' + '<div id="west" style="height: 100%; float: left;"></div>' + '<div id="east" style="height: 100%; float: right;"></div>' + '<div id="center" style="height: 100%;"></div>' + '<div id="overlay" style="position: absolute; height: 100%; width: 100%; top: 0px; left: 0px;"></div>' + '</div>';
                    }
                    else {
                        template = '<div style="height: 100%; position: relative;">' + '<div id="north"></div>' + '<div id="centerRow" style="height: 100%; overflow: hidden;">' + '<div id="west" style="height: 100%; float: left;"></div>' + '<div id="east" style="height: 100%; float: right;"></div>' + '<div id="center" style="height: 100%;"></div>' + '</div>' + '<div id="south"></div>' + '<div id="overlay" style="position: absolute; height: 100%; width: 100%; top: 0px; left: 0px;"></div>' + '</div>';
                    }
                    this.layoutActive = true;
                }
                else {
                    template = '<div style="position: relative;">' + '<div id="north"></div>' + '<div id="centerRow">' + '<div id="west"></div>' + '<div id="east"></div>' + '<div id="center"></div>' + '</div>' + '<div id="south"></div>' + '<div id="overlay" style="position: absolute; height: 100%; width: 100%; top: 0px; left: 0px;"></div>' + '</div>';
                    this.layoutActive = false;
                }
                this.eGui = _.loadTemplate(template);
                this.id = 'borderLayout';
                if (params.name) {
                    this.id += '_' + params.name;
                }
                this.eGui.setAttribute('id', this.id);
                this.childPanels = [];
                if (params) {
                    this.setupPanels(params);
                }
                this.setOverlayVisible(false);
            }
            BorderLayout.prototype.setupPanels = function (params) {
                this.eNorthWrapper = this.eGui.querySelector('#north');
                this.eSouthWrapper = this.eGui.querySelector('#south');
                this.eEastWrapper = this.eGui.querySelector('#east');
                this.eWestWrapper = this.eGui.querySelector('#west');
                this.eCenterWrapper = this.eGui.querySelector('#center');
                this.eOverlayWrapper = this.eGui.querySelector('#overlay');
                this.eCenterRow = this.eGui.querySelector('#centerRow');
                this.eNorthChildLayout = this.setupPanel(params.north, this.eNorthWrapper);
                this.eSouthChildLayout = this.setupPanel(params.south, this.eSouthWrapper);
                this.eEastChildLayout = this.setupPanel(params.east, this.eEastWrapper);
                this.eWestChildLayout = this.setupPanel(params.west, this.eWestWrapper);
                this.eCenterChildLayout = this.setupPanel(params.center, this.eCenterWrapper);
                this.setupPanel(params.overlay, this.eOverlayWrapper);
            };
            BorderLayout.prototype.setupPanel = function (content, ePanel) {
                if (!ePanel) {
                    return;
                }
                if (content) {
                    if (content.isLayoutPanel) {
                        this.childPanels.push(content);
                        ePanel.appendChild(content.getGui());
                        return content;
                    }
                    else {
                        ePanel.appendChild(content);
                        return null;
                    }
                }
                else {
                    ePanel.parentNode.removeChild(ePanel);
                    return null;
                }
            };
            BorderLayout.prototype.getGui = function () {
                return this.eGui;
            };
            // returns true if any item changed size, otherwise returns false
            BorderLayout.prototype.doLayout = function () {
                if (!_.isVisible(this.eGui)) {
                    return false;
                }
                var atLeastOneChanged = false;
                var childLayouts = [this.eNorthChildLayout, this.eSouthChildLayout, this.eEastChildLayout, this.eWestChildLayout];
                var that = this;
                _.forEach(childLayouts, function (childLayout) {
                    var childChangedSize = that.layoutChild(childLayout);
                    if (childChangedSize) {
                        atLeastOneChanged = true;
                    }
                });
                if (this.layoutActive) {
                    var ourHeightChanged = this.layoutHeight();
                    var ourWidthChanged = this.layoutWidth();
                    if (ourHeightChanged || ourWidthChanged) {
                        atLeastOneChanged = true;
                    }
                }
                var centerChanged = this.layoutChild(this.eCenterChildLayout);
                if (centerChanged) {
                    atLeastOneChanged = true;
                }
                return atLeastOneChanged;
            };
            BorderLayout.prototype.layoutChild = function (childPanel) {
                if (childPanel) {
                    return childPanel.doLayout();
                }
                else {
                    return false;
                }
            };
            BorderLayout.prototype.layoutHeight = function () {
                if (this.fullHeight) {
                    return false;
                }
                var totalHeight = _.offsetHeight(this.eGui);
                var northHeight = _.offsetHeight(this.eNorthWrapper);
                var southHeight = _.offsetHeight(this.eSouthWrapper);
                var centerHeight = totalHeight - northHeight - southHeight;
                if (centerHeight < 0) {
                    centerHeight = 0;
                }
                if (this.centerHeightLastTime !== centerHeight) {
                    this.eCenterRow.style.height = centerHeight + 'px';
                    this.centerHeightLastTime = centerHeight;
                    return true; // return true because there was a change
                }
                else {
                    return false;
                }
            };
            BorderLayout.prototype.layoutWidth = function () {
                var totalWidth = _.offsetWidth(this.eGui);
                var eastWidth = _.offsetWidth(this.eEastWrapper);
                var westWidth = _.offsetWidth(this.eWestWrapper);
                var centerWidth = totalWidth - eastWidth - westWidth;
                if (centerWidth < 0) {
                    centerWidth = 0;
                }
                this.eCenterWrapper.style.width = centerWidth + 'px';
            };
            BorderLayout.prototype.setEastVisible = function (visible) {
                if (this.eEastWrapper) {
                    this.eEastWrapper.style.display = visible ? '' : 'none';
                }
                this.doLayout();
            };
            BorderLayout.prototype.setOverlayVisible = function (visible) {
                if (this.eOverlayWrapper) {
                    this.eOverlayWrapper.style.display = visible ? '' : 'none';
                }
                this.doLayout();
            };
            BorderLayout.prototype.setSouthVisible = function (visible) {
                if (this.eSouthWrapper) {
                    this.eSouthWrapper.style.display = visible ? '' : 'none';
                }
                this.doLayout();
            };
            return BorderLayout;
        })();
        grid.BorderLayout = BorderLayout;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
/// <reference path="../layout/borderLayout.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var gridHtml = '<div>' + '<!-- header -->' + '<div class="ag-header">' + '<div class="ag-pinned-header"></div><div class="ag-header-viewport"><div class="ag-header-container"></div></div>' + '</div>' + '<!-- body -->' + '<div class="ag-body">' + '<div class="ag-pinned-cols-viewport">' + '<div class="ag-pinned-cols-container"></div>' + '</div>' + '<div class="ag-body-viewport-wrapper">' + '<div class="ag-body-viewport">' + '<div class="ag-body-container"></div>' + '</div>' + '</div>' + '</div>' + '</div>';
        var gridNoScrollsHtml = '<div>' + '<!-- header -->' + '<div class="ag-header-container"></div>' + '<!-- body -->' + '<div class="ag-body-container"></div>' + '</div>';
        // wrapping in outer div, and wrapper, is needed to center the loading icon
        // The idea for centering came from here: http://www.vanseodesign.com/css/vertical-centering/
        var loadingHtml = '<div class="ag-loading-panel">' + '<div class="ag-loading-wrapper">' + '<span class="ag-loading-center">Loading...</span>' + '</div>' + '</div>';
        var utils = grid.Utils;
        var GridPanel = (function () {
            function GridPanel(gridOptionsWrapper) {
                this.gridOptionsWrapper = gridOptionsWrapper;
                // makes code below more readable if we pull 'forPrint' out
                this.forPrint = this.gridOptionsWrapper.isDontUseScrolls();
                this.setupComponents();
                this.scrollWidth = utils.getScrollbarWidth();
            }
            GridPanel.prototype.setupComponents = function () {
                if (this.forPrint) {
                    this.eRoot = utils.loadTemplate(gridNoScrollsHtml);
                    utils.addCssClass(this.eRoot, 'ag-root ag-no-scrolls');
                }
                else {
                    this.eRoot = utils.loadTemplate(gridHtml);
                    utils.addCssClass(this.eRoot, 'ag-root ag-scrolls');
                }
                this.findElements();
                this.layout = new grid.BorderLayout({
                    overlay: utils.loadTemplate(loadingHtml),
                    center: this.eRoot,
                    dontFill: this.forPrint,
                    name: 'eGridPanel'
                });
                this.addScrollListener();
            };
            GridPanel.prototype.ensureIndexVisible = function (index) {
                var lastRow = this.rowModel.getVirtualRowCount();
                if (typeof index !== 'number' || index < 0 || index >= lastRow) {
                    console.warn('invalid row index for ensureIndexVisible: ' + index);
                    return;
                }
                var rowHeight = this.gridOptionsWrapper.getRowHeight();
                var rowTopPixel = rowHeight * index;
                var rowBottomPixel = rowTopPixel + rowHeight;
                var viewportTopPixel = this.eBodyViewport.scrollTop;
                var viewportHeight = this.eBodyViewport.offsetHeight;
                var scrollShowing = this.eBodyViewport.clientWidth < this.eBodyViewport.scrollWidth;
                if (scrollShowing) {
                    viewportHeight -= this.scrollWidth;
                }
                var viewportBottomPixel = viewportTopPixel + viewportHeight;
                var viewportScrolledPastRow = viewportTopPixel > rowTopPixel;
                var viewportScrolledBeforeRow = viewportBottomPixel < rowBottomPixel;
                if (viewportScrolledPastRow) {
                    // if row is before, scroll up with row at top
                    this.eBodyViewport.scrollTop = rowTopPixel;
                }
                else if (viewportScrolledBeforeRow) {
                    // if row is below, scroll down with row at bottom
                    var newScrollPosition = rowBottomPixel - viewportHeight;
                    this.eBodyViewport.scrollTop = newScrollPosition;
                }
                // otherwise, row is already in view, so do nothing
            };
            GridPanel.prototype.ensureColIndexVisible = function (index) {
                if (typeof index !== 'number') {
                    console.warn('col index must be a number: ' + index);
                    return;
                }
                var columns = this.columnModel.getDisplayedColumns();
                if (typeof index !== 'number' || index < 0 || index >= columns.length) {
                    console.warn('invalid col index for ensureColIndexVisible: ' + index + ', should be between 0 and ' + (columns.length - 1));
                    return;
                }
                var column = columns[index];
                var pinnedColCount = this.gridOptionsWrapper.getPinnedColCount();
                if (index < pinnedColCount) {
                    console.warn('invalid col index for ensureColIndexVisible: ' + index + ', scrolling to a pinned col makes no sense');
                    return;
                }
                // sum up all col width to the let to get the start pixel
                var colLeftPixel = 0;
                for (var i = pinnedColCount; i < index; i++) {
                    colLeftPixel += columns[i].actualWidth;
                }
                var colRightPixel = colLeftPixel + column.actualWidth;
                var viewportLeftPixel = this.eBodyViewport.scrollLeft;
                var viewportWidth = this.eBodyViewport.offsetWidth;
                var scrollShowing = this.eBodyViewport.clientHeight < this.eBodyViewport.scrollHeight;
                if (scrollShowing) {
                    viewportWidth -= this.scrollWidth;
                }
                var viewportRightPixel = viewportLeftPixel + viewportWidth;
                var viewportScrolledPastCol = viewportLeftPixel > colLeftPixel;
                var viewportScrolledBeforeCol = viewportRightPixel < colRightPixel;
                if (viewportScrolledPastCol) {
                    // if viewport's left side is after col's left side, scroll right to pull col into viewport at left
                    this.eBodyViewport.scrollLeft = colLeftPixel;
                }
                else if (viewportScrolledBeforeCol) {
                    // if viewport's right side is before col's right side, scroll left to pull col into viewport at right
                    var newScrollPosition = colRightPixel - viewportWidth;
                    this.eBodyViewport.scrollLeft = newScrollPosition;
                }
                // otherwise, col is already in view, so do nothing
            };
            GridPanel.prototype.showLoading = function (loading) {
                this.layout.setOverlayVisible(loading);
            };
            GridPanel.prototype.getWidthForSizeColsToFit = function () {
                var availableWidth = this.eBody.clientWidth;
                var scrollShowing = this.eBodyViewport.clientHeight < this.eBodyViewport.scrollHeight;
                if (scrollShowing) {
                    availableWidth -= this.scrollWidth;
                }
                return availableWidth;
            };
            GridPanel.prototype.init = function (columnModel, rowRenderer) {
                this.columnModel = columnModel;
                this.rowRenderer = rowRenderer;
            };
            GridPanel.prototype.setRowModel = function (rowModel) {
                this.rowModel = rowModel;
            };
            GridPanel.prototype.getBodyContainer = function () {
                return this.eBodyContainer;
            };
            GridPanel.prototype.getBodyViewport = function () {
                return this.eBodyViewport;
            };
            GridPanel.prototype.getPinnedColsContainer = function () {
                return this.ePinnedColsContainer;
            };
            GridPanel.prototype.getHeaderContainer = function () {
                return this.eHeaderContainer;
            };
            GridPanel.prototype.getRoot = function () {
                return this.eRoot;
            };
            GridPanel.prototype.getPinnedHeader = function () {
                return this.ePinnedHeader;
            };
            GridPanel.prototype.getHeader = function () {
                return this.eHeader;
            };
            GridPanel.prototype.getRowsParent = function () {
                return this.eParentOfRows;
            };
            GridPanel.prototype.findElements = function () {
                if (this.forPrint) {
                    this.eHeaderContainer = this.eRoot.querySelector(".ag-header-container");
                    this.eBodyContainer = this.eRoot.querySelector(".ag-body-container");
                    // for no-scrolls, all rows live in the body container
                    this.eParentOfRows = this.eBodyContainer;
                }
                else {
                    this.eBody = this.eRoot.querySelector(".ag-body");
                    this.eBodyContainer = this.eRoot.querySelector(".ag-body-container");
                    this.eBodyViewport = this.eRoot.querySelector(".ag-body-viewport");
                    this.eBodyViewportWrapper = this.eRoot.querySelector(".ag-body-viewport-wrapper");
                    this.ePinnedColsContainer = this.eRoot.querySelector(".ag-pinned-cols-container");
                    this.ePinnedColsViewport = this.eRoot.querySelector(".ag-pinned-cols-viewport");
                    this.ePinnedHeader = this.eRoot.querySelector(".ag-pinned-header");
                    this.eHeader = this.eRoot.querySelector(".ag-header");
                    this.eHeaderContainer = this.eRoot.querySelector(".ag-header-container");
                    // for scrolls, all rows live in eBody (containing pinned and normal body)
                    this.eParentOfRows = this.eBody;
                }
            };
            GridPanel.prototype.setBodyContainerWidth = function () {
                var mainRowWidth = this.columnModel.getBodyContainerWidth() + "px";
                this.eBodyContainer.style.width = mainRowWidth;
            };
            GridPanel.prototype.setPinnedColContainerWidth = function () {
                var pinnedColWidth = this.columnModel.getPinnedContainerWidth() + "px";
                this.ePinnedColsContainer.style.width = pinnedColWidth;
                this.eBodyViewportWrapper.style.marginLeft = pinnedColWidth;
            };
            GridPanel.prototype.showPinnedColContainersIfNeeded = function () {
                // no need to do this if not using scrolls
                if (this.forPrint) {
                    return;
                }
                var showingPinnedCols = this.gridOptionsWrapper.getPinnedColCount() > 0;
                //some browsers had layout issues with the blank divs, so if blank,
                //we don't display them
                if (showingPinnedCols) {
                    this.ePinnedHeader.style.display = 'inline-block';
                    this.ePinnedColsViewport.style.display = 'inline';
                }
                else {
                    this.ePinnedHeader.style.display = 'none';
                    this.ePinnedColsViewport.style.display = 'none';
                }
            };
            GridPanel.prototype.setHeaderHeight = function () {
                var headerHeight = this.gridOptionsWrapper.getHeaderHeight();
                var headerHeightPixels = headerHeight + 'px';
                if (this.forPrint) {
                    this.eHeaderContainer.style['height'] = headerHeightPixels;
                }
                else {
                    this.eHeader.style['height'] = headerHeightPixels;
                    this.eBody.style['paddingTop'] = headerHeightPixels;
                }
            };
            // see if a grey box is needed at the bottom of the pinned col
            GridPanel.prototype.setPinnedColHeight = function () {
                if (!this.forPrint) {
                    var bodyHeight = this.eBodyViewport.offsetHeight;
                    this.ePinnedColsViewport.style.height = bodyHeight + "px";
                }
            };
            GridPanel.prototype.addScrollListener = function () {
                // if printing, then no scrolling, so no point in listening for scroll events
                if (this.forPrint) {
                    return;
                }
                var that = this;
                var lastLeftPosition = -1;
                var lastTopPosition = -1;
                this.eBodyViewport.addEventListener("scroll", function () {
                    var newLeftPosition = that.eBodyViewport.scrollLeft;
                    var newTopPosition = that.eBodyViewport.scrollTop;
                    if (newLeftPosition !== lastLeftPosition) {
                        lastLeftPosition = newLeftPosition;
                        that.scrollHeader(newLeftPosition);
                    }
                    if (newTopPosition !== lastTopPosition) {
                        lastTopPosition = newTopPosition;
                        that.scrollPinned(newTopPosition);
                        that.rowRenderer.drawVirtualRows();
                    }
                });
                this.ePinnedColsViewport.addEventListener("scroll", function () {
                    // this means the pinned panel was moved, which can only
                    // happen when the user is navigating in the pinned container
                    // as the pinned col should never scroll. so we rollback
                    // the scroll on the pinned.
                    that.ePinnedColsViewport.scrollTop = 0;
                });
            };
            GridPanel.prototype.scrollHeader = function (bodyLeftPosition) {
                // this.eHeaderContainer.style.transform = 'translate3d(' + -bodyLeftPosition + "px,0,0)";
                this.eHeaderContainer.style.left = -bodyLeftPosition + "px";
            };
            GridPanel.prototype.scrollPinned = function (bodyTopPosition) {
                // this.ePinnedColsContainer.style.transform = 'translate3d(0,' + -bodyTopPosition + "px,0)";
                this.ePinnedColsContainer.style.top = -bodyTopPosition + "px";
            };
            return GridPanel;
        })();
        grid.GridPanel = GridPanel;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var DragAndDropService = (function () {
            function DragAndDropService() {
                // need to clean this up, add to 'finished' logic in grid
                document.addEventListener('mouseup', this.stopDragging.bind(this));
            }
            DragAndDropService.getInstance = function () {
                if (!this.theInstance) {
                    this.theInstance = new DragAndDropService();
                }
                return this.theInstance;
            };
            DragAndDropService.prototype.stopDragging = function () {
                if (this.dragItem) {
                    this.setDragCssClasses(this.dragItem.eDragSource, false);
                    this.dragItem = null;
                }
            };
            DragAndDropService.prototype.setDragCssClasses = function (eListItem, dragging) {
                utils.addOrRemoveCssClass(eListItem, 'ag-dragging', dragging);
                utils.addOrRemoveCssClass(eListItem, 'ag-not-dragging', !dragging);
            };
            DragAndDropService.prototype.addDragSource = function (eDragSource, dragSourceCallback) {
                this.setDragCssClasses(eDragSource, false);
                eDragSource.addEventListener('mousedown', this.onMouseDownDragSource.bind(this, eDragSource, dragSourceCallback));
            };
            DragAndDropService.prototype.onMouseDownDragSource = function (eDragSource, dragSourceCallback) {
                if (this.dragItem) {
                    this.stopDragging();
                }
                var data;
                if (dragSourceCallback.getData) {
                    data = dragSourceCallback.getData();
                }
                var containerId;
                if (dragSourceCallback.getContainerId) {
                    containerId = dragSourceCallback.getContainerId();
                }
                this.dragItem = {
                    eDragSource: eDragSource,
                    data: data,
                    containerId: containerId
                };
                this.setDragCssClasses(this.dragItem.eDragSource, true);
            };
            DragAndDropService.prototype.addDropTarget = function (eDropTarget, dropTargetCallback) {
                var mouseIn = false;
                var acceptDrag = false;
                var that = this;
                eDropTarget.addEventListener('mouseover', function () {
                    if (!mouseIn) {
                        mouseIn = true;
                        if (that.dragItem) {
                            acceptDrag = dropTargetCallback.acceptDrag(that.dragItem);
                        }
                        else {
                            acceptDrag = false;
                        }
                    }
                });
                eDropTarget.addEventListener('mouseout', function () {
                    if (acceptDrag) {
                        dropTargetCallback.noDrop();
                    }
                    mouseIn = false;
                    acceptDrag = false;
                });
                eDropTarget.addEventListener('mouseup', function () {
                    // dragItem should never be null, checking just in case
                    if (acceptDrag && that.dragItem) {
                        dropTargetCallback.drop(that.dragItem);
                    }
                });
            };
            return DragAndDropService;
        })();
        grid.DragAndDropService = DragAndDropService;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
/// <reference path="../dragAndDrop/dragAndDropService" />
/// <amd-dependency path="text!agList.html"/>
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        //var template = require('./agList.html');
        var utils = grid.Utils;
        var dragAndDropService = grid.DragAndDropService.getInstance();
        var template = '<div class="ag-list-selection">' + '<div>' + '<div ag-repeat class="ag-list-item">' + '</div>' + '</div>' + '</div>';
        var NOT_DROP_TARGET = 0;
        var DROP_TARGET_ABOVE = 1;
        var DROP_TARGET_BELOW = -11;
        var AgList = (function () {
            function AgList() {
                this.setupComponents();
                this.uniqueId = 'CheckboxSelection-' + Math.random();
                this.modelChangedListeners = [];
                this.itemSelectedListeners = [];
                this.beforeDropListeners = [];
                this.dragSources = [];
                this.setupAsDropTarget();
            }
            AgList.prototype.setEmptyMessage = function (emptyMessage) {
                this.emptyMessage = emptyMessage;
                this.refreshView();
            };
            AgList.prototype.getUniqueId = function () {
                return this.uniqueId;
            };
            AgList.prototype.addStyles = function (styles) {
                utils.addStylesToElement(this.eGui, styles);
            };
            AgList.prototype.addCssClass = function (cssClass) {
                utils.addCssClass(this.eGui, cssClass);
            };
            AgList.prototype.addDragSource = function (dragSource) {
                this.dragSources.push(dragSource);
            };
            AgList.prototype.addModelChangedListener = function (listener) {
                this.modelChangedListeners.push(listener);
            };
            AgList.prototype.addItemSelectedListener = function (listener) {
                this.itemSelectedListeners.push(listener);
            };
            AgList.prototype.addBeforeDropListener = function (listener) {
                this.beforeDropListeners.push(listener);
            };
            AgList.prototype.fireModelChanged = function () {
                for (var i = 0; i < this.modelChangedListeners.length; i++) {
                    this.modelChangedListeners[i]();
                }
            };
            AgList.prototype.fireItemSelected = function (item) {
                for (var i = 0; i < this.itemSelectedListeners.length; i++) {
                    this.itemSelectedListeners[i](item);
                }
            };
            AgList.prototype.fireBeforeDrop = function (item) {
                for (var i = 0; i < this.beforeDropListeners.length; i++) {
                    this.beforeDropListeners[i](item);
                }
            };
            AgList.prototype.setupComponents = function () {
                this.eGui = utils.loadTemplate(template);
                this.eFilterValueTemplate = this.eGui.querySelector("[ag-repeat]");
                this.eListParent = this.eFilterValueTemplate.parentNode;
                utils.removeAllChildren(this.eListParent);
            };
            AgList.prototype.setModel = function (model) {
                this.model = model;
                this.refreshView();
            };
            AgList.prototype.getModel = function () {
                return this.model;
            };
            AgList.prototype.setCellRenderer = function (cellRenderer) {
                this.cellRenderer = cellRenderer;
            };
            AgList.prototype.refreshView = function () {
                utils.removeAllChildren(this.eListParent);
                if (this.model && this.model.length > 0) {
                    this.insertRows();
                }
                else {
                    this.insertBlankMessage();
                }
            };
            AgList.prototype.insertRows = function () {
                for (var i = 0; i < this.model.length; i++) {
                    var item = this.model[i];
                    //var text = this.getText(item);
                    //var selected = this.isSelected(item);
                    var eListItem = this.eFilterValueTemplate.cloneNode(true);
                    if (this.cellRenderer) {
                        var params = { value: item };
                        utils.useRenderer(eListItem, this.cellRenderer, params);
                    }
                    else {
                        eListItem.innerHTML = item;
                    }
                    eListItem.addEventListener('click', this.fireItemSelected.bind(this, item));
                    this.addDragAndDropToListItem(eListItem, item);
                    this.eListParent.appendChild(eListItem);
                }
            };
            AgList.prototype.insertBlankMessage = function () {
                if (this.emptyMessage) {
                    var eMessage = document.createElement('div');
                    eMessage.style.color = 'grey';
                    eMessage.style.padding = '4px';
                    eMessage.style.textAlign = 'center';
                    eMessage.innerHTML = this.emptyMessage;
                    this.eListParent.appendChild(eMessage);
                }
            };
            AgList.prototype.setupAsDropTarget = function () {
                dragAndDropService.addDropTarget(this.eGui, {
                    acceptDrag: this.externalAcceptDrag.bind(this),
                    drop: this.externalDrop.bind(this),
                    noDrop: this.externalNoDrop.bind(this)
                });
            };
            AgList.prototype.externalAcceptDrag = function (dragEvent) {
                var allowedSource = this.dragSources.indexOf(dragEvent.containerId) >= 0;
                if (!allowedSource) {
                    return false;
                }
                var alreadyHaveCol = this.model.indexOf(dragEvent.data) >= 0;
                if (alreadyHaveCol) {
                    return false;
                }
                this.eGui.style.backgroundColor = 'lightgreen';
                return true;
            };
            AgList.prototype.externalDrop = function (dragEvent) {
                var newListItem = dragEvent.data;
                this.fireBeforeDrop(newListItem);
                this.addItemToList(newListItem);
                this.eGui.style.backgroundColor = '';
            };
            AgList.prototype.externalNoDrop = function () {
                this.eGui.style.backgroundColor = '';
            };
            AgList.prototype.addItemToList = function (newItem) {
                this.model.push(newItem);
                this.refreshView();
                this.fireModelChanged();
            };
            AgList.prototype.addDragAndDropToListItem = function (eListItem, item) {
                var that = this;
                dragAndDropService.addDragSource(eListItem, {
                    getData: function () {
                        return item;
                    },
                    getContainerId: function () {
                        return that.uniqueId;
                    }
                });
                dragAndDropService.addDropTarget(eListItem, {
                    acceptDrag: function (dragItem) {
                        return that.internalAcceptDrag(item, dragItem, eListItem);
                    },
                    drop: function (dragItem) {
                        that.internalDrop(item, dragItem.data);
                    },
                    noDrop: function () {
                        that.internalNoDrop(eListItem);
                    }
                });
            };
            AgList.prototype.internalAcceptDrag = function (targetColumn, dragItem, eListItem) {
                var result = dragItem.data !== targetColumn && dragItem.containerId === this.uniqueId;
                if (result) {
                    if (this.dragAfterThisItem(targetColumn, dragItem.data)) {
                        this.setDropCssClasses(eListItem, DROP_TARGET_ABOVE);
                    }
                    else {
                        this.setDropCssClasses(eListItem, DROP_TARGET_BELOW);
                    }
                }
                return result;
            };
            AgList.prototype.internalDrop = function (targetColumn, draggedColumn) {
                var oldIndex = this.model.indexOf(draggedColumn);
                var newIndex = this.model.indexOf(targetColumn);
                this.model.splice(oldIndex, 1);
                this.model.splice(newIndex, 0, draggedColumn);
                this.refreshView();
                this.fireModelChanged();
            };
            AgList.prototype.internalNoDrop = function (eListItem) {
                this.setDropCssClasses(eListItem, NOT_DROP_TARGET);
            };
            AgList.prototype.dragAfterThisItem = function (targetColumn, draggedColumn) {
                return this.model.indexOf(targetColumn) < this.model.indexOf(draggedColumn);
            };
            AgList.prototype.setDropCssClasses = function (eListItem, state) {
                utils.addOrRemoveCssClass(eListItem, 'ag-not-drop-target', state === NOT_DROP_TARGET);
                utils.addOrRemoveCssClass(eListItem, 'ag-drop-target-above', state === DROP_TARGET_ABOVE);
                utils.addOrRemoveCssClass(eListItem, 'ag-drop-target-below', state === DROP_TARGET_BELOW);
            };
            AgList.prototype.getGui = function () {
                return this.eGui;
            };
            return AgList;
        })();
        grid.AgList = AgList;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../widgets/agList.ts" />
/// <reference path="../utils.ts" />
/// <reference path="../svgFactory.ts" />
/// <reference path="../layout/BorderLayout.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var svgFactory = grid.SvgFactory.getInstance();
        var ColumnSelectionPanel = (function () {
            function ColumnSelectionPanel(columnController, gridOptionsWrapper) {
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.setupComponents();
                this.columnController = columnController;
                var that = this;
                this.columnController.addListener({
                    columnsChanged: that.columnsChanged.bind(that)
                });
            }
            ColumnSelectionPanel.prototype.columnsChanged = function (newColumns) {
                this.cColumnList.setModel(newColumns);
            };
            ColumnSelectionPanel.prototype.getDragSource = function () {
                return this.cColumnList.getUniqueId();
            };
            ColumnSelectionPanel.prototype.columnCellRenderer = function (params) {
                var column = params.value;
                var colDisplayName = this.columnController.getDisplayNameForCol(column);
                var eResult = document.createElement('span');
                var eVisibleIcons = document.createElement('span');
                utils.addCssClass(eVisibleIcons, 'ag-visible-icons');
                var eShowing = utils.createIcon('columnVisible', this.gridOptionsWrapper, column, svgFactory.createColumnShowingSvg);
                var eHidden = utils.createIcon('columnHidden', this.gridOptionsWrapper, column, svgFactory.createColumnHiddenSvg);
                eVisibleIcons.appendChild(eShowing);
                eVisibleIcons.appendChild(eHidden);
                eShowing.style.display = column.visible ? '' : 'none';
                eHidden.style.display = column.visible ? 'none' : '';
                eResult.appendChild(eVisibleIcons);
                var eValue = document.createElement('span');
                eValue.innerHTML = colDisplayName;
                eResult.appendChild(eValue);
                if (!column.visible) {
                    utils.addCssClass(eResult, 'ag-column-not-visible');
                }
                // change visible if use clicks the visible icon, or if row is double clicked
                eVisibleIcons.addEventListener('click', showEventListener);
                var that = this;
                function showEventListener() {
                    column.visible = !column.visible;
                    that.cColumnList.refreshView();
                    that.columnController.onColumnStateChanged();
                }
                return eResult;
            };
            ColumnSelectionPanel.prototype.setupComponents = function () {
                this.cColumnList = new grid.AgList();
                this.cColumnList.setCellRenderer(this.columnCellRenderer.bind(this));
                this.cColumnList.addStyles({ height: '100%', overflow: 'auto' });
                var that = this;
                this.cColumnList.addModelChangedListener(function () {
                    that.columnController.onColumnStateChanged();
                });
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                var columnsLocalText = localeTextFunc('columns', 'Columns');
                var eNorthPanel = document.createElement('div');
                eNorthPanel.innerHTML = '<div style="text-align: center;">' + columnsLocalText + '</div>';
                this.layout = new grid.BorderLayout({
                    center: this.cColumnList.getGui(),
                    north: eNorthPanel
                });
            };
            // not sure if this is called anywhere
            ColumnSelectionPanel.prototype.setSelected = function (column, selected) {
                column.visible = selected;
                this.columnController.onColumnStateChanged();
            };
            ColumnSelectionPanel.prototype.getGui = function () {
                return this.eRootPanel.getGui();
            };
            return ColumnSelectionPanel;
        })();
        grid.ColumnSelectionPanel = ColumnSelectionPanel;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../widgets/agList.ts" />
/// <reference path="../utils.ts" />
/// <reference path="../svgFactory.ts" />
/// <reference path="../layout/BorderLayout.ts" />
/// <reference path="../constants.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var svgFactory = grid.SvgFactory.getInstance();
        var constants = grid.Constants;
        var GroupSelectionPanel = (function () {
            function GroupSelectionPanel(columnController, inMemoryRowController, gridOptionsWrapper) {
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.setupComponents();
                this.columnController = columnController;
                this.inMemoryRowController = inMemoryRowController;
                var that = this;
                this.columnController.addListener({
                    columnsChanged: that.columnsChanged.bind(that)
                });
            }
            GroupSelectionPanel.prototype.columnsChanged = function (newColumns, newGroupedColumns) {
                this.cColumnList.setModel(newGroupedColumns);
            };
            GroupSelectionPanel.prototype.addDragSource = function (dragSource) {
                this.cColumnList.addDragSource(dragSource);
            };
            GroupSelectionPanel.prototype.columnCellRenderer = function (params) {
                var column = params.value;
                var colDisplayName = this.columnController.getDisplayNameForCol(column);
                var eResult = document.createElement('span');
                var eRemove = utils.createIcon('columnRemoveFromGroup', this.gridOptionsWrapper, column, svgFactory.createArrowUpSvg);
                utils.addCssClass(eRemove, 'ag-visible-icons');
                eResult.appendChild(eRemove);
                var that = this;
                eRemove.addEventListener('click', function () {
                    var model = that.cColumnList.getModel();
                    model.splice(model.indexOf(column), 1);
                    that.cColumnList.setModel(model);
                    that.onGroupingChanged();
                });
                var eValue = document.createElement('span');
                eValue.innerHTML = colDisplayName;
                eResult.appendChild(eValue);
                return eResult;
            };
            GroupSelectionPanel.prototype.setupComponents = function () {
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                var columnsLocalText = localeTextFunc('pivotedColumns', 'Pivoted Columns');
                var pivotedColumnsEmptyMessage = localeTextFunc('pivotedColumnsEmptyMessage', 'Drag columns from above to pivot');
                this.cColumnList = new grid.AgList();
                this.cColumnList.setCellRenderer(this.columnCellRenderer.bind(this));
                this.cColumnList.addModelChangedListener(this.onGroupingChanged.bind(this));
                this.cColumnList.setEmptyMessage(pivotedColumnsEmptyMessage);
                this.cColumnList.addStyles({ height: '100%', overflow: 'auto' });
                var eNorthPanel = document.createElement('div');
                eNorthPanel.style.paddingTop = '10px';
                eNorthPanel.innerHTML = '<div style="text-align: center;">' + columnsLocalText + '</div>';
                this.layout = new grid.BorderLayout({
                    center: this.cColumnList.getGui(),
                    north: eNorthPanel
                });
            };
            GroupSelectionPanel.prototype.onGroupingChanged = function () {
                this.inMemoryRowController.doGrouping();
                this.inMemoryRowController.updateModel(constants.STEP_EVERYTHING);
                this.columnController.onColumnStateChanged();
            };
            return GroupSelectionPanel;
        })();
        grid.GroupSelectionPanel = GroupSelectionPanel;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
/// <reference path="./agList.ts" />
/// <reference path="../svgFactory.ts" />
/// <reference path="../widgets/agPopupService.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var svgFactory = grid.SvgFactory.getInstance();
        var agPopupService = grid.PopupService.getInstance();
        var AgDropdownList = (function () {
            function AgDropdownList() {
                this.setupComponents();
                this.itemSelectedListeners = [];
            }
            AgDropdownList.prototype.setWidth = function (width) {
                this.eValue.style.width = width + 'px';
                this.agList.addStyles({ width: width + 'px' });
            };
            AgDropdownList.prototype.addItemSelectedListener = function (listener) {
                this.itemSelectedListeners.push(listener);
            };
            AgDropdownList.prototype.fireItemSelected = function (item) {
                for (var i = 0; i < this.itemSelectedListeners.length; i++) {
                    this.itemSelectedListeners[i](item);
                }
            };
            AgDropdownList.prototype.setupComponents = function () {
                this.eGui = document.createElement('span');
                this.eValue = document.createElement('span');
                this.eGui.appendChild(this.eValue);
                this.agList = new grid.AgList();
                this.eValue.addEventListener('click', this.onClick.bind(this));
                this.agList.addItemSelectedListener(this.itemSelected.bind(this));
                this.agList.addCssClass('ag-popup-list');
                utils.addStylesToElement(this.eValue, {
                    border: '1px solid darkgrey',
                    display: 'inline-block',
                    paddingLeft: 2
                });
                utils.addStylesToElement(this.eGui, { position: 'relative' });
                this.agList.addStyles({
                    display: 'inline-block',
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    backgroudColor: 'white'
                });
            };
            AgDropdownList.prototype.itemSelected = function (item) {
                this.setSelected(item);
                if (this.hidePopupCallback) {
                    this.hidePopupCallback();
                }
                this.fireItemSelected(item);
            };
            AgDropdownList.prototype.onClick = function () {
                var agListGui = this.agList.getGui();
                agPopupService.positionPopup(this.eGui, agListGui, -1);
                this.hidePopupCallback = agPopupService.addAsModalPopup(agListGui);
            };
            AgDropdownList.prototype.getGui = function () {
                return this.eGui;
            };
            AgDropdownList.prototype.setSelected = function (item) {
                this.selectedItem = item;
                this.refreshView();
            };
            AgDropdownList.prototype.setCellRenderer = function (cellRenderer) {
                this.agList.setCellRenderer(cellRenderer);
                this.cellRenderer = cellRenderer;
            };
            AgDropdownList.prototype.refreshView = function () {
                utils.removeAllChildren(this.eValue);
                if (this.selectedItem) {
                    if (this.cellRenderer) {
                        var params = { value: this.selectedItem };
                        utils.useRenderer(this.eValue, this.cellRenderer, params);
                    }
                    else {
                        this.eValue.appendChild(document.createTextNode(this.selectedItem));
                    }
                }
                var eDownIcon = svgFactory.createSmallArrowDownSvg();
                eDownIcon.style.float = 'right';
                eDownIcon.style.marginTop = '6';
                eDownIcon.style.marginRight = '2';
                this.eValue.appendChild(eDownIcon);
            };
            AgDropdownList.prototype.setModel = function (model) {
                this.agList.setModel(model);
            };
            return AgDropdownList;
        })();
        grid.AgDropdownList = AgDropdownList;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../widgets/agList.ts" />
/// <reference path="../constants.ts" />
/// <reference path="../utils.ts" />
/// <reference path="../layout/borderLayout.ts" />
/// <reference path="../svgFactory.ts" />
/// <reference path="../widgets/agDropdownList.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var svgFactory = grid.SvgFactory.getInstance();
        var constants = grid.Constants;
        var utils = grid.Utils;
        var ValuesSelectionPanel = (function () {
            function ValuesSelectionPanel(columnController, gridOptionsWrapper, api) {
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.setupComponents();
                this.columnController = columnController;
                this.api = api;
                var that = this;
                this.columnController.addListener({
                    columnsChanged: that.columnsChanged.bind(that)
                });
            }
            ValuesSelectionPanel.prototype.columnsChanged = function (newColumns, newGroupedColumns, newValuesColumns) {
                this.cColumnList.setModel(newValuesColumns);
            };
            ValuesSelectionPanel.prototype.addDragSource = function (dragSource) {
                this.cColumnList.addDragSource(dragSource);
            };
            ValuesSelectionPanel.prototype.cellRenderer = function (params) {
                var column = params.value;
                var colDisplayName = this.columnController.getDisplayNameForCol(column);
                var eResult = document.createElement('span');
                var eRemove = utils.createIcon('columnRemoveFromGroup', this.gridOptionsWrapper, column, svgFactory.createArrowUpSvg);
                utils.addCssClass(eRemove, 'ag-visible-icons');
                eResult.appendChild(eRemove);
                var that = this;
                eRemove.addEventListener('click', function () {
                    var model = that.cColumnList.getModel();
                    model.splice(model.indexOf(column), 1);
                    that.cColumnList.setModel(model);
                    that.onValuesChanged();
                });
                var agValueType = new grid.AgDropdownList();
                agValueType.setModel([constants.SUM, constants.MIN, constants.MAX]);
                agValueType.setSelected(column.aggFunc);
                agValueType.setWidth(45);
                agValueType.addItemSelectedListener(function (item) {
                    column.aggFunc = item;
                    that.onValuesChanged();
                });
                eResult.appendChild(agValueType.getGui());
                var eValue = document.createElement('span');
                eValue.innerHTML = colDisplayName;
                eValue.style.paddingLeft = '2px';
                eResult.appendChild(eValue);
                return eResult;
            };
            ValuesSelectionPanel.prototype.setupComponents = function () {
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                var columnsLocalText = localeTextFunc('valueColumns', 'Value Columns');
                var emptyMessage = localeTextFunc('valueColumnsEmptyMessage', 'Drag columns from above to create values');
                this.cColumnList = new grid.AgList();
                this.cColumnList.setCellRenderer(this.cellRenderer.bind(this));
                this.cColumnList.addModelChangedListener(this.onValuesChanged.bind(this));
                this.cColumnList.setEmptyMessage(emptyMessage);
                this.cColumnList.addStyles({ height: '100%', overflow: 'auto' });
                this.cColumnList.addBeforeDropListener(this.beforeDropListener.bind(this));
                var eNorthPanel = document.createElement('div');
                eNorthPanel.style.paddingTop = '10px';
                eNorthPanel.innerHTML = '<div style="text-align: center;">' + columnsLocalText + '</div>';
                this.layout = new grid.BorderLayout({
                    center: this.cColumnList.getGui(),
                    north: eNorthPanel
                });
            };
            ValuesSelectionPanel.prototype.beforeDropListener = function (newItem) {
                if (!newItem.aggFunc) {
                    newItem.aggFunc = constants.SUM;
                }
            };
            ValuesSelectionPanel.prototype.onValuesChanged = function () {
                this.api.recomputeAggregates();
            };
            return ValuesSelectionPanel;
        })();
        grid.ValuesSelectionPanel = ValuesSelectionPanel;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var VerticalStack = (function () {
            function VerticalStack() {
                this.isLayoutPanel = true;
                this.childPanels = [];
                this.eGui = document.createElement('div');
                this.eGui.style.height = '100%';
            }
            VerticalStack.prototype.addPanel = function (panel, height) {
                var component;
                if (panel.isLayoutPanel) {
                    this.childPanels.push(panel);
                    component = panel.getGui();
                }
                else {
                    component = panel;
                }
                if (height) {
                    component.style.height = height;
                }
                this.eGui.appendChild(component);
            };
            VerticalStack.prototype.getGui = function () {
                return this.eGui;
            };
            VerticalStack.prototype.doLayout = function () {
                for (var i = 0; i < this.childPanels.length; i++) {
                    this.childPanels[i].doLayout();
                }
            };
            return VerticalStack;
        })();
        grid.VerticalStack = VerticalStack;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="../utils.ts" />
/// <reference path="./columnSelectionPanel.ts" />
/// <reference path="./groupSelectionPanel.ts" />
/// <reference path="./valuesSelectionPanel.ts" />
/// <reference path="../layout/verticalStack.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var utils = grid.Utils;
        var ToolPanel = (function () {
            function ToolPanel() {
                this.layout = new grid.VerticalStack();
            }
            ToolPanel.prototype.init = function (columnController, inMemoryRowController, gridOptionsWrapper, api) {
                var suppressPivotAndValues = gridOptionsWrapper.isToolPanelSuppressPivot();
                var suppressValues = gridOptionsWrapper.isToolPanelSuppressValues();
                var showPivot = !suppressPivotAndValues;
                var showValues = !suppressPivotAndValues && !suppressValues;
                // top list, column reorder and visibility
                var columnSelectionPanel = new grid.ColumnSelectionPanel(columnController, gridOptionsWrapper);
                var heightColumnSelection = suppressPivotAndValues ? '100%' : '50%';
                this.layout.addPanel(columnSelectionPanel.layout, heightColumnSelection);
                var dragSource = columnSelectionPanel.getDragSource();
                if (showValues) {
                    var valuesSelectionPanel = new grid.ValuesSelectionPanel(columnController, gridOptionsWrapper, api);
                    this.layout.addPanel(valuesSelectionPanel.layout, '25%');
                    valuesSelectionPanel.addDragSource(dragSource);
                }
                if (showPivot) {
                    var groupSelectionPanel = new grid.GroupSelectionPanel(columnController, inMemoryRowController, gridOptionsWrapper);
                    var heightPivotSelection = showValues ? '25%' : '50%';
                    this.layout.addPanel(groupSelectionPanel.layout, heightPivotSelection);
                    groupSelectionPanel.addDragSource(dragSource);
                }
                var eGui = this.layout.getGui();
                utils.addCssClass(eGui, 'ag-tool-panel-container');
            };
            return ToolPanel;
        })();
        grid.ToolPanel = ToolPanel;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="constants.ts" />
/// <reference path="gridOptionsWrapper.ts" />
/// <reference path="utils.ts" />
/// <reference path="filter/filterManager.ts" />
/// <reference path="columnController.ts" />
/// <reference path="selectionController.ts" />
/// <reference path="selectionRendererFactory.ts" />
/// <reference path="rowRenderer.ts" />
/// <reference path="headerRenderer.ts" />
/// <reference path="rowControllers/inMemoryRowController.ts" />
/// <reference path="rowControllers/virtualPageRowController.ts" />
/// <reference path="rowControllers/paginationController.ts" />
/// <reference path="expressionService.ts" />
/// <reference path="templateService.ts" />
/// <reference path="gridPanel/gridPanel.ts" />
/// <reference path="toolPanel/toolPanel.ts" />
/// <reference path="widgets/agPopupService.ts" />
/// <reference path="gridOptions.ts" />
var awk;
(function (awk) {
    var grid;
    (function (grid) {
        var constants = grid.Constants;
        var utils = grid.Utils;
        var agPopupService = grid.PopupService.getInstance();
        var Grid = (function () {
            function Grid(eGridDiv, gridOptions, $scope, $compile, quickFilterOnScope) {
                this.gridOptions = gridOptions;
                this.gridOptionsWrapper = new grid.GridOptionsWrapper(this.gridOptions);
                this.addApi();
                this.setupComponents($scope, $compile, eGridDiv);
                var that = this;
                this.quickFilter = null;
                // if using angular, watch for quickFilter changes
                if ($scope) {
                    $scope.$watch(quickFilterOnScope, function (newFilter) {
                        that.onQuickFilterChanged(newFilter);
                    });
                }
                this.virtualRowCallbacks = {};
                this.scrollWidth = utils.getScrollbarWidth();
                // done when cols change
                this.setupColumns();
                this.inMemoryRowController.setAllRows(this.gridOptionsWrapper.getAllRows());
                var forPrint = this.gridOptionsWrapper.isDontUseScrolls();
                if (!forPrint) {
                    window.addEventListener('resize', this.doLayout.bind(this));
                }
                this.updateModelAndRefresh(constants.STEP_EVERYTHING);
                // if no data provided initially, and not doing infinite scrolling, show the loading panel
                var showLoading = !this.gridOptionsWrapper.getAllRows() && !this.gridOptionsWrapper.isVirtualPaging();
                this.showLoadingPanel(showLoading);
                // if datasource provided, use it
                if (this.gridOptionsWrapper.getDatasource()) {
                    this.setDatasource();
                }
                this.doLayout();
                this.finished = false;
                this.periodicallyDoLayout();
                // if ready function provided, use it
                if (typeof this.gridOptionsWrapper.getReady() == 'function') {
                    this.gridOptionsWrapper.getReady()(gridOptions.api);
                }
            }
            Grid.prototype.periodicallyDoLayout = function () {
                if (!this.finished) {
                    var that = this;
                    setTimeout(function () {
                        that.doLayout();
                        that.periodicallyDoLayout();
                    }, 500);
                }
            };
            Grid.prototype.setupComponents = function ($scope, $compile, eUserProvidedDiv) {
                // make local references, to make the below more human readable
                var gridOptionsWrapper = this.gridOptionsWrapper;
                var gridOptions = this.gridOptions;
                var forPrint = gridOptionsWrapper.isDontUseScrolls();
                // create all the beans
                var selectionController = new grid.SelectionController();
                var filterManager = new grid.FilterManager();
                var selectionRendererFactory = new grid.SelectionRendererFactory();
                var columnController = new grid.ColumnController();
                var rowRenderer = new grid.RowRenderer();
                var headerRenderer = new grid.HeaderRenderer();
                var inMemoryRowController = new grid.InMemoryRowController();
                var virtualPageRowController = new grid.VirtualPageRowController();
                var expressionService = new grid.ExpressionService();
                var templateService = new grid.TemplateService();
                var gridPanel = new grid.GridPanel(gridOptionsWrapper);
                var columnModel = columnController.getModel();
                // initialise all the beans
                templateService.init($scope);
                selectionController.init(this, gridPanel, gridOptionsWrapper, $scope, rowRenderer);
                filterManager.init(this, gridOptionsWrapper, $compile, $scope, expressionService, columnModel);
                selectionRendererFactory.init(this, selectionController);
                columnController.init(this, selectionRendererFactory, gridOptionsWrapper, expressionService);
                rowRenderer.init(gridOptions, columnModel, gridOptionsWrapper, gridPanel, this, selectionRendererFactory, $compile, $scope, selectionController, expressionService, templateService);
                headerRenderer.init(gridOptionsWrapper, columnController, columnModel, gridPanel, this, filterManager, $scope, $compile, expressionService);
                inMemoryRowController.init(gridOptionsWrapper, columnModel, this, filterManager, $scope, expressionService);
                virtualPageRowController.init(rowRenderer, gridOptionsWrapper, this);
                gridPanel.init(columnModel, rowRenderer);
                var toolPanelLayout = null;
                var eToolPanel = null;
                if (!forPrint) {
                    eToolPanel = new grid.ToolPanel();
                    toolPanelLayout = eToolPanel.layout;
                    eToolPanel.init(columnController, inMemoryRowController, gridOptionsWrapper, this.gridOptions.api);
                }
                // this is a child bean, get a reference and pass it on
                // CAN WE DELETE THIS? it's done in the setDatasource section
                var rowModel = inMemoryRowController.getModel();
                selectionController.setRowModel(rowModel);
                filterManager.setRowModel(rowModel);
                rowRenderer.setRowModel(rowModel);
                gridPanel.setRowModel(rowModel);
                // and the last bean, done in it's own section, as it's optional
                var paginationController = null;
                var paginationGui = null;
                if (!forPrint) {
                    paginationController = new grid.PaginationController();
                    paginationController.init(this, gridOptionsWrapper);
                    paginationGui = paginationController.getGui();
                }
                this.rowModel = rowModel;
                this.selectionController = selectionController;
                this.columnController = columnController;
                this.columnModel = columnModel;
                this.inMemoryRowController = inMemoryRowController;
                this.virtualPageRowController = virtualPageRowController;
                this.rowRenderer = rowRenderer;
                this.headerRenderer = headerRenderer;
                this.paginationController = paginationController;
                this.filterManager = filterManager;
                this.eToolPanel = eToolPanel;
                this.gridPanel = gridPanel;
                this.eRootPanel = new grid.BorderLayout({
                    center: gridPanel.layout,
                    east: toolPanelLayout,
                    south: paginationGui,
                    dontFill: forPrint,
                    name: 'eRootPanel'
                });
                agPopupService.init(this.eRootPanel.getGui());
                // default is we don't show paging panel, this is set to true when datasource is set
                this.eRootPanel.setSouthVisible(false);
                // see what the grid options are for default of toolbar
                this.showToolPanel(gridOptionsWrapper.isShowToolPanel());
                eUserProvidedDiv.appendChild(this.eRootPanel.getGui());
            };
            Grid.prototype.showToolPanel = function (show) {
                if (!this.eToolPanel) {
                    this.toolPanelShowing = false;
                    return;
                }
                this.toolPanelShowing = show;
                this.eRootPanel.setEastVisible(show);
            };
            Grid.prototype.isToolPanelShowing = function () {
                return this.toolPanelShowing;
            };
            Grid.prototype.setDatasource = function (datasource) {
                // if datasource provided, then set it
                if (datasource) {
                    this.gridOptions.datasource = datasource;
                }
                // get the set datasource (if null was passed to this method,
                // then need to get the actual datasource from options
                var datasourceToUse = this.gridOptionsWrapper.getDatasource();
                this.doingVirtualPaging = this.gridOptionsWrapper.isVirtualPaging() && datasourceToUse;
                this.doingPagination = datasourceToUse && !this.doingVirtualPaging;
                var showPagingPanel;
                if (this.doingVirtualPaging) {
                    this.paginationController.setDatasource(null);
                    this.virtualPageRowController.setDatasource(datasourceToUse);
                    this.rowModel = this.virtualPageRowController.getModel();
                    showPagingPanel = false;
                }
                else if (this.doingPagination) {
                    this.paginationController.setDatasource(datasourceToUse);
                    this.virtualPageRowController.setDatasource(null);
                    this.rowModel = this.inMemoryRowController.getModel();
                    showPagingPanel = true;
                }
                else {
                    this.paginationController.setDatasource(null);
                    this.virtualPageRowController.setDatasource(null);
                    this.rowModel = this.inMemoryRowController.getModel();
                    showPagingPanel = false;
                }
                this.selectionController.setRowModel(this.rowModel);
                this.filterManager.setRowModel(this.rowModel);
                this.rowRenderer.setRowModel(this.rowModel);
                this.eRootPanel.setSouthVisible(showPagingPanel);
                // because we just set the rowModel, need to update the gui
                this.rowRenderer.refreshView();
                this.doLayout();
            };
            // gets called after columns are shown / hidden from groups expanding
            Grid.prototype.refreshHeaderAndBody = function () {
                this.headerRenderer.refreshHeader();
                this.headerRenderer.updateFilterIcons();
                this.headerRenderer.updateSortIcons();
                this.gridPanel.setBodyContainerWidth();
                this.gridPanel.setPinnedColContainerWidth();
                this.rowRenderer.refreshView();
            };
            Grid.prototype.setFinished = function () {
                window.removeEventListener('resize', this.doLayout);
                this.finished = true;
            };
            Grid.prototype.getQuickFilter = function () {
                return this.quickFilter;
            };
            Grid.prototype.onQuickFilterChanged = function (newFilter) {
                if (newFilter === undefined || newFilter === "") {
                    newFilter = null;
                }
                if (this.quickFilter !== newFilter) {
                    if (this.gridOptionsWrapper.isVirtualPaging()) {
                        console.warn('ag-grid: cannot do quick filtering when doing virtual paging');
                        return;
                    }
                    //want 'null' to mean to filter, so remove undefined and empty string
                    if (newFilter === undefined || newFilter === "") {
                        newFilter = null;
                    }
                    if (newFilter !== null) {
                        newFilter = newFilter.toUpperCase();
                    }
                    this.quickFilter = newFilter;
                    this.onFilterChanged();
                }
            };
            Grid.prototype.onFilterChanged = function () {
                this.headerRenderer.updateFilterIcons();
                if (this.gridOptionsWrapper.isEnableServerSideFilter()) {
                    // if doing server side filtering, changing the sort has the impact
                    // of resetting the datasource
                    this.setDatasource();
                }
                else {
                    // if doing in memory filtering, we just update the in memory data
                    this.updateModelAndRefresh(constants.STEP_FILTER);
                }
            };
            Grid.prototype.onRowClicked = function (event, rowIndex, node) {
                if (this.gridOptions.rowClicked) {
                    var params = {
                        node: node,
                        data: node.data,
                        event: event,
                        rowIndex: rowIndex
                    };
                    this.gridOptions.rowClicked(params);
                }
                // we do not allow selecting groups by clicking (as the click here expands the group)
                // so return if it's a group row
                if (node.group) {
                    return;
                }
                // making local variables to make the below more readable
                var gridOptionsWrapper = this.gridOptionsWrapper;
                var selectionController = this.selectionController;
                // if no selection method enabled, do nothing
                if (!gridOptionsWrapper.isRowSelection()) {
                    return;
                }
                // if click selection suppressed, do nothing
                if (gridOptionsWrapper.isSuppressRowClickSelection()) {
                    return;
                }
                // ctrlKey for windows, metaKey for Apple
                var ctrlKeyPressed = event.ctrlKey || event.metaKey;
                var doDeselect = ctrlKeyPressed && selectionController.isNodeSelected(node) && gridOptionsWrapper.isRowDeselection();
                if (doDeselect) {
                    selectionController.deselectNode(node);
                }
                else {
                    var tryMulti = ctrlKeyPressed;
                    selectionController.selectNode(node, tryMulti);
                }
            };
            Grid.prototype.showLoadingPanel = function (show) {
                this.gridPanel.showLoading(show);
            };
            Grid.prototype.setupColumns = function () {
                this.gridPanel.setHeaderHeight();
                this.columnController.setColumns(this.gridOptionsWrapper.getColumnDefs());
                this.gridPanel.showPinnedColContainersIfNeeded();
                this.headerRenderer.refreshHeader();
                if (!this.gridOptionsWrapper.isDontUseScrolls()) {
                    this.gridPanel.setPinnedColContainerWidth();
                    this.gridPanel.setBodyContainerWidth();
                }
                this.headerRenderer.updateFilterIcons();
            };
            // rowsToRefresh is at what index to start refreshing the rows. the assumption is
            // if we are expanding or collapsing a group, then only he rows below the group
            // need to be refresh. this allows the context (eg focus) of the other cells to
            // remain.
            Grid.prototype.updateModelAndRefresh = function (step, refreshFromIndex) {
                this.inMemoryRowController.updateModel(step);
                this.rowRenderer.refreshView(refreshFromIndex);
            };
            Grid.prototype.setRows = function (rows, firstId) {
                if (rows) {
                    this.gridOptions.rowData = rows;
                }
                this.inMemoryRowController.setAllRows(this.gridOptionsWrapper.getAllRows(), firstId);
                this.selectionController.deselectAll();
                this.filterManager.onNewRowsLoaded();
                this.updateModelAndRefresh(constants.STEP_EVERYTHING);
                this.headerRenderer.updateFilterIcons();
                this.showLoadingPanel(false);
            };
            Grid.prototype.ensureNodeVisible = function (comparator) {
                if (this.doingVirtualPaging) {
                    throw 'Cannot use ensureNodeVisible when doing virtual paging, as we cannot check rows that are not in memory';
                }
                // look for the node index we want to display
                var rowCount = this.rowModel.getVirtualRowCount();
                var comparatorIsAFunction = typeof comparator === 'function';
                var indexToSelect = -1;
                for (var i = 0; i < rowCount; i++) {
                    var node = this.rowModel.getVirtualRow(i);
                    if (comparatorIsAFunction) {
                        if (comparator(node)) {
                            indexToSelect = i;
                            break;
                        }
                    }
                    else {
                        // check object equality against node and data
                        if (comparator === node || comparator === node.data) {
                            indexToSelect = i;
                            break;
                        }
                    }
                }
                if (indexToSelect >= 0) {
                    this.gridPanel.ensureIndexVisible(indexToSelect);
                }
            };
            Grid.prototype.getFilterModel = function () {
                return this.filterManager.getFilterModel();
            };
            Grid.prototype.addApi = function () {
                var that = this;
                var api = {
                    setDatasource: function (datasource) {
                        that.setDatasource(datasource);
                    },
                    onNewDatasource: function () {
                        that.setDatasource();
                    },
                    setRows: function (rows) {
                        that.setRows(rows);
                    },
                    onNewRows: function () {
                        that.setRows();
                    },
                    onNewCols: function () {
                        that.onNewCols();
                    },
                    unselectAll: function () {
                        console.error("unselectAll deprecated, call deselectAll instead");
                        this.deselectAll();
                    },
                    refreshView: function () {
                        that.rowRenderer.refreshView();
                    },
                    softRefreshView: function () {
                        that.rowRenderer.softRefreshView();
                    },
                    refreshGroupRows: function () {
                        that.rowRenderer.refreshGroupRows();
                    },
                    refreshHeader: function () {
                        // need to review this - the refreshHeader should also refresh all icons in the header
                        that.headerRenderer.refreshHeader();
                        that.headerRenderer.updateFilterIcons();
                    },
                    getModel: function () {
                        return that.rowModel;
                    },
                    onGroupExpandedOrCollapsed: function (refreshFromIndex) {
                        that.updateModelAndRefresh(constants.STEP_MAP, refreshFromIndex);
                    },
                    expandAll: function () {
                        that.inMemoryRowController.expandOrCollapseAll(true, null);
                        that.updateModelAndRefresh(constants.STEP_MAP);
                    },
                    collapseAll: function () {
                        that.inMemoryRowController.expandOrCollapseAll(false, null);
                        that.updateModelAndRefresh(constants.STEP_MAP);
                    },
                    addVirtualRowListener: function (rowIndex, callback) {
                        that.addVirtualRowListener(rowIndex, callback);
                    },
                    rowDataChanged: function (rows) {
                        that.rowRenderer.rowDataChanged(rows);
                    },
                    setQuickFilter: function (newFilter) {
                        that.onQuickFilterChanged(newFilter);
                    },
                    selectIndex: function (index, tryMulti, suppressEvents) {
                        that.selectionController.selectIndex(index, tryMulti, suppressEvents);
                    },
                    deselectIndex: function (index) {
                        that.selectionController.deselectIndex(index);
                    },
                    selectNode: function (node, tryMulti, suppressEvents) {
                        that.selectionController.selectNode(node, tryMulti, suppressEvents);
                    },
                    deselectNode: function (node) {
                        that.selectionController.deselectNode(node);
                    },
                    selectAll: function () {
                        that.selectionController.selectAll();
                        that.rowRenderer.refreshView();
                    },
                    deselectAll: function () {
                        that.selectionController.deselectAll();
                        that.rowRenderer.refreshView();
                    },
                    recomputeAggregates: function () {
                        that.inMemoryRowController.doAggregate();
                        that.rowRenderer.refreshGroupRows();
                    },
                    sizeColumnsToFit: function () {
                        if (that.gridOptionsWrapper.isDontUseScrolls()) {
                            console.warn('ag-grid: sizeColumnsToFit does not work when dontUseScrolls=true');
                            return;
                        }
                        var availableWidth = that.gridPanel.getWidthForSizeColsToFit();
                        that.columnController.sizeColumnsToFit(availableWidth);
                    },
                    showLoading: function (show) {
                        that.showLoadingPanel(show);
                    },
                    isNodeSelected: function (node) {
                        return that.selectionController.isNodeSelected(node);
                    },
                    getSelectedNodes: function () {
                        return that.selectionController.getSelectedNodes();
                    },
                    getBestCostNodeSelection: function () {
                        return that.selectionController.getBestCostNodeSelection();
                    },
                    ensureColIndexVisible: function (index) {
                        that.gridPanel.ensureColIndexVisible(index);
                    },
                    ensureIndexVisible: function (index) {
                        that.gridPanel.ensureIndexVisible(index);
                    },
                    ensureNodeVisible: function (comparator) {
                        that.ensureNodeVisible(comparator);
                    },
                    forEachInMemory: function (callback) {
                        that.rowModel.forEachInMemory(callback);
                    },
                    getFilterApiForColDef: function (colDef) {
                        console.warn('ag-grid API method getFilterApiForColDef deprecated, use getFilterApi instead');
                        return this.getFilterApi(colDef);
                    },
                    getFilterApi: function (key) {
                        var column = that.columnModel.getColumn(key);
                        return that.filterManager.getFilterApi(column);
                    },
                    getColumnDef: function (key) {
                        var column = that.columnModel.getColumn(key);
                        if (column) {
                            return column.colDef;
                        }
                        else {
                            return null;
                        }
                    },
                    onFilterChanged: function () {
                        that.onFilterChanged();
                    },
                    setSortModel: function (sortModel) {
                        that.setSortModel(sortModel);
                    },
                    getSortModel: function () {
                        return that.getSortModel();
                    },
                    setFilterModel: function (model) {
                        that.filterManager.setFilterModel(model);
                    },
                    getFilterModel: function () {
                        return that.getFilterModel();
                    },
                    getFocusedCell: function () {
                        return that.rowRenderer.getFocusedCell();
                    },
                    setFocusedCell: function (rowIndex, colIndex) {
                        that.setFocusedCell(rowIndex, colIndex);
                    },
                    showToolPanel: function (show) {
                        that.showToolPanel(show);
                    },
                    isToolPanelShowing: function () {
                        return that.isToolPanelShowing();
                    },
                    hideColumn: function (colId, hide) {
                        that.columnController.hideColumns([colId], hide);
                    },
                    hideColumns: function (colIds, hide) {
                        that.columnController.hideColumns(colIds, hide);
                    },
                    getColumnState: function () {
                        return that.columnController.getState();
                    },
                    setColumnState: function (state) {
                        that.columnController.setState(state);
                        that.inMemoryRowController.doGrouping();
                        that.inMemoryRowController.updateModel(constants.STEP_EVERYTHING);
                        that.refreshHeaderAndBody();
                    }
                };
                this.gridOptions.api = api;
            };
            Grid.prototype.setFocusedCell = function (rowIndex, colIndex) {
                this.gridPanel.ensureIndexVisible(rowIndex);
                this.gridPanel.ensureColIndexVisible(colIndex);
                var that = this;
                setTimeout(function () {
                    that.rowRenderer.setFocusedCell(rowIndex, colIndex);
                }, 10);
            };
            Grid.prototype.getSortModel = function () {
                var allColumns = this.columnModel.getAllColumns();
                var columnsWithSorting = [];
                var i;
                for (i = 0; i < allColumns.length; i++) {
                    if (allColumns[i].sort) {
                        columnsWithSorting.push(allColumns[i]);
                    }
                }
                columnsWithSorting.sort(function (a, b) {
                    return a.sortedAt - b.sortedAt;
                });
                var result = [];
                for (i = 0; i < columnsWithSorting.length; i++) {
                    var resultEntry = {
                        field: columnsWithSorting[i].colDef.field,
                        sort: columnsWithSorting[i].sort
                    };
                    result.push(resultEntry);
                }
                return result;
            };
            Grid.prototype.setSortModel = function (sortModel) {
                if (!this.gridOptionsWrapper.isEnableSorting()) {
                    console.warn('ag-grid: You are setting the sort model on a grid that does not have sorting enabled');
                    return;
                }
                // first up, clear any previous sort
                var sortModelProvided = sortModel !== null && sortModel !== undefined && sortModel.length > 0;
                var allColumns = this.columnModel.getAllColumns();
                for (var i = 0; i < allColumns.length; i++) {
                    var column = allColumns[i];
                    var sortForCol = null;
                    var sortedAt = -1;
                    if (sortModelProvided && !column.colDef.suppressSorting) {
                        for (var j = 0; j < sortModel.length; j++) {
                            var sortModelEntry = sortModel[j];
                            if (typeof sortModelEntry.field === 'string' && typeof column.colDef.field === 'string' && sortModelEntry.field === column.colDef.field) {
                                sortForCol = sortModelEntry.sort;
                                sortedAt = j;
                            }
                        }
                    }
                    if (sortForCol) {
                        column.sort = sortForCol;
                        column.sortedAt = sortedAt;
                    }
                    else {
                        column.sort = null;
                        column.sortedAt = null;
                    }
                }
                this.onSortingChanged();
            };
            Grid.prototype.onSortingChanged = function () {
                this.headerRenderer.updateSortIcons();
                if (this.gridOptionsWrapper.isEnableServerSideSorting()) {
                    // if doing server side sorting, changing the sort has the impact
                    // of resetting the datasource
                    this.setDatasource();
                }
                else {
                    // if doing in memory sorting, we just update the in memory data
                    this.updateModelAndRefresh(constants.STEP_SORT);
                }
            };
            Grid.prototype.addVirtualRowListener = function (rowIndex, callback) {
                if (!this.virtualRowCallbacks[rowIndex]) {
                    this.virtualRowCallbacks[rowIndex] = [];
                }
                this.virtualRowCallbacks[rowIndex].push(callback);
            };
            Grid.prototype.onVirtualRowSelected = function (rowIndex, selected) {
                // inform the callbacks of the event
                if (this.virtualRowCallbacks[rowIndex]) {
                    this.virtualRowCallbacks[rowIndex].forEach(function (callback) {
                        if (typeof callback.rowRemoved === 'function') {
                            callback.rowSelected(selected);
                        }
                    });
                }
            };
            Grid.prototype.onVirtualRowRemoved = function (rowIndex) {
                // inform the callbacks of the event
                if (this.virtualRowCallbacks[rowIndex]) {
                    this.virtualRowCallbacks[rowIndex].forEach(function (callback) {
                        if (typeof callback.rowRemoved === 'function') {
                            callback.rowRemoved();
                        }
                    });
                }
                // remove the callbacks
                delete this.virtualRowCallbacks[rowIndex];
            };
            Grid.prototype.onNewCols = function () {
                this.setupColumns();
                this.updateModelAndRefresh(constants.STEP_EVERYTHING);
            };
            Grid.prototype.updateBodyContainerWidthAfterColResize = function () {
                this.rowRenderer.setMainRowWidths();
                this.gridPanel.setBodyContainerWidth();
            };
            Grid.prototype.updatePinnedColContainerWidthAfterColResize = function () {
                this.gridPanel.setPinnedColContainerWidth();
            };
            Grid.prototype.doLayout = function () {
                // need to do layout first, as drawVirtualRows and setPinnedColHeight
                // need to know the result of the resizing of the panels.
                var sizeChanged = this.eRootPanel.doLayout();
                // both of the two below should be done in gridPanel, the gridPanel should register 'resize' to the panel
                if (sizeChanged) {
                    this.rowRenderer.drawVirtualRows();
                    this.gridPanel.setPinnedColHeight();
                }
            };
            return Grid;
        })();
        grid.Grid = Grid;
    })(grid = awk.grid || (awk.grid = {}));
})(awk || (awk = {}));
/// <reference path="grid.ts" />
(function () {
    // Establish the root object, `window` or `exports`
    var root = this;
    // if angular is present, register the directive
    if (typeof angular !== 'undefined') {
        var angularModule = angular.module("angularGrid", []);
        angularModule.directive("angularGrid", function () {
            return {
                restrict: "A",
                controller: ['$element', '$scope', '$compile', AngularDirectiveController],
                scope: {
                    angularGrid: "="
                }
            };
        });
        angularModule.directive("agGrid", function () {
            return {
                restrict: "A",
                controller: ['$element', '$scope', '$compile', '$attrs', AngularDirectiveController],
                scope: true
            };
        });
    }
    if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            exports = module.exports = angularGridGlobalFunction;
        }
        exports.angularGrid = angularGridGlobalFunction;
    }
    root.angularGrid = angularGridGlobalFunction;
    function AngularDirectiveController($element, $scope, $compile, $attrs) {
        var gridOptions;
        var quickFilterOnScope;
        if ($attrs) {
            // new directive of ag-grid
            var keyOfGridInScope = $attrs.agGrid;
            quickFilterOnScope = keyOfGridInScope + '.quickFilterText';
            gridOptions = $scope.$eval(keyOfGridInScope);
            if (!gridOptions) {
                console.warn("WARNING - grid options for Angular Grid not found. Please ensure the attribute ag-grid points to a valid object on the scope");
                return;
            }
        }
        else {
            // old directive of angular-grid
            console.warn("WARNING - Directive angular-grid is deprecated, you should use the ag-grid directive instead.");
            gridOptions = $scope.angularGrid;
            quickFilterOnScope = 'angularGrid.quickFilterText';
            if (!gridOptions) {
                console.warn("WARNING - grid options for Angular Grid not found. Please ensure the attribute angular-grid points to a valid object on the scope");
                return;
            }
        }
        var eGridDiv = $element[0];
        var grid = new awk.grid.Grid(eGridDiv, gridOptions, $scope, $compile, quickFilterOnScope);
        $scope.$on("$destroy", function () {
            grid.setFinished();
        });
    }
    // Global Function - this function is used for creating a grid, outside of any AngularJS
    function angularGridGlobalFunction(element, gridOptions) {
        // see if element is a query selector, or a real element
        var eGridDiv;
        if (typeof element === 'string') {
            eGridDiv = document.querySelector(element);
            if (!eGridDiv) {
                console.warn('WARNING - was not able to find element ' + element + ' in the DOM, Angular Grid initialisation aborted.');
                return;
            }
        }
        else {
            eGridDiv = element;
        }
        new awk.grid.Grid(eGridDiv, gridOptions, null, null, null);
    }
}).call(window);
.ag-root {
  font-size: 14px;
  cursor: default;
/* Set to relative, so absolute popups appear relative to this */
  position: relative;
/*disable user mouse selection */
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.ag-no-scrolls {
  white-space: nowrap;
  display: inline-block;
}
.ag-scrolls {
  height: 100%;
}
.ag-popup-backdrop {
  position: fixed;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
}
.ag-header {
  position: absolute;
  top: 0px;
  left: 0px;
  white-space: nowrap;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  overflow: hidden;
  width: 100%;
}
.ag-pinned-header {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  display: inline-block;
  overflow: hidden;
  height: 100%;
}
.ag-header-viewport {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  display: inline-block;
  overflow: hidden;
  height: 100%;
}
.ag-scrolls .ag-header-container {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  position: relative;
  white-space: nowrap;
  height: 100%;
}
.ag-no-scrolls .ag-header-container {
  white-space: nowrap;
}
.ag-header-cell {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  vertical-align: bottom;
  text-align: center;
  display: inline-block;
}
.ag-header-cell-grouped {
  height: 50%;
}
.ag-header-cell-not-grouped {
  height: 100%;
}
.ag-header-group {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  display: inline-block;
  height: 100%;
}
.ag-header-group-cell {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  text-align: center;
  height: 50%;
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
  overflow: hidden;
}
.ag-header-group-cell-label {
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
  overflow: hidden;
}
.ag-header-cell-label {
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
  overflow: hidden;
}
.ag-header-cell-resize {
  height: 100%;
  width: 4px;
  float: right;
  cursor: col-resize;
}
.ag-header-cell-menu-button {
  float: right;
}
.ag-loading-panel {
  display: table;
  width: 100%;
  height: 100%;
}
.ag-loading-wrapper {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}
.ag-body {
  height: 100%;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.ag-pinned-cols-viewport {
  float: left;
  position: absolute;
  overflow: hidden;
}
.ag-pinned-cols-container {
  display: inline-block;
  position: relative;
}
.ag-body-viewport-wrapper {
  height: 100%;
}
.ag-body-viewport {
  overflow: auto;
  height: 100%;
}
.ag-scrolls .ag-body-container {
  position: relative;
  display: inline-block;
}
.ag-scrolls .ag-row {
  white-space: nowrap;
  position: absolute;
  width: 100%;
}
.agile-gird-row:hover {
  background-color: #f0f8ff;
}
.ag-cell {
  display: inline-block;
  white-space: nowrap;
  height: 100%;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
  overflow: hidden;
  float: left;
}
.ag-group-cell-entire-row {
  width: 100%;
  display: inline-block;
  white-space: nowrap;
  height: 100%;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
  overflow: hidden;
}
.ag-footer-cell-entire-row {
  width: 100%;
  display: inline-block;
  white-space: nowrap;
  height: 100%;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
  overflow: hidden;
}
.ag-large .ag-root {
  font-size: 20px;
}
.ag-filter {
  position: absolute;
  z-index: 100;
}
.ag-filter-list-viewport {
  overflow-x: auto;
  height: 200px;
  width: 200px;
}
.ag-filter-list-container {
  position: relative;
  overflow: hidden;
}
.ag-filter-item {
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  position: absolute;
}
.ag-filter-filter {
  width: 170px;
  margin: 4px;
}
.ag-filter-select {
  width: 110px;
  margin: 4px 4px 0px 4px;
}
.ag-no-vertical-scroll .ag-scrolls {
  height: unset;
}
.ag-no-vertical-scroll .ag-body {
  height: unset;
}
.ag-no-vertical-scroll .ag-body-viewport-wrapper {
  height: unset;
}
.ag-no-vertical-scroll .ag-body-viewport {
  height: unset;
}
.ag-list-selection {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  cursor: default;
}
.ag-tool-panel-container {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  cursor: default;
  width: 200px;
}
.ag-fresh .ag-root {
  border: 1px solid #808080;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.ag-fresh .ag-cell {
  padding: 2px;
}
.ag-fresh .ag-cell-focus {
  border: 1px solid #a9a9a9;
}
.ag-fresh .ag-cell-no-focus {
  border-right: 1px dotted #808080;
  border-top: 1px solid transparent;
  border-left: 1px solid transparent;
  border-bottom: 1px solid transparent;
}
.ag-fresh .ag-pinned-header {
  background: -webkit-linear-gradient(#fff, #d3d3d3);
  background: -moz-linear-gradient(#fff, #d3d3d3);
  background: -o-linear-gradient(#fff, #d3d3d3);
  background: -ms-linear-gradient(#fff, #d3d3d3);
  background: linear-gradient(#fff, #d3d3d3);
  border-bottom: 1px solid #808080;
}
.ag-fresh .ag-header-container {
  background: -webkit-linear-gradient(#fff, #d3d3d3);
  background: -moz-linear-gradient(#fff, #d3d3d3);
  background: -o-linear-gradient(#fff, #d3d3d3);
  background: -ms-linear-gradient(#fff, #d3d3d3);
  background: linear-gradient(#fff, #d3d3d3);
  border-bottom: 1px solid #808080;
}
.ag-fresh .ag-header-cell {
  border-right: 1px solid #808080;
}
.ag-fresh .ag-header-group-cell {
  border-right: 1px solid #808080;
}
.ag-fresh .ag-header-group-cell-with-group {
  border-bottom: 1px solid #808080;
}
.ag-fresh .ag-header-cell-label {
  padding: 4px 2px 4px 2px;
}
.ag-fresh .ag-header-cell-text {
  padding-left: 2px;
}
.ag-fresh .ag-header-group-cell-label {
  padding: 4px;
  font-weight: bold;
}
.ag-fresh .ag-header-group-text {
  margin-right: 2px;
}
.ag-fresh .ag-header-cell-menu-button {
  padding: 2px;
  margin-top: 4px;
  border: 1px solid transparent;
  -webkit-border-radius: 3px;
  border-radius: 3px;
  -webkit-box-sizing: content-box;
  -moz-box-sizing: content-box;
  box-sizing: content-box; /* When using bootstrap, box-sizing was set to 'border-box' */
}
.ag-fresh .ag-header-cell-menu-button:hover {
  border: 1px solid #000;
}
.ag-fresh .ag-header-icon {
  color: #800000;
}
.ag-fresh .ag-dark .ag-header-expand-icon:hover {
  cursor: pointer;
}
.ag-fresh .ag-row-odd {
  background-color: #f6f6f6;
}
.ag-fresh .ag-row-even {
  background-color: #fff;
}
.ag-fresh .ag-loading-panel {
  background-color: rgba(255,255,255,0.5);
}
.ag-fresh .ag-loading-center {
  background-color: #fff;
  border: 1px solid #a9a9a9;
  -webkit-border-radius: 10px;
  border-radius: 10px;
  padding: 10px;
}
.ag-fresh .ag-body {
  background-color: #ddd;
}
.ag-fresh .ag-row-selected {
  background-color: #b0e0e6;
}
.ag-fresh .ag-group-cell-entire-row {
  background-color: #aaa;
  padding: 4px;
}
.ag-fresh .ag-footer-cell-entire-row {
  background-color: #aaa;
  padding: 4px;
}
.ag-fresh .ag-group-cell {
  font-style: italic;
}
.ag-fresh .ag-group-expand {
  padding-right: 2px;
}
.ag-fresh .ag-footer-cell {
  font-style: italic;
}
.ag-fresh .ag-filter-checkbox {
  position: relative;
  top: 2px;
  left: 2px;
}
.ag-fresh .ag-filter-header-container {
  border-bottom: 1px solid #d3d3d3;
}
.ag-fresh .ag-filter {
  border: 1px solid #000;
  background-color: #f0f0f0;
}
.ag-fresh .ag-filter-value {
  margin-left: 4px;
}
.ag-fresh .ag-selection-checkbox {
  margin-left: 4px;
}
.ag-fresh .ag-paging-panel {
  padding: 4px;
}
.ag-fresh .ag-paging-button {
  margin-left: 4px;
  margin-right: 4px;
}
.ag-fresh .ag-paging-row-summary-panel {
  display: inline-block;
  width: 300px;
}
.ag-fresh .ag-column-not-visible {
  opacity: 0.75;
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=75)";
  filter: alpha(opacity=75);
}
.ag-fresh .ag-not-dragging {
  border: 1px solid transparent;
}
.ag-fresh .ag-drop-target-above {
  border-top: 5px solid #a9a9a9;
}
.ag-fresh .ag-drop-target-below {
  border-bottom: 5px solid #a9a9a9;
}
.ag-fresh .ag-dragging {
  border: 1px dotted #a9a9a9;
}
.ag-fresh .ag-list-item-selected {
  color: #f0f0f0;
}
.ag-fresh .ag-list-item-not-selected {
  font-style: italic;
  color: #a0a0a0;
}
.ag-fresh .ag-tool-panel-container {
  background-color: #eee;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  border: 1px solid #a9a9a9;
  padding: 4px;
}
.ag-fresh .ag-list-selection {
  background-color: #fff;
  border: 1px solid #a9a9a9;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.ag-fresh .ag-popup-list .ag-list-item:hover {
  background-color: #add8e6;
}
.ag-fresh .ag-visible-icons {
  padding-left: 2px;
  padding-right: 2px;
}