myems/admin/js/plugins/nggrid/build/ng-grid.js

2982 lines
114 KiB
JavaScript

/***********************************************
* ng-grid JavaScript Library
* Authors: https://github.com/angular-ui/ng-grid/blob/master/README.md
* License: MIT (http://www.opensource.org/licenses/mit-license.php)
* Compiled At: 03/29/2013 17:16
***********************************************/
(function(window, $) {
'use strict';
var EXCESS_ROWS = 6;
var SCROLL_THRESHOLD = 4;
var ASC = "asc";
var DESC = "desc";
var NG_FIELD = '_ng_field_';
var NG_DEPTH = '_ng_depth_';
var NG_HIDDEN = '_ng_hidden_';
var NG_COLUMN = '_ng_column_';
var CUSTOM_FILTERS = /CUSTOM_FILTERS/g;
var COL_FIELD = /COL_FIELD/g;
var DISPLAY_CELL_TEMPLATE = /DISPLAY_CELL_TEMPLATE/g;
var EDITABLE_CELL_TEMPLATE = /EDITABLE_CELL_TEMPLATE/g;
var TEMPLATE_REGEXP = /<.+>/;
window.ngGrid = {};
window.ngGrid.i18n = {};
var ngGridServices = angular.module('ngGrid.services', []);
var ngGridDirectives = angular.module('ngGrid.directives', []);
var ngGridFilters = angular.module('ngGrid.filters', []);
angular.module('ngGrid', ['ngGrid.services', 'ngGrid.directives', 'ngGrid.filters']);
var ngMoveSelectionHandler = function($scope, elm, evt, grid) {
if ($scope.selectionProvider.selectedItems === undefined) {
return true;
}
var charCode = evt.which || evt.keyCode,
newColumnIndex,
lastInRow = false,
firstInRow = false,
rowIndex = $scope.selectionProvider.lastClickedRow.rowIndex,
visibleCols = $scope.columns.filter(function(c) { return c.visible; }),
pinnedCols = $scope.columns.filter(function(c) { return c.pinned; });
if ($scope.col) {
newColumnIndex = visibleCols.indexOf($scope.col);
}
if(charCode != 37 && charCode != 38 && charCode != 39 && charCode != 40 && charCode != 9 && charCode != 13){
return true;
}
if($scope.enableCellSelection){
if(charCode == 9){
evt.preventDefault();
}
var focusedOnFirstColumn = $scope.showSelectionCheckbox ? $scope.col.index == 1 : $scope.col.index == 0;
var focusedOnFirstVisibleColumns = $scope.$index == 1 || $scope.$index == 0;
var focusedOnLastVisibleColumns = $scope.$index == ($scope.renderedColumns.length - 1) || $scope.$index == ($scope.renderedColumns.length - 2);
var focusedOnLastColumn = visibleCols.indexOf($scope.col) == (visibleCols.length - 1);
var focusedOnLastPinnedColumn = pinnedCols.indexOf($scope.col) == (pinnedCols.length - 1);
if (charCode == 37 || charCode == 9 && evt.shiftKey) {
var scrollTo = 0;
if (!focusedOnFirstColumn) {
newColumnIndex -= 1;
}
if (focusedOnFirstVisibleColumns) {
if(focusedOnFirstColumn && charCode == 9 && evt.shiftKey){
scrollTo = grid.$canvas.width();
newColumnIndex = visibleCols.length - 1;
firstInRow = true;
} else {
scrollTo = grid.$viewport.scrollLeft() - $scope.col.width;
}
} else if (pinnedCols.length > 0) {
scrollTo = grid.$viewport.scrollLeft() - visibleCols[newColumnIndex].width;
}
grid.$viewport.scrollLeft(scrollTo);
} else if(charCode == 39 || charCode == 9 && !evt.shiftKey){
if (focusedOnLastVisibleColumns) {
if(focusedOnLastColumn && charCode == 9 && !evt.shiftKey){
grid.$viewport.scrollLeft(0);
newColumnIndex = $scope.showSelectionCheckbox ? 1 : 0;
lastInRow = true;
} else {
grid.$viewport.scrollLeft(grid.$viewport.scrollLeft() + $scope.col.width);
}
} else if (focusedOnLastPinnedColumn) {
grid.$viewport.scrollLeft(0);
}
if(!focusedOnLastColumn){
newColumnIndex += 1;
}
}
}
var items;
if ($scope.configGroups.length > 0) {
items = grid.rowFactory.parsedData.filter(function (row) {
return !row.isAggRow;
});
} else {
items = grid.filteredRows;
}
var offset = 0;
if(rowIndex != 0 && (charCode == 38 || charCode == 13 && evt.shiftKey || charCode == 9 && evt.shiftKey && firstInRow)){
offset = -1;
} else if(rowIndex != items.length - 1 && (charCode == 40 || charCode == 13 && !evt.shiftKey || charCode == 9 && lastInRow)){
offset = 1;
}
if (offset) {
var r = items[rowIndex + offset];
if (r.beforeSelectionChange(r, evt)) {
r.continueSelection(evt);
$scope.$emit('ngGridEventDigestGridParent');
if ($scope.selectionProvider.lastClickedRow.renderedRowIndex >= $scope.renderedRows.length - EXCESS_ROWS - 2) {
grid.$viewport.scrollTop(grid.$viewport.scrollTop() + $scope.rowHeight);
} else if ($scope.selectionProvider.lastClickedRow.renderedRowIndex <= EXCESS_ROWS + 2) {
grid.$viewport.scrollTop(grid.$viewport.scrollTop() - $scope.rowHeight);
}
}
}
if($scope.enableCellSelection){
setTimeout(function(){
$scope.domAccessProvider.focusCellElement($scope, $scope.renderedColumns.indexOf(visibleCols[newColumnIndex]));
},3);
}
return false;
};
if (!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
};
}
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(elt ) {
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0) ? Math.ceil(from) : Math.floor(from);
if (from < 0) {
from += len;
}
for (; from < len; from++) {
if (from in this && this[from] === elt) {
return from;
}
}
return -1;
};
}
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun ) {
"use strict";
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function") {
throw new TypeError();
}
var res = [];
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in t) {
var val = t[i];
if (fun.call(thisp, val, i, t)) {
res.push(val);
}
}
}
return res;
};
}
ngGridFilters.filter('checkmark', function() {
return function(input) {
return input ? '\u2714' : '\u2718';
};
});
ngGridFilters.filter('ngColumns', function() {
return function(input) {
return input.filter(function(col) {
return !col.isAggCol;
});
};
});
ngGridServices.factory('$domUtilityService',['$utilityService', function($utils) {
var domUtilityService = {};
var regexCache = {};
var getWidths = function() {
var $testContainer = $('<div></div>');
$testContainer.appendTo('body');
$testContainer.height(100).width(100).css("position", "absolute").css("overflow", "scroll");
$testContainer.append('<div style="height: 400px; width: 400px;"></div>');
domUtilityService.ScrollH = ($testContainer.height() - $testContainer[0].clientHeight);
domUtilityService.ScrollW = ($testContainer.width() - $testContainer[0].clientWidth);
$testContainer.empty();
$testContainer.attr('style', '');
$testContainer.append('<span style="font-family: Verdana, Helvetica, Sans-Serif; font-size: 14px;"><strong>M</strong></span>');
domUtilityService.LetterW = $testContainer.children().first().width();
$testContainer.remove();
};
domUtilityService.eventStorage = {};
domUtilityService.AssignGridContainers = function($scope, rootEl, grid) {
grid.$root = $(rootEl);
grid.$topPanel = grid.$root.find(".ngTopPanel");
grid.$groupPanel = grid.$root.find(".ngGroupPanel");
grid.$headerContainer = grid.$topPanel.find(".ngHeaderContainer");
$scope.$headerContainer = grid.$headerContainer;
grid.$headerScroller = grid.$topPanel.find(".ngHeaderScroller");
grid.$headers = grid.$headerScroller.children();
grid.$viewport = grid.$root.find(".ngViewport");
grid.$canvas = grid.$viewport.find(".ngCanvas");
grid.$footerPanel = grid.$root.find(".ngFooterPanel");
$scope.$watch(function () {
return grid.$viewport.scrollLeft();
}, function (newLeft) {
return grid.$headerContainer.scrollLeft(newLeft);
});
domUtilityService.UpdateGridLayout($scope, grid);
};
domUtilityService.getRealWidth = function (obj) {
var width = 0;
var props = { visibility: "hidden", display: "block" };
var hiddenParents = obj.parents().andSelf().not(':visible');
$.swap(hiddenParents[0], props, function () {
width = obj.outerWidth();
});
return width;
};
domUtilityService.UpdateGridLayout = function($scope, grid) {
var scrollTop = grid.$viewport.scrollTop();
grid.elementDims.rootMaxW = grid.$root.width();
if (grid.$root.is(':hidden')) {
grid.elementDims.rootMaxW = domUtilityService.getRealWidth(grid.$root);
}
grid.elementDims.rootMaxH = grid.$root.height();
grid.refreshDomSizes();
$scope.adjustScrollTop(scrollTop, true);
};
domUtilityService.numberOfGrids = 0;
domUtilityService.BuildStyles = function($scope, grid, digest) {
var rowHeight = grid.config.rowHeight,
$style = grid.$styleSheet,
gridId = grid.gridId,
css,
cols = $scope.columns,
sumWidth = 0;
if (!$style) {
$style = $('#' + gridId);
if (!$style[0]) {
$style = $("<style id='" + gridId + "' type='text/css' rel='stylesheet' />").appendTo(grid.$root);
}
}
$style.empty();
var trw = $scope.totalRowWidth();
css = "." + gridId + " .ngCanvas { width: " + trw + "px; }" +
"." + gridId + " .ngRow { width: " + trw + "px; }" +
"." + gridId + " .ngCanvas { width: " + trw + "px; }" +
"." + gridId + " .ngHeaderScroller { width: " + (trw + domUtilityService.ScrollH + 2) + "px}";
for (var i = 0; i < cols.length; i++) {
var col = cols[i];
if (col.visible !== false) {
var colLeft = col.pinned ? grid.$viewport.scrollLeft() + sumWidth : sumWidth;
css += "." + gridId + " .col" + i + " { width: " + col.width + "px; left: " + colLeft + "px; height: " + rowHeight + "px }" +
"." + gridId + " .colt" + i + " { width: " + col.width + "px; }";
sumWidth += col.width;
}
};
if ($utils.isIe) {
$style[0].styleSheet.cssText = css;
} else {
$style[0].appendChild(document.createTextNode(css));
}
grid.$styleSheet = $style;
if (digest) {
$scope.adjustScrollLeft(grid.$viewport.scrollLeft());
domUtilityService.digest($scope);
}
};
domUtilityService.setColLeft = function(col, colLeft, grid) {
if (grid.$styleSheet) {
var regex = regexCache[col.index];
if (!regex) {
regex = regexCache[col.index] = new RegExp("\.col" + col.index + " \{ width: [0-9]+px; left: [0-9]+px");
}
var str = grid.$styleSheet.html();
var newStr = str.replace(regex, "\.col" + col.index + " \{ width: " + col.width + "px; left: " + colLeft + "px");
if ($utils.isIe) {
setTimeout(function() {
grid.$styleSheet.html(newStr);
});
} else {
grid.$styleSheet.html(newStr);
}
}
};
domUtilityService.setColLeft.immediate = 1;
domUtilityService.RebuildGrid = function($scope, grid){
domUtilityService.UpdateGridLayout($scope, grid);
if (grid.config.maintainColumnRatios) {
grid.configureColumnWidths();
}
$scope.adjustScrollLeft(grid.$viewport.scrollLeft());
domUtilityService.BuildStyles($scope, grid, true);
};
domUtilityService.digest = function($scope) {
if (!$scope.$root.$$phase) {
$scope.$digest();
}
};
domUtilityService.ScrollH = 17;
domUtilityService.ScrollW = 17;
domUtilityService.LetterW = 10;
getWidths();
return domUtilityService;
}]);
ngGridServices.factory('$sortService', ['$parse', function($parse) {
var sortService = {};
sortService.colSortFnCache = {};
sortService.guessSortFn = function(item) {
var itemType = typeof(item);
switch (itemType) {
case "number":
return sortService.sortNumber;
case "boolean":
return sortService.sortBool;
case "string":
return item.match(/^-?[£$¤]?[\d,.]+%?$/) ? sortService.sortNumberStr : sortService.sortAlpha;
default:
if (Object.prototype.toString.call(item) === '[object Date]') {
return sortService.sortDate;
} else {
return sortService.basicSort;
}
}
};
sortService.basicSort = function(a, b) {
if (a == b) {
return 0;
}
if (a < b) {
return -1;
}
return 1;
};
sortService.sortNumber = function(a, b) {
return a - b;
};
sortService.sortNumberStr = function(a, b) {
var numA, numB, badA = false, badB = false;
numA = parseFloat(a.replace(/[^0-9.-]/g, ''));
if (isNaN(numA)) {
badA = true;
}
numB = parseFloat(b.replace(/[^0-9.-]/g, ''));
if (isNaN(numB)) {
badB = true;
}
if (badA && badB) {
return 0;
}
if (badA) {
return 1;
}
if (badB) {
return -1;
}
return numA - numB;
};
sortService.sortAlpha = function(a, b) {
var strA = a.toLowerCase(),
strB = b.toLowerCase();
return strA == strB ? 0 : (strA < strB ? -1 : 1);
};
sortService.sortDate = function(a, b) {
var timeA = a.getTime(),
timeB = b.getTime();
return timeA == timeB ? 0 : (timeA < timeB ? -1 : 1);
};
sortService.sortBool = function(a, b) {
if (a && b) {
return 0;
}
if (!a && !b) {
return 0;
} else {
return a ? 1 : -1;
}
};
sortService.sortData = function(sortInfo, data ) {
if (!data || !sortInfo) {
return;
}
var l = sortInfo.fields.length,
order = sortInfo.fields,
col,
direction,
d = data.slice(0);
data.sort(function (itemA, itemB) {
var tem = 0,
indx = 0,
sortFn;
while (tem == 0 && indx < l) {
col = sortInfo.columns[indx];
direction = sortInfo.directions[indx],
sortFn = sortService.getSortFn(col, d);
var propA = $parse(order[indx])(itemA);
var propB = $parse(order[indx])(itemB);
if ((!propA && propA != 0) || (!propB && propB != 0)) {
if (!propB && !propA) {
tem = 0;
} else if (!propA) {
tem = 1;
} else if (!propB) {
tem = -1;
}
} else {
tem = sortFn(propA, propB);
}
indx++;
}
if (direction === ASC) {
return tem;
} else {
return 0 - tem;
}
});
};
sortService.Sort = function(sortInfo, data) {
if (sortService.isSorting) {
return;
}
sortService.isSorting = true;
sortService.sortData(sortInfo, data);
sortService.isSorting = false;
};
sortService.getSortFn = function(col, data) {
var sortFn = undefined, item;
if (sortService.colSortFnCache[col.field]) {
sortFn = sortService.colSortFnCache[col.field];
} else if (col.sortingAlgorithm != undefined) {
sortFn = col.sortingAlgorithm;
sortService.colSortFnCache[col.field] = col.sortingAlgorithm;
} else {
item = data[0];
if (!item) {
return sortFn;
}
sortFn = sortService.guessSortFn($parse(col.field)(item));
if (sortFn) {
sortService.colSortFnCache[col.field] = sortFn;
} else {
sortFn = sortService.sortAlpha;
}
}
return sortFn;
};
return sortService;
}]);
ngGridServices.factory('$utilityService', ['$parse', function ($parse) {
var funcNameRegex = /function (.{1,})\(/;
var utils = {
visualLength: function(node) {
var elem = document.getElementById('testDataLength');
if (!elem) {
elem = document.createElement('SPAN');
elem.id = "testDataLength";
elem.style.visibility = "hidden";
document.body.appendChild(elem);
}
$(elem).css('font', $(node).css('font'));
elem.innerHTML = $(node).text();
return elem.offsetWidth;
},
forIn: function(obj, action) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
action(obj[prop], prop);
}
}
},
evalProperty: function (entity, path) {
return $parse(path)(entity);
},
endsWith: function(str, suffix) {
if (!str || !suffix || typeof str != "string") {
return false;
}
return str.indexOf(suffix, str.length - suffix.length) !== -1;
},
isNullOrUndefined: function(obj) {
if (obj === undefined || obj === null) {
return true;
}
return false;
},
getElementsByClassName: function(cl) {
var retnode = [];
var myclass = new RegExp('\\b' + cl + '\\b');
var elem = document.getElementsByTagName('*');
for (var i = 0; i < elem.length; i++) {
var classes = elem[i].className;
if (myclass.test(classes)) {
retnode.push(elem[i]);
}
}
return retnode;
},
newId: (function() {
var seedId = new Date().getTime();
return function() {
return seedId += 1;
};
})(),
seti18n: function($scope, language) {
var $langPack = window.ngGrid.i18n[language];
for (var label in $langPack) {
$scope.i18n[label] = $langPack[label];
}
},
getInstanceType: function (o) {
var results = (funcNameRegex).exec(o.constructor.toString());
return (results && results.length > 1) ? results[1] : "";
},
ieVersion: (function() {
var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
while (div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
iElems[0]) ;
return version > 4 ? version : undefined;
})()
};
$.extend(utils, {
isIe: (function() {
return utils.ieVersion !== undefined;
})()
});
return utils;
}]);
var ngAggregate = function (aggEntity, rowFactory, rowHeight) {
var self = this;
self.rowIndex = 0;
self.offsetTop = self.rowIndex * rowHeight;
self.entity = aggEntity;
self.label = aggEntity.gLabel;
self.field = aggEntity.gField;
self.depth = aggEntity.gDepth;
self.parent = aggEntity.parent;
self.children = aggEntity.children;
self.aggChildren = aggEntity.aggChildren;
self.aggIndex = aggEntity.aggIndex;
self.collapsed = true;
self.isAggRow = true;
self.offsetleft = aggEntity.gDepth * 25;
self.aggLabelFilter = aggEntity.aggLabelFilter;
self.toggleExpand = function() {
self.collapsed = self.collapsed ? false : true;
if (self.orig) {
self.orig.collapsed = self.collapsed;
}
self.notifyChildren();
};
self.setExpand = function(state) {
self.collapsed = state;
self.notifyChildren();
};
self.notifyChildren = function () {
var longest = Math.max(rowFactory.aggCache.length, self.children.length);
for (var i = 0; i < longest; i++) {
if (self.aggChildren[i]) {
self.aggChildren[i].entity[NG_HIDDEN] = self.collapsed;
if (self.collapsed) {
self.aggChildren[i].setExpand(self.collapsed);
}
}
if (self.children[i]) {
self.children[i][NG_HIDDEN] = self.collapsed;
}
if (i > self.aggIndex && rowFactory.aggCache[i]) {
var agg = rowFactory.aggCache[i];
var offset = (30 * self.children.length);
agg.offsetTop = self.collapsed ? agg.offsetTop - offset : agg.offsetTop + offset;
}
};
rowFactory.renderedChange();
};
self.aggClass = function() {
return self.collapsed ? "ngAggArrowCollapsed" : "ngAggArrowExpanded";
};
self.totalChildren = function() {
if (self.aggChildren.length > 0) {
var i = 0;
var recurse = function(cur) {
if (cur.aggChildren.length > 0) {
angular.forEach(cur.aggChildren, function(a) {
recurse(a);
});
} else {
i += cur.children.length;
}
};
recurse(self);
return i;
} else {
return self.children.length;
}
};
self.copy = function () {
var ret = new ngAggregate(self.entity, rowFactory, rowHeight);
ret.orig = self;
return ret;
};
};
var ngColumn = function (config, $scope, grid, domUtilityService, $templateCache, $utils) {
var self = this,
colDef = config.colDef,
delay = 500,
clicks = 0,
timer = null;
self.width = colDef.width;
self.groupIndex = 0;
self.isGroupedBy = false;
self.minWidth = !colDef.minWidth ? 50 : colDef.minWidth;
self.maxWidth = !colDef.maxWidth ? 9000 : colDef.maxWidth;
self.enableCellEdit = config.enableCellEdit || colDef.enableCellEdit;
self.headerRowHeight = config.headerRowHeight;
self.displayName = colDef.displayName || colDef.field;
self.index = config.index;
self.isAggCol = config.isAggCol;
self.cellClass = colDef.cellClass;
self.sortPriority = undefined;
self.cellFilter = colDef.cellFilter ? colDef.cellFilter : "";
self.field = colDef.field;
self.aggLabelFilter = colDef.cellFilter || colDef.aggLabelFilter;
self.visible = $utils.isNullOrUndefined(colDef.visible) || colDef.visible;
self.sortable = false;
self.resizable = false;
self.pinnable = false;
self.pinned = (config.enablePinning && colDef.pinned);
self.originalIndex = self.index;
self.groupable = $utils.isNullOrUndefined(colDef.groupable) || colDef.groupable;
if (config.enableSort) {
self.sortable = $utils.isNullOrUndefined(colDef.sortable) || colDef.sortable;
}
if (config.enableResize) {
self.resizable = $utils.isNullOrUndefined(colDef.resizable) || colDef.resizable;
}
if (config.enablePinning) {
self.pinnable = $utils.isNullOrUndefined(colDef.pinnable) || colDef.pinnable;
}
self.sortDirection = undefined;
self.sortingAlgorithm = colDef.sortFn;
self.headerClass = colDef.headerClass;
self.cursor = self.sortable ? 'pointer' : 'default';
self.headerCellTemplate = colDef.headerCellTemplate || $templateCache.get('headerCellTemplate.html');
self.cellTemplate = colDef.cellTemplate || $templateCache.get('cellTemplate.html').replace(CUSTOM_FILTERS, self.cellFilter ? "|" + self.cellFilter : "");
if(self.enableCellEdit) {
self.cellEditTemplate = $templateCache.get('cellEditTemplate.html');
self.editableCellTemplate = colDef.editableCellTemplate || $templateCache.get('editableCellTemplate.html');
}
if (colDef.cellTemplate && !TEMPLATE_REGEXP.test(colDef.cellTemplate)) {
self.cellTemplate = $.ajax({
type: "GET",
url: colDef.cellTemplate,
async: false
}).responseText;
}
if (self.enableCellEdit && colDef.editableCellTemplate && !TEMPLATE_REGEXP.test(colDef.editableCellTemplate)) {
self.editableCellTemplate = $.ajax({
type: "GET",
url: colDef.editableCellTemplate,
async: false
}).responseText;
}
if (colDef.headerCellTemplate && !TEMPLATE_REGEXP.test(colDef.headerCellTemplate)) {
self.headerCellTemplate = $.ajax({
type: "GET",
url: colDef.headerCellTemplate,
async: false
}).responseText;
}
self.colIndex = function () {
var classes = self.pinned ? "pinned " : "";
classes += "col" + self.index + " colt" + self.index;
return classes;
};
self.groupedByClass = function() {
return self.isGroupedBy ? "ngGroupedByIcon" : "ngGroupIcon";
};
self.toggleVisible = function() {
self.visible = !self.visible;
};
self.showSortButtonUp = function() {
return self.sortable ? self.sortDirection === DESC : self.sortable;
};
self.showSortButtonDown = function() {
return self.sortable ? self.sortDirection === ASC : self.sortable;
};
self.noSortVisible = function() {
return !self.sortDirection;
};
self.sort = function(evt) {
if (!self.sortable) {
return true;
}
var dir = self.sortDirection === ASC ? DESC : ASC;
self.sortDirection = dir;
config.sortCallback(self, evt);
return false;
};
self.gripClick = function() {
clicks++;
if (clicks === 1) {
timer = setTimeout(function() {
clicks = 0;
}, delay);
} else {
clearTimeout(timer);
config.resizeOnDataCallback(self);
clicks = 0;
}
};
self.gripOnMouseDown = function(event) {
if (event.ctrlKey && !self.pinned) {
self.toggleVisible();
domUtilityService.BuildStyles($scope, grid);
return true;
}
event.target.parentElement.style.cursor = 'col-resize';
self.startMousePosition = event.clientX;
self.origWidth = self.width;
$(document).mousemove(self.onMouseMove);
$(document).mouseup(self.gripOnMouseUp);
return false;
};
self.onMouseMove = function(event) {
var diff = event.clientX - self.startMousePosition;
var newWidth = diff + self.origWidth;
self.width = (newWidth < self.minWidth ? self.minWidth : (newWidth > self.maxWidth ? self.maxWidth : newWidth));
domUtilityService.BuildStyles($scope, grid);
return false;
};
self.gripOnMouseUp = function (event) {
$(document).off('mousemove', self.onMouseMove);
$(document).off('mouseup', self.gripOnMouseUp);
event.target.parentElement.style.cursor = 'default';
$scope.adjustScrollLeft(0);
domUtilityService.digest($scope);
return false;
};
self.copy = function() {
var ret = new ngColumn(config, $scope, grid, domUtilityService, $templateCache);
ret.isClone = true;
ret.orig = self;
return ret;
};
self.setVars = function (fromCol) {
self.orig = fromCol;
self.width = fromCol.width;
self.groupIndex = fromCol.groupIndex;
self.isGroupedBy = fromCol.isGroupedBy;
self.displayName = fromCol.displayName;
self.index = fromCol.index;
self.isAggCol = fromCol.isAggCol;
self.cellClass = fromCol.cellClass;
self.cellFilter = fromCol.cellFilter;
self.field = fromCol.field;
self.aggLabelFilter = fromCol.aggLabelFilter;
self.visible = fromCol.visible;
self.sortable = fromCol.sortable;
self.resizable = fromCol.resizable;
self.pinnable = fromCol.pinnable;
self.pinned = fromCol.pinned;
self.originalIndex = fromCol.originalIndex;
self.sortDirection = fromCol.sortDirection;
self.sortingAlgorithm = fromCol.sortingAlgorithm;
self.headerClass = fromCol.headerClass;
self.headerCellTemplate = fromCol.headerCellTemplate;
self.cellTemplate = fromCol.cellTemplate;
self.cellEditTemplate = fromCol.cellEditTemplate;
};
};
var ngDimension = function (options) {
this.outerHeight = null;
this.outerWidth = null;
$.extend(this, options);
};
var ngDomAccessProvider = function (grid) {
var self = this, previousColumn;
self.selectInputElement = function(elm){
var node = elm.nodeName.toLowerCase();
if(node == 'input' || node == 'textarea'){
elm.select();
}
};
self.focusCellElement = function($scope, index){
if($scope.selectionProvider.lastClickedRow){
var columnIndex = index != undefined ? index : previousColumn;
var elm = $scope.selectionProvider.lastClickedRow.clone ? $scope.selectionProvider.lastClickedRow.clone.elm : $scope.selectionProvider.lastClickedRow.elm;
if (columnIndex != undefined && elm) {
var columns = angular.element(elm[0].children).filter(function () { return this.nodeType != 8;});
var i = Math.max(Math.min($scope.renderedColumns.length - 1, columnIndex), 0);
if(grid.config.showSelectionCheckbox && angular.element(columns[i]).scope() && angular.element(columns[i]).scope().col.index == 0){
i = 1;
}
if (columns[i]) {
columns[i].children[0].focus();
}
previousColumn = columnIndex;
}
}
};
var changeUserSelect = function(elm, value) {
elm.css({
'-webkit-touch-callout': value,
'-webkit-user-select': value,
'-khtml-user-select': value,
'-moz-user-select': value == 'none'
? '-moz-none'
: value,
'-ms-user-select': value,
'user-select': value
});
};
self.selectionHandlers = function($scope, elm){
var doingKeyDown = false;
elm.bind('keydown', function(evt) {
if (evt.keyCode == 16) {
changeUserSelect(elm, 'none', evt);
return true;
} else if (!doingKeyDown) {
doingKeyDown = true;
var ret = ngMoveSelectionHandler($scope, elm, evt, grid);
doingKeyDown = false;
return ret;
}
return true;
});
elm.bind('keyup', function(evt) {
if (evt.keyCode == 16) {
changeUserSelect(elm, 'text', evt);
}
return true;
});
};
};
var ngEventProvider = function (grid, $scope, domUtilityService, $timeout) {
var self = this;
self.colToMove = undefined;
self.groupToMove = undefined;
self.assignEvents = function() {
if (grid.config.jqueryUIDraggable && !grid.config.enablePinning) {
grid.$groupPanel.droppable({
addClasses: false,
drop: function(event) {
self.onGroupDrop(event);
}
});
} else {
grid.$groupPanel.on('mousedown', self.onGroupMouseDown).on('dragover', self.dragOver).on('drop', self.onGroupDrop);
grid.$headerScroller.on('mousedown', self.onHeaderMouseDown).on('dragover', self.dragOver);
if (grid.config.enableColumnReordering && !grid.config.enablePinning) {
grid.$headerScroller.on('drop', self.onHeaderDrop);
}
if (grid.config.enableRowReordering) {
grid.$viewport.on('mousedown', self.onRowMouseDown).on('dragover', self.dragOver).on('drop', self.onRowDrop);
}
}
$scope.$watch('renderedColumns', function() {
$timeout(self.setDraggables);
});
};
self.dragStart = function(evt){
evt.dataTransfer.setData('text', '');
};
self.dragOver = function(evt) {
evt.preventDefault();
};
self.setDraggables = function() {
if (!grid.config.jqueryUIDraggable) {
var columns = grid.$root.find('.ngHeaderSortColumn');
angular.forEach(columns, function(col){
col.setAttribute('draggable', 'true');
if (col.addEventListener) {
col.addEventListener('dragstart', self.dragStart);
}
});
if (navigator.userAgent.indexOf("MSIE") != -1){
grid.$root.find('.ngHeaderSortColumn').bind('selectstart', function () {
this.dragDrop();
return false;
});
}
} else {
grid.$root.find('.ngHeaderSortColumn').draggable({
helper: 'clone',
appendTo: 'body',
stack: 'div',
addClasses: false,
start: function(event) {
self.onHeaderMouseDown(event);
}
}).droppable({
drop: function(event) {
self.onHeaderDrop(event);
}
});
}
};
self.onGroupMouseDown = function(event) {
var groupItem = $(event.target);
if (groupItem[0].className != 'ngRemoveGroup') {
var groupItemScope = angular.element(groupItem).scope();
if (groupItemScope) {
if (!grid.config.jqueryUIDraggable) {
groupItem.attr('draggable', 'true');
if(this.addEventListener){
this.addEventListener('dragstart', self.dragStart);
}
if (navigator.userAgent.indexOf("MSIE") != -1){
groupItem.bind('selectstart', function () {
this.dragDrop();
return false;
});
}
}
self.groupToMove = { header: groupItem, groupName: groupItemScope.group, index: groupItemScope.$index };
}
} else {
self.groupToMove = undefined;
}
};
self.onGroupDrop = function(event) {
event.stopPropagation();
var groupContainer;
var groupScope;
if (self.groupToMove) {
groupContainer = $(event.target).closest('.ngGroupElement');
if (groupContainer.context.className == 'ngGroupPanel') {
$scope.configGroups.splice(self.groupToMove.index, 1);
$scope.configGroups.push(self.groupToMove.groupName);
} else {
groupScope = angular.element(groupContainer).scope();
if (groupScope) {
if (self.groupToMove.index != groupScope.$index) {
$scope.configGroups.splice(self.groupToMove.index, 1);
$scope.configGroups.splice(groupScope.$index, 0, self.groupToMove.groupName);
}
}
}
self.groupToMove = undefined;
grid.fixGroupIndexes();
} else if (self.colToMove) {
if ($scope.configGroups.indexOf(self.colToMove.col) == -1) {
groupContainer = $(event.target).closest('.ngGroupElement');
if (groupContainer.context.className == 'ngGroupPanel' || groupContainer.context.className == 'ngGroupPanelDescription ng-binding') {
$scope.groupBy(self.colToMove.col);
} else {
groupScope = angular.element(groupContainer).scope();
if (groupScope) {
$scope.removeGroup(groupScope.$index);
}
}
}
self.colToMove = undefined;
}
if (!$scope.$$phase) {
$scope.$apply();
}
};
self.onHeaderMouseDown = function(event) {
var headerContainer = $(event.target).closest('.ngHeaderSortColumn');
var headerScope = angular.element(headerContainer).scope();
if (headerScope) {
self.colToMove = { header: headerContainer, col: headerScope.col };
}
};
self.onHeaderDrop = function(event) {
if (!self.colToMove || self.colToMove.col.pinned) {
return;
}
var headerContainer = $(event.target).closest('.ngHeaderSortColumn');
var headerScope = angular.element(headerContainer).scope();
if (headerScope) {
if (self.colToMove.col == headerScope.col) {
return;
}
$scope.columns.splice(self.colToMove.col.index, 1);
$scope.columns.splice(headerScope.col.index, 0, self.colToMove.col);
grid.fixColumnIndexes();
domUtilityService.BuildStyles($scope, grid, true);
self.colToMove = undefined;
}
};
self.onRowMouseDown = function(event) {
var targetRow = $(event.target).closest('.ngRow');
var rowScope = angular.element(targetRow).scope();
if (rowScope) {
targetRow.attr('draggable', 'true');
domUtilityService.eventStorage.rowToMove = { targetRow: targetRow, scope: rowScope };
}
};
self.onRowDrop = function(event) {
var targetRow = $(event.target).closest('.ngRow');
var rowScope = angular.element(targetRow).scope();
if (rowScope) {
var prevRow = domUtilityService.eventStorage.rowToMove;
if (prevRow.scope.row == rowScope.row) {
return;
}
grid.changeRowOrder(prevRow.scope.row, rowScope.row);
grid.searchProvider.evalFilter();
domUtilityService.eventStorage.rowToMove = undefined;
domUtilityService.digest(rowScope.$root);
}
};
self.assignGridEventHandlers = function() {
if (grid.config.tabIndex === -1) {
grid.$viewport.attr('tabIndex', domUtilityService.numberOfGrids);
domUtilityService.numberOfGrids++;
} else {
grid.$viewport.attr('tabIndex', grid.config.tabIndex);
}
$(window).resize(function() {
domUtilityService.RebuildGrid($scope,grid);
});
$(grid.$root.parent()).on('resize', function() {
domUtilityService.RebuildGrid($scope, grid);
});
};
self.assignGridEventHandlers();
self.assignEvents();
};
var ngFooter = function ($scope, grid) {
$scope.maxRows = function () {
var ret = Math.max($scope.pagingOptions.totalServerItems, grid.data.length);
return ret;
};
$scope.multiSelect = (grid.config.enableRowSelection && grid.config.multiSelect);
$scope.selectedItemCount = grid.selectedItemCount;
$scope.maxPages = function () {
return Math.ceil($scope.maxRows() / $scope.pagingOptions.pageSize);
};
$scope.pageForward = function() {
var page = $scope.pagingOptions.currentPage;
if ($scope.pagingOptions.totalServerItems > 0) {
$scope.pagingOptions.currentPage = Math.min(page + 1, $scope.maxPages());
} else {
$scope.pagingOptions.currentPage++;
}
};
$scope.pageBackward = function() {
var page = $scope.pagingOptions.currentPage;
$scope.pagingOptions.currentPage = Math.max(page - 1, 1);
};
$scope.pageToFirst = function() {
$scope.pagingOptions.currentPage = 1;
};
$scope.pageToLast = function() {
var maxPages = $scope.maxPages();
$scope.pagingOptions.currentPage = maxPages;
};
$scope.cantPageForward = function() {
var curPage = $scope.pagingOptions.currentPage;
var maxPages = $scope.maxPages();
if ($scope.pagingOptions.totalServerItems > 0) {
return !(curPage < maxPages);
} else {
return grid.data.length < 1;
}
};
$scope.cantPageToLast = function() {
if ($scope.pagingOptions.totalServerItems > 0) {
return $scope.cantPageForward();
} else {
return true;
}
};
$scope.cantPageBackward = function() {
var curPage = $scope.pagingOptions.currentPage;
return !(curPage > 1);
};
};
var ngGrid = function ($scope, options, sortService, domUtilityService, $filter, $templateCache, $utils, $timeout, $parse) {
var defaults = {
aggregateTemplate: undefined,
afterSelectionChange: function() {
},
beforeSelectionChange: function() {
return true;
},
checkboxCellTemplate: undefined,
checkboxHeaderTemplate: undefined,
columnDefs: undefined,
data: [],
dataUpdated: function() {
},
enableCellEdit: false,
enableCellSelection: false,
enableColumnResize: false,
enableColumnReordering: false,
enableColumnHeavyVirt: false,
enablePaging: false,
enablePinning: false,
enableRowReordering: false,
enableRowSelection: true,
enableSorting: true,
enableHighlighting: false,
excludeProperties: [],
filterOptions: {
filterText: "",
useExternalFilter: false
},
footerRowHeight: 55,
footerTemplate: undefined,
groups: [],
headerRowHeight: 30,
headerRowTemplate: undefined,
jqueryUIDraggable: false,
jqueryUITheme: false,
keepLastSelected: true,
maintainColumnRatios: undefined,
menuTemplate: undefined,
multiSelect: true,
pagingOptions: {
pageSizes: [250, 500, 1000],
pageSize: 250,
totalServerItems: 0,
currentPage: 1
},
pinSelectionCheckbox: false,
plugins: [],
primaryKey: undefined,
rowHeight: 30,
rowTemplate: undefined,
selectedItems: [],
selectWithCheckboxOnly: false,
showColumnMenu: false,
showFilter: false,
showFooter: false,
showGroupPanel: false,
showSelectionCheckbox: false,
sortInfo: {fields: [], columns: [], directions: [] },
tabIndex: -1,
useExternalSorting: false,
i18n: 'en',
virtualizationThreshold: 50
},
self = this;
self.maxCanvasHt = 0;
self.config = $.extend(defaults, window.ngGrid.config, options);
self.config.showSelectionCheckbox = (self.config.showSelectionCheckbox && self.config.enableColumnHeavyVirt === false);
self.config.enablePinning = (self.config.enablePinning && self.config.enableColumnHeavyVirt === false);
self.config.selectWithCheckboxOnly = (self.config.selectWithCheckboxOnly && self.config.showSelectionCheckbox !== false);
self.config.pinSelectionCheckbox = self.config.enablePinning;
if (typeof options.columnDefs == "string") {
self.config.columnDefs = $scope.$eval(options.columnDefs);
}
self.rowCache = [];
self.rowMap = [];
self.gridId = "ng" + $utils.newId();
self.$root = null;
self.$groupPanel = null;
self.$topPanel = null;
self.$headerContainer = null;
self.$headerScroller = null;
self.$headers = null;
self.$viewport = null;
self.$canvas = null;
self.rootDim = self.config.gridDim;
self.data = [];
self.lateBindColumns = false;
self.filteredRows = [];
var getTemplate = function (key) {
var t = self.config[key];
var uKey = self.gridId + key + ".html";
if (t && !TEMPLATE_REGEXP.test(t)) {
$templateCache.put(uKey, $.ajax({
type: "GET",
url: t,
async: false
}).responseText);
} else if (t) {
$templateCache.put(uKey, t);
} else {
var dKey = key + ".html";
$templateCache.put(uKey, $templateCache.get(dKey));
}
};
getTemplate('rowTemplate');
getTemplate('aggregateTemplate');
getTemplate('headerRowTemplate');
getTemplate('checkboxCellTemplate');
getTemplate('checkboxHeaderTemplate');
getTemplate('menuTemplate');
getTemplate('footerTemplate');
if (typeof self.config.data == "object") {
self.data = self.config.data;
}
self.calcMaxCanvasHeight = function() {
return (self.config.groups.length > 0) ? (self.rowFactory.parsedData.filter(function(e) {
return !e[NG_HIDDEN];
}).length * self.config.rowHeight) : (self.filteredRows.length * self.config.rowHeight);
};
self.elementDims = {
scrollW: 0,
scrollH: 0,
rowIndexCellW: 25,
rowSelectedCellW: 25,
rootMaxW: 0,
rootMaxH: 0
};
self.setRenderedRows = function (newRows) {
$scope.renderedRows.length = newRows.length;
for (var i = 0; i < newRows.length; i++) {
if (!$scope.renderedRows[i] || (newRows[i].isAggRow || $scope.renderedRows[i].isAggRow)) {
$scope.renderedRows[i] = newRows[i].copy();
$scope.renderedRows[i].collapsed = newRows[i].collapsed;
if (!newRows[i].isAggRow) {
$scope.renderedRows[i].setVars(newRows[i]);
}
} else {
$scope.renderedRows[i].setVars(newRows[i]);
}
$scope.renderedRows[i].rowIndex = newRows[i].rowIndex;
$scope.renderedRows[i].offsetTop = newRows[i].offsetTop;
newRows[i].renderedRowIndex = i;
}
self.refreshDomSizes();
$scope.$emit('ngGridEventRows', newRows);
};
self.minRowsToRender = function() {
var viewportH = $scope.viewportDimHeight() || 1;
return Math.floor(viewportH / self.config.rowHeight);
};
self.refreshDomSizes = function() {
var dim = new ngDimension();
dim.outerWidth = self.elementDims.rootMaxW;
dim.outerHeight = self.elementDims.rootMaxH;
self.rootDim = dim;
self.maxCanvasHt = self.calcMaxCanvasHeight();
};
self.buildColumnDefsFromData = function () {
self.config.columnDefs = [];
var item = self.data[0];
if (!item) {
self.lateBoundColumns = true;
return;
}
$utils.forIn(item, function (prop, propName) {
if (self.config.excludeProperties.indexOf(propName) == -1) {
self.config.columnDefs.push({
field: propName
});
}
});
};
self.buildColumns = function() {
var columnDefs = self.config.columnDefs,
cols = [];
if (!columnDefs) {
self.buildColumnDefsFromData();
columnDefs = self.config.columnDefs;
}
if (self.config.showSelectionCheckbox) {
cols.push(new ngColumn({
colDef: {
field: '\u2714',
width: self.elementDims.rowSelectedCellW,
sortable: false,
resizable: false,
groupable: false,
headerCellTemplate: $templateCache.get($scope.gridId + 'checkboxHeaderTemplate.html'),
cellTemplate: $templateCache.get($scope.gridId + 'checkboxCellTemplate.html'),
pinned: self.config.pinSelectionCheckbox
},
index: 0,
headerRowHeight: self.config.headerRowHeight,
sortCallback: self.sortData,
resizeOnDataCallback: self.resizeOnData,
enableResize: self.config.enableColumnResize,
enableSort: self.config.enableSorting
}, $scope, self, domUtilityService, $templateCache, $utils));
}
if (columnDefs.length > 0) {
var indexOffset = self.config.showSelectionCheckbox ? self.config.groups.length + 1 : self.config.groups.length;
$scope.configGroups.length = 0;
angular.forEach(columnDefs, function(colDef, i) {
i += indexOffset;
var column = new ngColumn({
colDef: colDef,
index: i,
headerRowHeight: self.config.headerRowHeight,
sortCallback: self.sortData,
resizeOnDataCallback: self.resizeOnData,
enableResize: self.config.enableColumnResize,
enableSort: self.config.enableSorting,
enablePinning: self.config.enablePinning,
enableCellEdit: self.config.enableCellEdit
}, $scope, self, domUtilityService, $templateCache, $utils);
var indx = self.config.groups.indexOf(colDef.field);
if (indx != -1) {
column.isGroupedBy = true;
$scope.configGroups.splice(indx, 0, column);
column.groupIndex = $scope.configGroups.length;
}
cols.push(column);
});
$scope.columns = cols;
}
};
self.configureColumnWidths = function() {
var cols = self.config.columnDefs;
var indexOffset = self.config.showSelectionCheckbox ? $scope.configGroups.length + 1 : $scope.configGroups.length;
var numOfCols = cols.length + indexOffset,
asterisksArray = [],
percentArray = [],
asteriskNum = 0,
totalWidth = 0;
totalWidth += self.config.showSelectionCheckbox ? 25 : 0;
angular.forEach(cols, function(col, i) {
i += indexOffset;
var isPercent = false, t = undefined;
if ($utils.isNullOrUndefined(col.width)) {
col.width = "*";
} else {
isPercent = isNaN(col.width) ? $utils.endsWith(col.width, "%") : false;
t = isPercent ? col.width : parseInt(col.width, 10);
}
if (isNaN(t)) {
t = col.width;
if (t == 'auto') {
$scope.columns[i].width = col.minWidth;
totalWidth += $scope.columns[i].width;
var temp = $scope.columns[i];
$timeout(function () {
self.resizeOnData(temp, true);
});
return;
} else if (t.indexOf("*") != -1) {
if (col.visible !== false) {
asteriskNum += t.length;
}
col.index = i;
asterisksArray.push(col);
return;
} else if (isPercent) {
col.index = i;
percentArray.push(col);
return;
} else {
throw "unable to parse column width, use percentage (\"10%\",\"20%\", etc...) or \"*\" to use remaining width of grid";
}
} else if (col.visible !== false) {
totalWidth += $scope.columns[i].width = parseInt(col.width, 10);
}
});
if (asterisksArray.length > 0) {
self.config.maintainColumnRatios === false ? angular.noop() : self.config.maintainColumnRatios = true;
var remainigWidth = self.rootDim.outerWidth - totalWidth;
var asteriskVal = Math.floor(remainigWidth / asteriskNum);
angular.forEach(asterisksArray, function(col) {
var t = col.width.length;
$scope.columns[col.index].width = asteriskVal * t;
if (col.index + 1 == numOfCols) {
var offset = 2;
if (self.maxCanvasHt > $scope.viewportDimHeight()) {
offset += domUtilityService.ScrollW;
}
$scope.columns[col.index].width -= offset;
}
if (col.visible !== false) {
totalWidth += $scope.columns[col.index].width;
}
});
}
if (percentArray.length > 0) {
angular.forEach(percentArray, function(col) {
var t = col.width;
$scope.columns[col.index].width = Math.floor(self.rootDim.outerWidth * (parseInt(t.slice(0, -1), 10) / 100));
});
}
};
self.init = function() {
$scope.selectionProvider = new ngSelectionProvider(self, $scope, $parse);
$scope.domAccessProvider = new ngDomAccessProvider(self);
self.rowFactory = new ngRowFactory(self, $scope, domUtilityService, $templateCache, $utils);
self.searchProvider = new ngSearchProvider($scope, self, $filter);
self.styleProvider = new ngStyleProvider($scope, self, domUtilityService);
$scope.$watch('configGroups', function(a) {
var tempArr = [];
angular.forEach(a, function(item) {
tempArr.push(item.field || item);
});
self.config.groups = tempArr;
self.rowFactory.filteredRowsChanged();
$scope.$emit('ngGridEventGroups', a);
}, true);
$scope.$watch('columns', function (a) {
domUtilityService.BuildStyles($scope, self, true);
$scope.$emit('ngGridEventColumns', a);
}, true);
$scope.$watch(function() {
return options.i18n;
}, function(newLang) {
$utils.seti18n($scope, newLang);
});
self.maxCanvasHt = self.calcMaxCanvasHeight();
if (self.config.sortInfo.fields && self.config.sortInfo.fields.length > 0) {
self.getColsFromFields();
self.sortActual();
}
};
self.resizeOnData = function(col) {
var longest = col.minWidth;
var arr = $utils.getElementsByClassName('col' + col.index);
angular.forEach(arr, function(elem, index) {
var i;
if (index === 0) {
var kgHeaderText = $(elem).find('.ngHeaderText');
i = $utils.visualLength(kgHeaderText) + 10;
} else {
var ngCellText = $(elem).find('.ngCellText');
i = $utils.visualLength(ngCellText) + 10;
}
if (i > longest) {
longest = i;
}
});
col.width = col.longest = Math.min(col.maxWidth, longest + 7);
domUtilityService.BuildStyles($scope, self, true);
};
self.lastSortedColumns = [];
self.changeRowOrder = function(prevRow, targetRow) {
var i = self.rowCache.indexOf(prevRow);
var j = self.rowCache.indexOf(targetRow);
self.rowCache.splice(i, 1);
self.rowCache.splice(j, 0, prevRow);
$scope.$emit('ngGridEventChangeOrder', self.rowCache);
};
self.sortData = function(col, evt) {
if (evt.shiftKey && self.config.sortInfo) {
var indx = self.config.sortInfo.columns.indexOf(col);
if (indx === -1) {
if (self.config.sortInfo.columns.length == 1) {
self.config.sortInfo.columns[0].sortPriority = 1;
}
self.config.sortInfo.columns.push(col);
col.sortPriority = self.config.sortInfo.columns.length;
self.config.sortInfo.fields.push(col.field);
self.config.sortInfo.directions.push(col.sortDirection);
self.lastSortedColumns.push(col);
} else {
self.config.sortInfo.directions[indx] = col.sortDirection;
}
} else {
var isArr = $.isArray(col);
self.config.sortInfo.columns.length = 0;
self.config.sortInfo.fields.length = 0;
self.config.sortInfo.directions.length = 0;
var push = function (c) {
self.config.sortInfo.columns.push(c);
self.config.sortInfo.fields.push(c.field);
self.config.sortInfo.directions.push(c.sortDirection);
self.lastSortedColumns.push(c);
};
if (isArr) {
self.clearSortingData();
angular.forEach(col, function (c, i) {
c.sortPriority = i + 1;
push(c);
});
} else {
self.clearSortingData(col);
col.sortPriority = undefined;
push(col);
}
}
self.sortActual();
self.searchProvider.evalFilter();
$scope.$emit('ngGridEventSorted', self.config.sortInfo);
};
self.getColsFromFields = function() {
if (self.config.sortInfo.columns) {
self.config.sortInfo.columns.length = 0;
} else {
self.config.sortInfo.columns = [];
}
angular.forEach($scope.columns, function(c) {
var i = self.config.sortInfo.fields.indexOf(c.field);
if (i != -1) {
c.sortDirection = self.config.sortInfo.directions[i] || 'asc';
self.config.sortInfo.columns.push(c);
}
return false;
});
};
self.sortActual = function() {
if (!self.config.useExternalSorting) {
var tempData = self.data.slice(0);
angular.forEach(tempData, function(item, i) {
item.preSortSelected = self.rowCache[self.rowMap[i]].selected;
item.preSortIndex = i;
});
sortService.Sort(self.config.sortInfo, tempData);
angular.forEach(tempData, function(item, i) {
self.rowCache[i].entity = item;
self.rowCache[i].selected = item.preSortSelected;
self.rowMap[item.preSortIndex] = i;
delete item.preSortSelected;
delete item.preSortIndex;
});
}
};
self.clearSortingData = function (col) {
if (!col) {
angular.forEach(self.lastSortedColumns, function (c) {
c.sortDirection = "";
c.sortPriority = null;
});
self.lastSortedColumns = [];
} else {
angular.forEach(self.lastSortedColumns, function (c) {
if (col.index != c.index) {
c.sortDirection = "";
c.sortPriority = null;
}
});
self.lastSortedColumns[0] = col;
self.lastSortedColumns.length = 1;
};
};
self.fixColumnIndexes = function() {
for (var i = 0; i < $scope.columns.length; i++) {
if ($scope.columns[i].visible !== false) {
$scope.columns[i].index = i;
}
}
};
self.fixGroupIndexes = function() {
angular.forEach($scope.configGroups, function(item, i) {
item.groupIndex = i + 1;
});
};
$scope.elementsNeedMeasuring = true;
$scope.columns = [];
$scope.renderedRows = [];
$scope.renderedColumns = [];
$scope.headerRow = null;
$scope.rowHeight = self.config.rowHeight;
$scope.jqueryUITheme = self.config.jqueryUITheme;
$scope.showSelectionCheckbox = self.config.showSelectionCheckbox;
$scope.enableCellSelection = self.config.enableCellSelection;
$scope.footer = null;
$scope.selectedItems = self.config.selectedItems;
$scope.multiSelect = self.config.multiSelect;
$scope.showFooter = self.config.showFooter;
$scope.footerRowHeight = $scope.showFooter ? self.config.footerRowHeight : 0;
$scope.showColumnMenu = self.config.showColumnMenu;
$scope.showMenu = false;
$scope.configGroups = [];
$scope.gridId = self.gridId;
$scope.enablePaging = self.config.enablePaging;
$scope.pagingOptions = self.config.pagingOptions;
$scope.i18n = {};
$utils.seti18n($scope, self.config.i18n);
$scope.adjustScrollLeft = function (scrollLeft) {
var colwidths = 0,
totalLeft = 0,
x = $scope.columns.length,
newCols = [],
dcv = !self.config.enableColumnHeavyVirt;
var r = 0;
var addCol = function (c) {
if (dcv) {
newCols.push(c);
} else {
if (!$scope.renderedColumns[r]) {
$scope.renderedColumns[r] = c.copy();
} else {
$scope.renderedColumns[r].setVars(c);
}
}
r++;
};
for (var i = 0; i < x; i++) {
var col = $scope.columns[i];
if (col.visible !== false) {
var w = col.width + colwidths;
if (col.pinned) {
addCol(col);
var newLeft = i > 0 ? (scrollLeft + totalLeft) : scrollLeft;
domUtilityService.setColLeft(col, newLeft, self);
totalLeft += col.width;
} else {
if (w >= scrollLeft) {
if (colwidths <= scrollLeft + self.rootDim.outerWidth) {
addCol(col);
}
}
}
colwidths += col.width;
}
}
if (dcv) {
$scope.renderedColumns = newCols;
}
};
self.prevScrollTop = 0;
self.prevScrollIndex = 0;
$scope.adjustScrollTop = function(scrollTop, force) {
if (self.prevScrollTop === scrollTop && !force) {
return;
}
if (scrollTop > 0 && self.$viewport[0].scrollHeight - scrollTop <= self.$viewport.outerHeight()) {
$scope.$emit('ngGridEventScroll');
}
var rowIndex = Math.floor(scrollTop / self.config.rowHeight);
var newRange;
if (self.filteredRows.length > self.config.virtualizationThreshold) {
if (self.prevScrollTop < scrollTop && rowIndex < self.prevScrollIndex + SCROLL_THRESHOLD) {
return;
}
if (self.prevScrollTop > scrollTop && rowIndex > self.prevScrollIndex - SCROLL_THRESHOLD) {
return;
}
newRange = new ngRange(Math.max(0, rowIndex - EXCESS_ROWS), rowIndex + self.minRowsToRender() + EXCESS_ROWS);
} else {
var maxLen = $scope.configGroups.length > 0 ? self.rowFactory.parsedData.length : self.data.length;
newRange = new ngRange(0, Math.max(maxLen, self.minRowsToRender() + EXCESS_ROWS));
}
self.prevScrollTop = scrollTop;
self.rowFactory.UpdateViewableRange(newRange);
self.prevScrollIndex = rowIndex;
};
$scope.toggleShowMenu = function() {
$scope.showMenu = !$scope.showMenu;
};
$scope.toggleSelectAll = function(a) {
$scope.selectionProvider.toggleSelectAll(a);
};
$scope.totalFilteredItemsLength = function() {
return self.filteredRows.length;
};
$scope.showGroupPanel = function() {
return self.config.showGroupPanel;
};
$scope.topPanelHeight = function() {
return self.config.showGroupPanel === true ? self.config.headerRowHeight + 32 : self.config.headerRowHeight;
};
$scope.viewportDimHeight = function() {
return Math.max(0, self.rootDim.outerHeight - $scope.topPanelHeight() - $scope.footerRowHeight - 2);
};
$scope.groupBy = function (col) {
if (self.data.length < 1 || !col.groupable || !col.field) {
return;
}
if (!col.sortDirection) col.sort({ shiftKey: false });
var indx = $scope.configGroups.indexOf(col);
if (indx == -1) {
col.isGroupedBy = true;
$scope.configGroups.push(col);
col.groupIndex = $scope.configGroups.length;
} else {
$scope.removeGroup(indx);
}
self.$viewport.scrollTop(0);
domUtilityService.digest($scope);
};
$scope.removeGroup = function(index) {
var col = $scope.columns.filter(function(item) {
return item.groupIndex == (index + 1);
})[0];
col.isGroupedBy = false;
col.groupIndex = 0;
if ($scope.columns[index].isAggCol) {
$scope.columns.splice(index, 1);
$scope.configGroups.splice(index, 1);
self.fixGroupIndexes();
}
if ($scope.configGroups.length === 0) {
self.fixColumnIndexes();
domUtilityService.digest($scope);
}
$scope.adjustScrollLeft(0);
};
$scope.togglePin = function (col) {
var indexFrom = col.index;
var indexTo = 0;
for (var i = 0; i < $scope.columns.length; i++) {
if (!$scope.columns[i].pinned) {
break;
}
indexTo++;
}
if (col.pinned) {
indexTo = Math.max(col.originalIndex, indexTo - 1);
}
col.pinned = !col.pinned;
$scope.columns.splice(indexFrom, 1);
$scope.columns.splice(indexTo, 0, col);
self.fixColumnIndexes();
domUtilityService.BuildStyles($scope, self, true);
self.$viewport.scrollLeft(self.$viewport.scrollLeft() - col.width);
};
$scope.totalRowWidth = function() {
var totalWidth = 0,
cols = $scope.columns;
for (var i = 0; i < cols.length; i++) {
if (cols[i].visible !== false) {
totalWidth += cols[i].width;
}
}
return totalWidth;
};
$scope.headerScrollerDim = function() {
var viewportH = $scope.viewportDimHeight(),
maxHeight = self.maxCanvasHt,
vScrollBarIsOpen = (maxHeight > viewportH),
newDim = new ngDimension();
newDim.autoFitHeight = true;
newDim.outerWidth = $scope.totalRowWidth();
if (vScrollBarIsOpen) {
newDim.outerWidth += self.elementDims.scrollW;
} else if ((maxHeight - viewportH) <= self.elementDims.scrollH) {
newDim.outerWidth += self.elementDims.scrollW;
}
return newDim;
};
self.init();
};
var ngRange = function (top, bottom) {
this.topRow = top;
this.bottomRow = bottom;
};
var ngRow = function (entity, config, selectionProvider, rowIndex, $utils) {
var self = this,
enableRowSelection = config.enableRowSelection;
self.jqueryUITheme = config.jqueryUITheme;
self.rowClasses = config.rowClasses;
self.entity = entity;
self.selectionProvider = selectionProvider;
self.selected = selectionProvider.getSelection(entity);
self.cursor = enableRowSelection ? 'pointer' : 'default';
self.setSelection = function(isSelected) {
self.selectionProvider.setSelection(self, isSelected);
self.selectionProvider.lastClickedRow = self;
};
self.continueSelection = function(event) {
self.selectionProvider.ChangeSelection(self, event);
};
self.ensureEntity = function(expected) {
if (self.entity != expected) {
self.entity = expected;
self.selected = self.selectionProvider.getSelection(self.entity);
}
};
self.toggleSelected = function(event) {
if (!enableRowSelection && !config.enableCellSelection) {
return true;
}
var element = event.target || event;
if (element.type == "checkbox" && element.parentElement.className != "ngSelectionCell ng-scope") {
return true;
}
if (config.selectWithCheckboxOnly && element.type != "checkbox") {
self.selectionProvider.lastClickedRow = self;
return true;
} else {
if (self.beforeSelectionChange(self, event)) {
self.continueSelection(event);
}
}
return false;
};
self.rowIndex = rowIndex;
self.offsetTop = self.rowIndex * config.rowHeight;
self.rowDisplayIndex = 0;
self.alternatingRowClass = function () {
var isEven = (self.rowIndex % 2) === 0;
var classes = {
'ngRow' : true,
'selected': self.selected,
'even': isEven,
'odd': !isEven,
'ui-state-default': self.jqueryUITheme && isEven,
'ui-state-active': self.jqueryUITheme && !isEven
};
return classes;
};
self.beforeSelectionChange = config.beforeSelectionChangeCallback;
self.afterSelectionChange = config.afterSelectionChangeCallback;
self.getProperty = function(path) {
return $utils.evalProperty(self.entity, path);
};
self.copy = function () {
self.clone = new ngRow(entity, config, selectionProvider, rowIndex, $utils);
self.clone.isClone = true;
self.clone.elm = self.elm;
return self.clone;
};
self.setVars = function (fromRow) {
fromRow.clone = self;
self.entity = fromRow.entity;
self.selected = fromRow.selected;
};
};
var ngRowFactory = function (grid, $scope, domUtilityService, $templateCache, $utils) {
var self = this;
self.aggCache = {};
self.parentCache = [];
self.dataChanged = true;
self.parsedData = [];
self.rowConfig = {};
self.selectionProvider = $scope.selectionProvider;
self.rowHeight = 30;
self.numberOfAggregates = 0;
self.groupedData = undefined;
self.rowHeight = grid.config.rowHeight;
self.rowConfig = {
enableRowSelection: grid.config.enableRowSelection,
rowClasses: grid.config.rowClasses,
selectedItems: $scope.selectedItems,
selectWithCheckboxOnly: grid.config.selectWithCheckboxOnly,
beforeSelectionChangeCallback: grid.config.beforeSelectionChange,
afterSelectionChangeCallback: grid.config.afterSelectionChange,
jqueryUITheme: grid.config.jqueryUITheme,
enableCellSelection: grid.config.enableCellSelection,
rowHeight: grid.config.rowHeight
};
self.renderedRange = new ngRange(0, grid.minRowsToRender() + EXCESS_ROWS);
self.buildEntityRow = function(entity, rowIndex) {
return new ngRow(entity, self.rowConfig, self.selectionProvider, rowIndex, $utils);
};
self.buildAggregateRow = function(aggEntity, rowIndex) {
var agg = self.aggCache[aggEntity.aggIndex];
if (!agg) {
agg = new ngAggregate(aggEntity, self, self.rowConfig.rowHeight);
self.aggCache[aggEntity.aggIndex] = agg;
}
agg.rowIndex = rowIndex;
agg.offsetTop = rowIndex * self.rowConfig.rowHeight;
return agg;
};
self.UpdateViewableRange = function(newRange) {
self.renderedRange = newRange;
self.renderedChange();
};
self.filteredRowsChanged = function() {
if (grid.lateBoundColumns && grid.filteredRows.length > 0) {
grid.config.columnDefs = undefined;
grid.buildColumns();
grid.lateBoundColumns = false;
$scope.$evalAsync(function() {
$scope.adjustScrollLeft(0);
});
}
self.dataChanged = true;
if (grid.config.groups.length > 0) {
self.getGrouping(grid.config.groups);
}
self.UpdateViewableRange(self.renderedRange);
};
self.renderedChange = function() {
if (!self.groupedData || grid.config.groups.length < 1) {
self.renderedChangeNoGroups();
grid.refreshDomSizes();
return;
}
self.wasGrouped = true;
self.parentCache = [];
var x = 0;
var temp = self.parsedData.filter(function (e) {
if (e.isAggRow) {
if (e.parent && e.parent.collapsed) {
return false;
}
return true;
}
if (!e[NG_HIDDEN]) {
e.rowIndex = x++;
}
return !e[NG_HIDDEN];
});
self.totalRows = temp.length;
var rowArr = [];
for (var i = self.renderedRange.topRow; i < self.renderedRange.bottomRow; i++) {
if (temp[i]) {
temp[i].offsetTop = i * grid.config.rowHeight;
rowArr.push(temp[i]);
}
}
grid.setRenderedRows(rowArr);
};
self.renderedChangeNoGroups = function () {
var rowArr = [];
for (var i = self.renderedRange.topRow; i < self.renderedRange.bottomRow; i++) {
if (grid.filteredRows[i]) {
grid.filteredRows[i].rowIndex = i;
grid.filteredRows[i].offsetTop = i * grid.config.rowHeight;
rowArr.push(grid.filteredRows[i]);
}
}
grid.setRenderedRows(rowArr);
};
self.fixRowCache = function () {
var newLen = grid.data.length;
var diff = newLen - grid.rowCache.length;
if (diff < 0) {
grid.rowCache.length = grid.rowMap.length = newLen;
} else {
for (var i = grid.rowCache.length; i < newLen; i++) {
grid.rowCache[i] = grid.rowFactory.buildEntityRow(grid.data[i], i);
}
}
};
self.parseGroupData = function(g) {
if (g.values) {
for (var x = 0; x < g.values.length; x++){
self.parentCache[self.parentCache.length - 1].children.push(g.values[x]);
self.parsedData.push(g.values[x]);
}
} else {
for (var prop in g) {
if (prop == NG_FIELD || prop == NG_DEPTH || prop == NG_COLUMN) {
continue;
} else if (g.hasOwnProperty(prop)) {
var agg = self.buildAggregateRow({
gField: g[NG_FIELD],
gLabel: prop,
gDepth: g[NG_DEPTH],
isAggRow: true,
'_ng_hidden_': false,
children: [],
aggChildren: [],
aggIndex: self.numberOfAggregates,
aggLabelFilter: g[NG_COLUMN].aggLabelFilter
}, 0);
self.numberOfAggregates++;
agg.parent = self.parentCache[agg.depth - 1];
if (agg.parent) {
agg.parent.collapsed = false;
agg.parent.aggChildren.push(agg);
}
self.parsedData.push(agg);
self.parentCache[agg.depth] = agg;
self.parseGroupData(g[prop]);
}
}
}
};
self.getGrouping = function(groups) {
self.aggCache = [];
self.numberOfAggregates = 0;
self.groupedData = {};
var rows = grid.filteredRows,
maxDepth = groups.length,
cols = $scope.columns;
for (var x = 0; x < rows.length; x++){
var model = rows[x].entity;
if (!model) return;
rows[x][NG_HIDDEN] = true;
var ptr = self.groupedData;
for (var y = 0; y < groups.length; y++) {
var group = groups[y];
var col = cols.filter(function(c) {
return c.field == group;
})[0];
var val = $utils.evalProperty(model, group);
val = val ? val.toString() : 'null';
if (!ptr[val]) {
ptr[val] = {};
}
if (!ptr[NG_FIELD]) {
ptr[NG_FIELD] = group;
}
if (!ptr[NG_DEPTH]) {
ptr[NG_DEPTH] = y;
}
if (!ptr[NG_COLUMN]) {
ptr[NG_COLUMN] = col;
}
ptr = ptr[val];
}
if (!ptr.values) {
ptr.values = [];
}
ptr.values.push(rows[x]);
};
for (var z = 0; z < groups.length; z++) {
if (!cols[z].isAggCol && z <= maxDepth) {
cols.splice(0, 0, new ngColumn({
colDef: {
field: '',
width: 25,
sortable: false,
resizable: false,
headerCellTemplate: '<div class="ngAggHeader"></div>',
pinned: grid.config.pinSelectionCheckbox
},
enablePinning: grid.config.enablePinning,
isAggCol: true,
headerRowHeight: grid.config.headerRowHeight,
}, $scope, grid, domUtilityService, $templateCache, $utils));
}
}
domUtilityService.BuildStyles($scope, grid, true);
grid.fixColumnIndexes();
$scope.adjustScrollLeft(0);
self.parsedData.length = 0;
self.parseGroupData(self.groupedData);
self.fixRowCache();
};
if (grid.config.groups.length > 0 && grid.filteredRows.length > 0) {
self.getGrouping(grid.config.groups);
}
};
var ngSearchProvider = function ($scope, grid, $filter) {
var self = this,
searchConditions = [];
self.extFilter = grid.config.filterOptions.useExternalFilter;
$scope.showFilter = grid.config.showFilter;
$scope.filterText = '';
self.fieldMap = {};
self.evalFilter = function () {
var filterFunc = function(item) {
for (var x = 0, len = searchConditions.length; x < len; x++) {
var condition = searchConditions[x];
var result;
if (!condition.column) {
for (var prop in item) {
if (item.hasOwnProperty(prop)) {
var c = self.fieldMap[prop];
if (!c)
continue;
var f = null,
s = null;
if (c && c.cellFilter) {
s = c.cellFilter.split(':');
f = $filter(s[0]);
}
var pVal = item[prop];
if (pVal != null) {
if (typeof f == 'function') {
var filterRes = f(typeof pVal === 'object' ? evalObject(pVal, c.field) : pVal, s[1]).toString();
result = condition.regex.test(filterRes);
} else {
result = condition.regex.test(typeof pVal === 'object' ? evalObject(pVal, c.field).toString() : pVal.toString());
}
if (pVal && result) {
return true;
}
}
}
}
return false;
}
var col = self.fieldMap[condition.columnDisplay];
if (!col) {
return false;
}
var sp = col.cellFilter.split(':');
var filter = col.cellFilter ? $filter(sp[0]) : null;
var value = item[condition.column] || item[col.field.split('.')[0]];
if (value == null)
return false;
if (typeof filter == 'function') {
var filterResults = filter(typeof value === 'object' ? evalObject(value, col.field) : value, sp[1]).toString();
result = condition.regex.test(filterResults);
} else {
result = condition.regex.test(typeof value === 'object' ? evalObject(value, col.field).toString() : value.toString());
}
if (!value || !result) {
return false;
}
}
return true;
};
if (searchConditions.length === 0) {
grid.filteredRows = grid.rowCache;
} else {
grid.filteredRows = grid.rowCache.filter(function(row) {
return filterFunc(row.entity);
});
}
for (var i = 0; i < grid.filteredRows.length; i++)
{
grid.filteredRows[i].rowIndex = i;
}
grid.rowFactory.filteredRowsChanged();
};
var evalObject = function (obj, columnName) {
if (typeof obj != 'object' || typeof columnName != 'string')
return obj;
var args = columnName.split('.');
var cObj = obj;
if (args.length > 1) {
for (var i = 1, len = args.length; i < len; i++) {
cObj = cObj[args[i]];
if (!cObj)
return obj;
}
return cObj;
}
return obj;
};
var getRegExp = function (str, modifiers) {
try {
return new RegExp(str, modifiers);
} catch (err) {
return new RegExp(str.replace(/(\^|\$|\(|\)|\<|\>|\[|\]|\{|\}|\\|\||\.|\*|\+|\?)/g, '\\$1'));
}
};
var buildSearchConditions = function (a) {
searchConditions = [];
var qStr;
if (!(qStr = $.trim(a))) {
return;
}
var columnFilters = qStr.split(";");
for (var i = 0; i < columnFilters.length; i++) {
var args = columnFilters[i].split(':');
if (args.length > 1) {
var columnName = $.trim(args[0]);
var columnValue = $.trim(args[1]);
if (columnName && columnValue) {
searchConditions.push({
column: columnName,
columnDisplay: columnName.replace(/\s+/g, '').toLowerCase(),
regex: getRegExp(columnValue, 'i')
});
}
} else {
var val = $.trim(args[0]);
if (val) {
searchConditions.push({
column: '',
regex: getRegExp(val, 'i')
});
}
}
};
};
$scope.$watch(function() {
return grid.config.filterOptions.filterText;
}, function(a){
$scope.filterText = a;
});
$scope.$watch('filterText', function(a){
if(!self.extFilter){
$scope.$emit('ngGridEventFilter', a);
buildSearchConditions(a);
self.evalFilter();
}
});
if (!self.extFilter) {
$scope.$watch('columns', function (cs) {
for (var i = 0; i < cs.length; i++) {
var col = cs[i];
if(col.field)
self.fieldMap[col.field.split('.')[0]] = col;
if(col.displayName)
self.fieldMap[col.displayName.toLowerCase().replace(/\s+/g, '')] = col;
};
});
}
};
var ngSelectionProvider = function (grid, $scope, $parse) {
var self = this;
self.multi = grid.config.multiSelect;
self.selectedItems = grid.config.selectedItems;
self.selectedIndex = grid.config.selectedIndex;
self.lastClickedRow = undefined;
self.ignoreSelectedItemChanges = false;
self.pKeyParser = $parse(grid.config.primaryKey);
self.ChangeSelection = function (rowItem, evt) {
if (evt && !evt.ctrlKey && !evt.shiftKey && evt.originalEvent.constructor.name == "MouseEvent") {
self.toggleSelectAll(false, true);
}
if (evt && evt.shiftKey && !evt.keyCode && self.multi && grid.config.enableRowSelection) {
if (self.lastClickedRow) {
var rowsArr;
if ($scope.configGroups.length > 0) {
rowsArr = grid.rowFactory.parsedData.filter(function(row) {
return !row.isAggRow;
});
} else {
rowsArr = grid.filteredRows;
}
var thisIndx = rowItem.rowIndex;
var prevIndx = self.lastClickedRow.rowIndex;
self.lastClickedRow = rowItem;
if (thisIndx == prevIndx) {
return false;
}
if (thisIndx < prevIndx) {
thisIndx = thisIndx ^ prevIndx;
prevIndx = thisIndx ^ prevIndx;
thisIndx = thisIndx ^ prevIndx;
thisIndx--;
} else {
prevIndx++;
}
var rows = [];
for (; prevIndx <= thisIndx; prevIndx++) {
rows.push(rowsArr[prevIndx]);
}
if (rows[rows.length - 1].beforeSelectionChange(rows, evt)) {
for (var i = 0; i < rows.length; i++) {
var ri = rows[i];
var selectionState = ri.selected;
ri.selected = !selectionState;
if (ri.clone) {
ri.clone.selected = ri.selected;
}
var index = self.selectedItems.indexOf(ri.entity);
if (index === -1) {
self.selectedItems.push(ri.entity);
} else {
self.selectedItems.splice(index, 1);
}
}
rows[rows.length - 1].afterSelectionChange(rows, evt);
}
return true;
}
} else if (!self.multi) {
if (self.lastClickedRow == rowItem) {
self.setSelection(self.lastClickedRow, grid.config.keepLastSelected ? true : !rowItem.selected);
} else {
if (self.lastClickedRow) {
self.setSelection(self.lastClickedRow, false);
}
self.setSelection(rowItem, !rowItem.selected);
}
} else if (!evt.keyCode) {
self.setSelection(rowItem, !rowItem.selected);
}
self.lastClickedRow = rowItem;
return true;
};
self.getSelection = function (entity) {
var isSelected = false;
if (grid.config.primaryKey) {
var val = self.pKeyParser(entity);
angular.forEach(self.selectedItems, function (c) {
if (val == self.pkeyParser(c)) {
isSelected = true;
}
});
} else {
isSelected = self.selectedItems.indexOf(entity) !== -1;
}
return isSelected;
};
self.setSelection = function (rowItem, isSelected) {
if(grid.config.enableRowSelection){
rowItem.selected = isSelected;
if (rowItem.clone) {
rowItem.clone.selected = isSelected;
}
if (!isSelected) {
var indx = self.selectedItems.indexOf(rowItem.entity);
if(indx != -1){
self.selectedItems.splice(indx, 1);
}
} else {
if (self.selectedItems.indexOf(rowItem.entity) === -1) {
if(!self.multi && self.selectedItems.length > 0){
self.toggleSelectAll(false, true);
rowItem.selected = isSelected;
if (rowItem.clone) {
rowItem.clone.selected = isSelected;
}
}
self.selectedItems.push(rowItem.entity);
}
}
rowItem.afterSelectionChange(rowItem);
}
};
self.toggleSelectAll = function (checkAll, bypass) {
if (bypass || grid.config.beforeSelectionChange(grid.filteredRows)) {
var selectedlength = self.selectedItems.length;
if (selectedlength > 0) {
self.selectedItems.length = 0;
}
for (var i = 0; i < grid.filteredRows.length; i++) {
grid.filteredRows[i].selected = checkAll;
if (grid.filteredRows[i].clone) {
grid.filteredRows[i].clone.selected = checkAll;
}
if (checkAll) {
self.selectedItems.push(grid.filteredRows[i].entity);
}
}
if (!bypass) {
grid.config.afterSelectionChange(grid.filteredRows);
}
}
};
};
var ngStyleProvider = function($scope, grid, domUtilityService) {
$scope.headerCellStyle = function(col) {
return { "height": col.headerRowHeight + "px" };
};
$scope.rowStyle = function(row) {
return { "top": row.offsetTop + "px", "height": $scope.rowHeight + "px" };
};
$scope.canvasStyle = function() {
return { "height": grid.maxCanvasHt.toString() + "px" };
};
$scope.headerScrollerStyle = function() {
return { "height": grid.config.headerRowHeight + "px" };
};
$scope.topPanelStyle = function() {
return { "width": grid.rootDim.outerWidth + "px", "height": $scope.topPanelHeight() + "px" };
};
$scope.headerStyle = function() {
return { "width": (grid.rootDim.outerWidth) + "px", "height": grid.config.headerRowHeight + "px" };
};
$scope.groupPanelStyle = function () {
return { "width": (grid.rootDim.outerWidth) + "px", "height": "32px" };
};
$scope.viewportStyle = function() {
return { "width": grid.rootDim.outerWidth + "px", "height": $scope.viewportDimHeight() + "px" };
};
$scope.footerStyle = function() {
return { "width": grid.rootDim.outerWidth + "px", "height": $scope.footerRowHeight + "px" };
};
};
ngGridDirectives.directive('ngCellHasFocus', ['$domUtilityService',
function (domUtilityService) {
var focusOnInputElement = function($scope, elm){
$scope.isFocused = true;
domUtilityService.digest($scope);
var elementWithoutComments = angular.element(elm[0].children).filter(function () { return this.nodeType != 8; });
var inputElement = angular.element(elementWithoutComments[0].children[0]);
if(inputElement.length > 0){
angular.element(inputElement).focus();
$scope.domAccessProvider.selectInputElement(inputElement[0]);
angular.element(inputElement).bind('blur', function(){
$scope.isFocused = false;
domUtilityService.digest($scope);
return true;
});
}
};
return function($scope, elm) {
var isFocused = false;
$scope.editCell = function(){
setTimeout(function() {
focusOnInputElement($scope,elm);
}, 0);
};
elm.bind('mousedown', function(){
elm.focus();
return true;
});
elm.bind('focus', function(){
isFocused = true;
return true;
});
elm.bind('blur', function(){
isFocused = false;
return true;
});
elm.bind('keydown', function(evt){
if(isFocused && evt.keyCode != 37 && evt.keyCode != 38 && evt.keyCode != 39 && evt.keyCode != 40 && evt.keyCode != 9 && !evt.shiftKey && evt.keyCode != 13){
focusOnInputElement($scope,elm);
}
if(evt.keyCode == 27){
elm.focus();
}
return true;
});
};
}]);
ngGridDirectives.directive('ngCellText',
function () {
return function(scope, elm) {
elm.bind('mouseover', function(evt) {
evt.preventDefault();
elm.css({
'cursor': 'text'
});
});
elm.bind('mouseleave', function(evt) {
evt.preventDefault();
elm.css({
'cursor': 'default'
});
});
};
});
ngGridDirectives.directive('ngCell', ['$compile', '$domUtilityService', function ($compile, domUtilityService) {
var ngCell = {
scope: false,
compile: function() {
return {
pre: function($scope, iElement) {
var html;
var cellTemplate = $scope.col.cellTemplate.replace(COL_FIELD, '$eval(\'row.entity.\' + col.field)');
if($scope.col.enableCellEdit){
html = $scope.col.cellEditTemplate;
html = html.replace(DISPLAY_CELL_TEMPLATE, cellTemplate);
html = html.replace(EDITABLE_CELL_TEMPLATE, $scope.col.editableCellTemplate.replace(COL_FIELD, "col.field"));
} else {
html = cellTemplate;
}
var cellElement = $compile(html)($scope);
if($scope.enableCellSelection && cellElement[0].className.indexOf('ngSelectionCell') == -1){
cellElement[0].setAttribute('tabindex', 0);
cellElement.addClass('ngCellElement');
}
iElement.append(cellElement);
},
post: function($scope, iElement){
if($scope.enableCellSelection){
$scope.domAccessProvider.selectionHandlers($scope, iElement);
}
$scope.$on('ngGridEventDigestCell', function(){
domUtilityService.digest($scope);
});
}
};
}
};
return ngCell;
}]);
ngGridDirectives.directive('ngGridFooter', ['$compile', '$templateCache', function ($compile, $templateCache) {
var ngGridFooter = {
scope: false,
compile: function () {
return {
pre: function ($scope, iElement) {
if (iElement.children().length === 0) {
iElement.append($compile($templateCache.get($scope.gridId + 'footerTemplate.html'))($scope));
}
}
};
}
};
return ngGridFooter;
}]);
ngGridDirectives.directive('ngGridMenu', ['$compile', '$templateCache', function ($compile, $templateCache) {
var ngGridMenu = {
scope: false,
compile: function () {
return {
pre: function ($scope, iElement) {
if (iElement.children().length === 0) {
iElement.append($compile($templateCache.get($scope.gridId + 'menuTemplate.html'))($scope));
}
}
};
}
};
return ngGridMenu;
}]);
ngGridDirectives.directive('ngGrid', ['$compile', '$filter', '$templateCache', '$sortService', '$domUtilityService', '$utilityService', '$timeout', '$parse', function ($compile, $filter, $templateCache, sortService, domUtilityService, $utils, $timeout, $parse) {
var ngGridDirective = {
scope: true,
compile: function() {
return {
pre: function($scope, iElement, iAttrs) {
var $element = $(iElement);
var options = $scope.$eval(iAttrs.ngGrid);
options.gridDim = new ngDimension({ outerHeight: $($element).height(), outerWidth: $($element).width() });
var grid = new ngGrid($scope, options, sortService, domUtilityService, $filter, $templateCache, $utils, $timeout, $parse);
if (typeof options.columnDefs == "string") {
$scope.$parent.$watch(options.columnDefs, function (a) {
if (!a) {
grid.refreshDomSizes();
grid.buildColumns();
return;
}
grid.lateBoundColumns = false;
$scope.columns = [];
grid.config.columnDefs = a;
grid.buildColumns();
grid.configureColumnWidths();
grid.eventProvider.assignEvents();
domUtilityService.RebuildGrid($scope, grid);
});
} else {
grid.buildColumns();
}
if (typeof options.data == "string") {
var dataWatcher = function (a) {
grid.data = $.extend([], a);
grid.rowFactory.fixRowCache();
angular.forEach(grid.data, function (item, j) {
var indx = grid.rowMap[j] || j;
if (grid.rowCache[indx]) {
grid.rowCache[indx].ensureEntity(item);
}
grid.rowMap[indx] = j;
});
grid.searchProvider.evalFilter();
grid.configureColumnWidths();
grid.refreshDomSizes();
if (grid.config.sortInfo.fields.length > 0) {
grid.getColsFromFields();
grid.sortActual();
grid.searchProvider.evalFilter();
$scope.$emit('ngGridEventSorted', grid.config.sortInfo);
}
$scope.$emit("ngGridEventData", grid.gridId);
};
$scope.$parent.$watch(options.data, dataWatcher);
$scope.$parent.$watch(options.data + '.length', function() {
dataWatcher($scope.$eval(options.data));
});
}
grid.footerController = new ngFooter($scope, grid);
iElement.addClass("ngGrid").addClass(grid.gridId.toString());
if (!options.enableHighlighting) {
iElement.addClass("unselectable");
}
if (options.jqueryUITheme) {
iElement.addClass('ui-widget');
}
iElement.append($compile($templateCache.get('gridTemplate.html'))($scope));
domUtilityService.AssignGridContainers($scope, iElement, grid);
grid.eventProvider = new ngEventProvider(grid, $scope, domUtilityService, $timeout);
options.selectRow = function (rowIndex, state) {
if (grid.rowCache[rowIndex]) {
if (grid.rowCache[rowIndex].clone) {
grid.rowCache[rowIndex].clone.setSelection(state ? true : false);
}
grid.rowCache[rowIndex].setSelection(state ? true : false);
}
};
options.selectItem = function (itemIndex, state) {
options.selectRow(grid.rowMap[itemIndex], state);
};
options.selectAll = function (state) {
$scope.toggleSelectAll(state);
};
options.groupBy = function (field) {
if (field) {
$scope.groupBy($scope.columns.filter(function(c) {
return c.field == field;
})[0]);
} else {
var arr = $.extend(true, [], $scope.configGroups);
angular.forEach(arr, $scope.groupBy);
}
};
options.sortBy = function (field) {
var col = $scope.columns.filter(function (c) {
return c.field == field;
})[0];
if (col) col.sort();
};
options.gridId = grid.gridId;
options.ngGrid = grid;
options.$gridScope = $scope;
$scope.$on('ngGridEventDigestGrid', function(){
domUtilityService.digest($scope.$parent);
});
$scope.$on('ngGridEventDigestGridParent', function(){
domUtilityService.digest($scope.$parent);
});
$scope.$evalAsync(function() {
$scope.adjustScrollLeft(0);
});
angular.forEach(options.plugins, function (p) {
if (typeof p === 'function') {
p = p.call(this);
}
p.init($scope.$new(), grid, { SortService: sortService, DomUtilityService: domUtilityService });
options.plugins[$utils.getInstanceType(p)] = p;
});
if (options.init == "function") {
options.init(grid, $scope);
}
return null;
}
};
}
};
return ngGridDirective;
}]);
ngGridDirectives.directive('ngHeaderCell', ['$compile', function($compile) {
var ngHeaderCell = {
scope: false,
compile: function() {
return {
pre: function($scope, iElement) {
iElement.append($compile($scope.col.headerCellTemplate)($scope));
}
};
}
};
return ngHeaderCell;
}]);
ngGridDirectives.directive('ngIf', [function () {
return {
transclude: 'element',
priority: 1000,
terminal: true,
restrict: 'A',
compile: function (e, a, transclude) {
return function (scope, element, attr) {
var childElement;
var childScope;
scope.$watch(attr['ngIf'], function (newValue) {
if (childElement) {
childElement.remove();
childElement = undefined;
}
if (childScope) {
childScope.$destroy();
childScope = undefined;
}
if (newValue) {
childScope = scope.$new();
transclude(childScope, function (clone) {
childElement = clone;
element.after(clone);
});
}
});
};
}
};
}]);
ngGridDirectives.directive('ngInput',['$parse', function($parse) {
return function ($scope, elm, attrs) {
var getter = $parse($scope.$eval(attrs.ngInput));
var setter = getter.assign;
var oldCellValue = getter($scope.row.entity);
elm.val(oldCellValue);
elm.bind('keyup', function() {
var newVal = elm.val();
if (!$scope.$root.$$phase) {
$scope.$apply(function(){setter($scope.row.entity,newVal); });
}
});
elm.bind('keydown', function(evt){
switch(evt.keyCode){
case 37:
case 38:
case 39:
case 40:
evt.stopPropagation();
break;
case 27:
if (!$scope.$root.$$phase) {
$scope.$apply(function(){
setter($scope.row.entity,oldCellValue);
elm.val(oldCellValue);
elm.blur();
});
}
default:
break;
}
return true;
});
};
}]);
ngGridDirectives.directive('ngRow', ['$compile', '$domUtilityService', '$templateCache', function ($compile, domUtilityService, $templateCache) {
var ngRow = {
scope: false,
compile: function() {
return {
pre: function($scope, iElement) {
$scope.row.elm = iElement;
if ($scope.row.clone) {
$scope.row.clone.elm = iElement;
}
if ($scope.row.isAggRow) {
var html = $templateCache.get($scope.gridId + 'aggregateTemplate.html');
if ($scope.row.aggLabelFilter) {
html = html.replace(CUSTOM_FILTERS, '| ' + $scope.row.aggLabelFilter);
} else {
html = html.replace(CUSTOM_FILTERS, "");
}
iElement.append($compile(html)($scope));
} else {
iElement.append($compile($templateCache.get($scope.gridId + 'rowTemplate.html'))($scope));
}
$scope.$on('ngGridEventDigestRow', function(){
domUtilityService.digest($scope);
});
}
};
}
};
return ngRow;
}]);
ngGridDirectives.directive('ngViewport', [function() {
return function($scope, elm) {
var isMouseWheelActive;
var prevScollLeft;
var prevScollTop = 0;
elm.bind('scroll', function(evt) {
var scrollLeft = evt.target.scrollLeft,
scrollTop = evt.target.scrollTop;
if ($scope.$headerContainer) {
$scope.$headerContainer.scrollLeft(scrollLeft);
}
$scope.adjustScrollLeft(scrollLeft);
$scope.adjustScrollTop(scrollTop);
if (!$scope.$root.$$phase) {
$scope.$digest();
}
prevScollLeft = scrollLeft;
prevScollTop = prevScollTop;
isMouseWheelActive = false;
return true;
});
elm.bind("mousewheel DOMMouseScroll", function() {
isMouseWheelActive = true;
elm.focus();
return true;
});
if (!$scope.enableCellSelection) {
$scope.domAccessProvider.selectionHandlers($scope, elm);
}
};
}]);
window.ngGrid.i18n['en'] = {
ngAggregateLabel: 'items',
ngGroupPanelDescription: 'Drag a column header here and drop it to group by that column.',
ngSearchPlaceHolder: 'Search...',
ngMenuText: 'Choose Columns:',
ngShowingItemsLabel: 'Showing Items:',
ngTotalItemsLabel: 'Total Items:',
ngSelectedItemsLabel: 'Selected Items:',
ngPageSizeLabel: 'Page Size:',
ngPagerFirstTitle: 'First Page',
ngPagerNextTitle: 'Next Page',
ngPagerPrevTitle: 'Previous Page',
ngPagerLastTitle: 'Last Page'
};
window.ngGrid.i18n['fr'] = {
ngAggregateLabel: 'articles',
ngGroupPanelDescription: 'Faites glisser un en-tête de colonne ici et déposez-le vers un groupe par cette colonne.',
ngSearchPlaceHolder: 'Recherche...',
ngMenuText: 'Choisir des colonnes:',
ngShowingItemsLabel: 'Articles Affichage des:',
ngTotalItemsLabel: 'Nombre total d\'articles:',
ngSelectedItemsLabel: 'Éléments Articles:',
ngPageSizeLabel: 'Taille de page:',
ngPagerFirstTitle: 'Première page',
ngPagerNextTitle: 'Page Suivante',
ngPagerPrevTitle: 'Page précédente',
ngPagerLastTitle: 'Dernière page'
};
window.ngGrid.i18n['ge'] = {
ngAggregateLabel: 'artikel',
ngGroupPanelDescription: 'Ziehen Sie eine Spaltenüberschrift hier und legen Sie es der Gruppe nach dieser Spalte.',
ngSearchPlaceHolder: 'Suche...',
ngMenuText: 'Spalten auswählen:',
ngShowingItemsLabel: 'Zeige Artikel:',
ngTotalItemsLabel: 'Meiste Artikel:',
ngSelectedItemsLabel: 'Ausgewählte Artikel:',
ngPageSizeLabel: 'Größe Seite:',
ngPagerFirstTitle: 'Erste Page',
ngPagerNextTitle: 'Nächste Page',
ngPagerPrevTitle: 'Vorherige Page',
ngPagerLastTitle: 'Letzte Page'
};
window.ngGrid.i18n['sp'] = {
ngAggregateLabel: 'Artículos',
ngGroupPanelDescription: 'Arrastre un encabezado de columna aquí y soltarlo para agrupar por esa columna.',
ngSearchPlaceHolder: 'Buscar...',
ngMenuText: 'Elegir columnas:',
ngShowingItemsLabel: 'Artículos Mostrando:',
ngTotalItemsLabel: 'Artículos Totales:',
ngSelectedItemsLabel: 'Artículos Seleccionados:',
ngPageSizeLabel: 'Tamaño de Página:',
ngPagerFirstTitle: 'Primera Página',
ngPagerNextTitle: 'Página Siguiente',
ngPagerPrevTitle: 'Página Anterior',
ngPagerLastTitle: 'Última Página'
};
window.ngGrid.i18n['zh-cn'] = {
ngAggregateLabel: '条目',
ngGroupPanelDescription: '拖曳表头到此处以进行分组',
ngSearchPlaceHolder: '搜索...',
ngMenuText: '数据分组与选择列:',
ngShowingItemsLabel: '当前显示条目:',
ngTotalItemsLabel: '条目总数:',
ngSelectedItemsLabel: '选中条目:',
ngPageSizeLabel: '每页显示数:',
ngPagerFirstTitle: '回到首页',
ngPagerNextTitle: '下一页',
ngPagerPrevTitle: '上一页',
ngPagerLastTitle: '前往尾页'
};
window.ngGrid.i18n['zh-tw'] = {
ngAggregateLabel: '筆',
ngGroupPanelDescription: '拖拉表頭到此處以進行分組',
ngSearchPlaceHolder: '搜尋...',
ngMenuText: '選擇欄位:',
ngShowingItemsLabel: '目前顯示筆數:',
ngTotalItemsLabel: '總筆數:',
ngSelectedItemsLabel: '選取筆數:',
ngPageSizeLabel: '每頁顯示:',
ngPagerFirstTitle: '第一頁',
ngPagerNextTitle: '下一頁',
ngPagerPrevTitle: '上一頁',
ngPagerLastTitle: '最後頁'
};
angular.module("ngGrid").run(["$templateCache", function($templateCache) {
$templateCache.put("aggregateTemplate.html",
"<div ng-click=\"row.toggleExpand()\" ng-style=\"rowStyle(row)\" ng-style=\"{'left': row.offsetleft}\" class=\"ngAggregate\">" +
" <span class=\"ngAggregateText\">{{row.label CUSTOM_FILTERS}} ({{row.totalChildren()}} {{AggItemsLabel}})</span>" +
" <div class=\"{{row.aggClass()}}\"></div>" +
"</div>" +
""
);
$templateCache.put("cellEditTemplate.html",
"<div ng-cell-has-focus ng-dblclick=\"editCell()\">" +
" <div ng-if=\"!isFocused\">" +
" DISPLAY_CELL_TEMPLATE" +
" </div>" +
" <div ng-if=\"isFocused\">" +
" EDITABLE_CELL_TEMPLATE" +
" </div>" +
"</div>"
);
$templateCache.put("cellTemplate.html",
"<div class=\"ngCellText\" ng-class=\"col.colIndex()\"><span ng-cell-text>{{COL_FIELD CUSTOM_FILTERS}}</span></div>"
);
$templateCache.put("checkboxCellTemplate.html",
"<div class=\"ngSelectionCell\"><input tabindex=\"-1\" class=\"ngSelectionCheckbox\" type=\"checkbox\" ng-checked=\"row.selected\" /></div>"
);
$templateCache.put("checkboxHeaderTemplate.html",
"<input class=\"ngSelectionHeader\" type=\"checkbox\" ng-show=\"multiSelect\" ng-model=\"allSelected\" ng-change=\"toggleSelectAll(allSelected)\"/>"
);
$templateCache.put("editableCellTemplate.html",
"<input ng-class=\"'colt' + col.index\" ng-input=\"COL_FIELD\" />"
);
$templateCache.put("footerTemplate.html",
"<div ng-show=\"showFooter\" class=\"ngFooterPanel\" ng-class=\"{'ui-widget-content': jqueryUITheme, 'ui-corner-bottom': jqueryUITheme}\" ng-style=\"footerStyle()\">" +
" <div class=\"ngTotalSelectContainer\" >" +
" <div class=\"ngFooterTotalItems\" ng-class=\"{'ngNoMultiSelect': !multiSelect}\" >" +
" <span class=\"ngLabel\">{{i18n.ngTotalItemsLabel}} {{maxRows()}}</span><span ng-show=\"filterText.length > 0\" class=\"ngLabel\">({{i18n.ngShowingItemsLabel}} {{totalFilteredItemsLength()}})</span>" +
" </div>" +
" <div class=\"ngFooterSelectedItems\" ng-show=\"multiSelect\">" +
" <span class=\"ngLabel\">{{i18n.ngSelectedItemsLabel}} {{selectedItems.length}}</span>" +
" </div>" +
" </div>" +
" <div class=\"ngPagerContainer\" style=\"float: right; margin-top: 10px;\" ng-show=\"enablePaging\" ng-class=\"{'ngNoMultiSelect': !multiSelect}\">" +
" <div style=\"float:left; margin-right: 10px;\" class=\"ngRowCountPicker\">" +
" <span style=\"float: left; margin-top: 3px;\" class=\"ngLabel\">{{i18n.ngPageSizeLabel}}</span>" +
" <select style=\"float: left;height: 27px; width: 100px\" ng-model=\"pagingOptions.pageSize\" >" +
" <option ng-repeat=\"size in pagingOptions.pageSizes\">{{size}}</option>" +
" </select>" +
" </div>" +
" <div style=\"float:left; margin-right: 10px; line-height:25px;\" class=\"ngPagerControl\" style=\"float: left; min-width: 135px;\">" +
" <button class=\"ngPagerButton\" ng-click=\"pageToFirst()\" ng-disabled=\"cantPageBackward()\" title=\"{{i18n.ngPagerFirstTitle}}\"><div class=\"ngPagerFirstTriangle\"><div class=\"ngPagerFirstBar\"></div></div></button>" +
" <button class=\"ngPagerButton\" ng-click=\"pageBackward()\" ng-disabled=\"cantPageBackward()\" title=\"{{i18n.ngPagerPrevTitle}}\"><div class=\"ngPagerFirstTriangle ngPagerPrevTriangle\"></div></button>" +
" <input class=\"ngPagerCurrent\" type=\"number\" style=\"width:50px; height: 24px; margin-top: 1px; padding: 0 4px;\" ng-model=\"pagingOptions.currentPage\"/>" +
" <button class=\"ngPagerButton\" ng-click=\"pageForward()\" ng-disabled=\"cantPageForward()\" title=\"{{i18n.ngPagerNextTitle}}\"><div class=\"ngPagerLastTriangle ngPagerNextTriangle\"></div></button>" +
" <button class=\"ngPagerButton\" ng-click=\"pageToLast()\" ng-disabled=\"cantPageToLast()\" title=\"{{i18n.ngPagerLastTitle}}\"><div class=\"ngPagerLastTriangle\"><div class=\"ngPagerLastBar\"></div></div></button>" +
" </div>" +
" </div>" +
"</div>"
);
$templateCache.put("gridTemplate.html",
"<div class=\"ngTopPanel\" ng-class=\"{'ui-widget-header':jqueryUITheme, 'ui-corner-top': jqueryUITheme}\" ng-style=\"topPanelStyle()\">" +
" <div class=\"ngGroupPanel\" ng-show=\"showGroupPanel()\" ng-style=\"groupPanelStyle()\">" +
" <div class=\"ngGroupPanelDescription\" ng-show=\"configGroups.length == 0\">{{i18n.ngGroupPanelDescription}}</div>" +
" <ul ng-show=\"configGroups.length > 0\" class=\"ngGroupList\">" +
" <li class=\"ngGroupItem\" ng-repeat=\"group in configGroups\">" +
" <span class=\"ngGroupElement\">" +
" <span class=\"ngGroupName\">{{group.displayName}}" +
" <span ng-click=\"removeGroup($index)\" class=\"ngRemoveGroup\">x</span>" +
" </span>" +
" <span ng-hide=\"$last\" class=\"ngGroupArrow\"></span>" +
" </span>" +
" </li>" +
" </ul>" +
" </div>" +
" <div class=\"ngHeaderContainer\" ng-style=\"headerStyle()\">" +
" <div class=\"ngHeaderScroller\" ng-style=\"headerScrollerStyle()\" ng-include=\"gridId + 'headerRowTemplate.html'\"></div>" +
" </div>" +
" <div ng-grid-menu></div>" +
"</div>" +
"<div class=\"ngViewport\" unselectable=\"on\" ng-viewport ng-class=\"{'ui-widget-content': jqueryUITheme}\" ng-style=\"viewportStyle()\">" +
" <div class=\"ngCanvas\" ng-style=\"canvasStyle()\">" +
" <div ng-style=\"rowStyle(row)\" ng-repeat=\"row in renderedRows\" ng-click=\"row.toggleSelected($event)\" ng-class=\"row.alternatingRowClass()\" ng-row></div>" +
" </div>" +
"</div>" +
"<div ng-grid-footer></div>" +
""
);
$templateCache.put("headerCellTemplate.html",
"<div class=\"ngHeaderSortColumn {{col.headerClass}}\" ng-style=\"{'cursor': col.cursor}\" ng-class=\"{ 'ngSorted': !noSortVisible }\">" +
" <div ng-click=\"col.sort($event)\" ng-class=\"'colt' + col.index\" class=\"ngHeaderText\">{{col.displayName}}</div>" +
" <div class=\"ngSortButtonDown\" ng-show=\"col.showSortButtonDown()\"></div>" +
" <div class=\"ngSortButtonUp\" ng-show=\"col.showSortButtonUp()\"></div>" +
" <div class=\"ngSortPriority\">{{col.sortPriority}}</div>" +
" <div ng-class=\"{ ngPinnedIcon: col.pinned, ngUnPinnedIcon: !col.pinned }\" ng-click=\"togglePin(col)\" ng-show=\"col.pinnable\"></div>" +
"</div>" +
"<div ng-show=\"col.resizable\" class=\"ngHeaderGrip\" ng-click=\"col.gripClick($event)\" ng-mousedown=\"col.gripOnMouseDown($event)\"></div>"
);
$templateCache.put("headerRowTemplate.html",
"<div ng-style=\"{ height: col.headerRowHeight }\" ng-repeat=\"col in renderedColumns\" ng-class=\"col.colIndex()\" class=\"ngHeaderCell\" ng-header-cell></div>"
);
$templateCache.put("menuTemplate.html",
"<div ng-show=\"showColumnMenu || showFilter\" class=\"ngHeaderButton\" ng-click=\"toggleShowMenu()\">" +
" <div class=\"ngHeaderButtonArrow\"></div>" +
"</div>" +
"<div ng-show=\"showMenu\" class=\"ngColMenu\">" +
" <div ng-show=\"showFilter\">" +
" <input placeholder=\"{{i18n.ngSearchPlaceHolder}}\" type=\"text\" ng-model=\"filterText\"/>" +
" </div>" +
" <div ng-show=\"showColumnMenu\">" +
" <span class=\"ngMenuText\">{{i18n.ngMenuText}}</span>" +
" <ul class=\"ngColList\">" +
" <li class=\"ngColListItem\" ng-repeat=\"col in columns | ngColumns\">" +
" <label><input ng-disabled=\"col.pinned\" type=\"checkbox\" class=\"ngColListCheckbox\" ng-model=\"col.visible\"/>{{col.displayName}}</label>" +
" <a title=\"Group By\" ng-class=\"col.groupedByClass()\" ng-show=\"col.groupable && col.visible\" ng-click=\"groupBy(col)\"></a>" +
" <span class=\"ngGroupingNumber\" ng-show=\"col.groupIndex > 0\">{{col.groupIndex}}</span> " +
" </li>" +
" </ul>" +
" </div>" +
"</div>"
);
$templateCache.put("rowTemplate.html",
"<div ng-style=\"{ 'cursor': row.cursor }\" ng-repeat=\"col in renderedColumns\" ng-class=\"col.colIndex()\" class=\"ngCell {{col.cellClass}}\" ng-cell></div>"
);
}]);
}(window, jQuery));