@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
7,403 lines • 243 kB
JavaScript
//#region ../src/treelist/contextmenu.js
(function($, undefined) {
var kendo = window.kendo, ui = kendo.ui, ContextMenu = ui.ContextMenu, extend = $.extend, encode = kendo.htmlEncode;
var ACTION = "action";
var TreeListContextMenu = ContextMenu.extend({
init: function(element, options) {
var that = this;
ContextMenu.fn.init.call(that, element, options);
that._overrideTemplates();
that._extendItems();
that.bind("select", that._onSelect.bind(that));
that.bind("open", that._onOpen.bind(that));
},
_overrideTemplates: function() {
this.templates.sprite = ({ icon, spriteCssClass }) => `${icon || spriteCssClass ? kendo.ui.icon({
icon: encode(icon || ""),
iconClass: encode(spriteCssClass || "")
}) : ""}`;
},
defaultItems: {
"separator": {
name: "separator",
separator: true
},
"create": {
name: "create",
text: "Add",
icon: "plus",
command: "AddCommand",
rules: "isEditable"
},
"createChild": {
name: "createChild",
text: "Add Child",
icon: "plus",
command: "CreateChildCommand",
rules: "isEditable"
},
"edit": {
name: "edit",
text: "Edit",
icon: "pencil",
command: "EditCommand",
rules: "isEditable"
},
"destroy": {
name: "destroy",
text: "Delete",
icon: "trash",
command: "DeleteCommand",
rules: "isEditable"
},
"select": {
name: "select",
text: "Select",
icon: "table-body",
rules: "isSelectable",
items: [
{
name: "selectRow",
text: "Row",
icon: "table-row-groups",
command: "SelectRowCommand"
},
{
name: "selectAllRows",
text: "All rows",
icon: "grid",
command: "SelectAllRowsCommand",
softRules: "isMultiRowSelectionEnabled"
},
{
name: "clearSelection",
text: "Clear selection",
icon: "table-unmerge",
softRules: "hasSelection",
command: "ClearSelectionCommand"
}
]
},
"exportPDF": {
name: "exportPDF",
text: "Export to PDF",
icon: "file-pdf",
command: "ExportPDFCommand"
},
"exportExcel": {
name: "exportExcel",
text: "Export to Excel",
icon: "file-excel",
command: "ExportExcelCommand"
},
"sortAsc": {
name: "sortAsc",
text: "Sort Ascending",
icon: "sort-asc-small",
rules: "isSortable",
command: "SortCommand",
options: "dir:asc"
},
"sortDesc": {
name: "sortDesc",
text: "Sort Descending",
icon: "sort-desc-small",
rules: "isSortable",
command: "SortCommand",
options: "dir:desc"
},
"expandItem": {
name: "expandItem",
text: "Expand Item",
icon: "folder-open",
softRules: "isExpandable",
command: "ToggleItemCommand",
options: "expand:true"
},
"collapseItem": {
name: "collapseItem",
text: "Collapse Item",
icon: "folder",
softRules: "isCollapsible",
command: "ToggleItemCommand",
options: "expand:false"
}
},
events: ContextMenu.fn.events.concat([ACTION]),
_onSelect: function(ev) {
var command = $(ev.item).data("command");
var options = $(ev.item).data("options");
options = options ? options.split(",").map((val) => {
if (val.indexOf(":") > -1) {
var [key, val] = val.split(":");
return { [key || "_"]: val };
}
return { [val]: true };
}).reduce((acc, v) => Object.assign(acc, v), {}) : {};
var target = $(ev.target);
if (!command) {
return;
}
this.action({
command,
options: Object.assign(options, { target })
});
},
_onOpen: function(ev) {
var menu = ev.sender, items = menu.options.items, elTarget = $(ev.event ? ev.event.target : null);
if (!items && $.isEmptyObject(this.defaultItems) || elTarget.closest(".k-grid-column-menu").length) {
ev.preventDefault();
return;
}
this._toggleSeparatorVisibility();
menu.element.find(`[${kendo.attr("soft-rules")}]`).each((i, item) => {
var rules = $(item).attr(kendo.attr("soft-rules")).split(";");
menu.enable(item, this._validateSoftRules(rules, elTarget));
});
},
_toggleSeparatorVisibility: function() {
var that = this, items = that.element.find(".k-item.k-separator").filter((i, item) => {
var prev = $(item).prev(".k-item:not(.k-separator)");
var next = $(item).next(".k-item:not(.k-separator)");
return !(prev.length && next.length);
});
items.hide();
},
_extendItems: function() {
var that = this, items = that.options.items, item, isBuiltInTool;
if (items && items.length) {
for (var i = 0; i < items.length; i++) {
item = items[i];
isBuiltInTool = $.isPlainObject(item) && Object.keys(item).length === 1 && item.name;
if (isBuiltInTool) {
item = item.name;
}
if ($.isPlainObject(item)) {
that._append(item);
} else if (that.defaultItems[item]) {
item = that.defaultItems[item];
that._append(item);
} else if (typeof item === "string") {
item = {
name: item,
text: item,
spriteCssClass: item,
command: item + "Command"
};
that._append(item);
}
}
} else {
for (var key in that.defaultItems) {
item = that.defaultItems[key];
that._append(item);
}
}
},
_extendItem: function(item) {
var that = this, messages = that.options.messages, attr = item.attr || {};
if (item.command) {
attr[kendo.attr("command")] = item.command;
}
if (item.options) {
attr[kendo.attr("options")] = item.options;
}
if (item.softRules) {
attr[kendo.attr("soft-rules")] = item.softRules;
}
if (item.items) {
for (var j = 0; j < item.items.length; j++) {
item.items.forEach((subItem) => {
that._extendItem(subItem);
});
}
}
extend(item, {
text: messages.commands[item.name],
icon: item.icon || "",
spriteCssClass: item.spriteCssClass || "",
attr,
uid: kendo.guid()
});
},
_validateSoftRules: function(rules, target) {
var that = this;
if (!rules || !(rules && rules.length)) {
return true;
}
for (var i = 0; i < rules.length; i++) {
if (!this._readState(rules[i], target)) {
return false;
}
}
return true;
},
_validateRules: function(tool) {
var that = this, rules = tool.rules ? tool.rules.split(";") : [];
if (!rules.length) {
return true;
}
for (var i = 0; i < rules.length; i++) {
if (!this._readState(rules[i])) {
return false;
}
}
return true;
},
_readState: function(state, target) {
var that = this, states = that.options.states;
if (kendo.isFunction(states[state])) {
return states[state](target);
} else {
return states[state];
}
},
_append: function(item) {
var that = this;
that._extendItem(item);
if (that._validateRules(item)) {
that.append(item);
}
},
action: function(args) {
this.trigger(ACTION, args);
}
});
kendo.ui.treelist = kendo.ui.treelist || {};
extend(kendo.ui.treelist, { ContextMenu: TreeListContextMenu });
})(window.kendo.jQuery);
//#endregion
//#region ../src/treelist/commands.js
(function($, undefined) {
var kendo = window.kendo, extend = $.extend, Class = kendo.Class;
var Command = Class.extend({ init: function(options) {
this.options = options;
this.treelist = options.treelist;
} });
var SortCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist, dataSource = treelist.dataSource, sort = dataSource.sort() || [], options = that.options, dir = options.dir, field = options.target.attr(kendo.attr("field")), multipleMode = treelist.options.sortable.mode && treelist.options.sortable.mode === "multiple", compare = treelist.options.compare, length, idx;
if (multipleMode) {
for (idx = 0, length = sort.length; idx < length; idx++) {
if (sort[idx].field === field) {
sort.splice(idx, 1);
break;
}
}
sort.push({
field,
dir,
compare
});
} else {
sort = [{
field,
dir,
compare
}];
}
dataSource.sort(sort);
} });
var AddCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist;
treelist.addRow();
} });
var CreateChildCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist, target = that.options.target.closest("tr");
treelist.addRow(target);
} });
var EditCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist, inCellMode = treelist._editMode() === "incell", target = inCellMode ? that.options.target : that.options.target.closest("tr");
if (inCellMode) {
treelist.editCell(target);
} else {
treelist.editRow(target);
}
} });
var DeleteCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist, target = that.options.target.closest("tr");
treelist.removeRow(target);
} });
var SelectRowCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist, selectMode = kendo.ui.Selectable.parseOptions(treelist.options.selectable), target = that.options.target.closest("tr");
treelist.select(selectMode.cell ? target.find("td") : target);
} });
var SelectAllRowsCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist, selectMode = kendo.ui.Selectable.parseOptions(treelist.options.selectable), rows = treelist.items();
treelist.select(selectMode.cell ? rows.find("td") : rows);
} });
var ClearSelectionCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist;
treelist.clearSelection();
} });
var ExportPDFCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist;
treelist.saveAsPDF();
} });
var ExportExcelCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist;
treelist.saveAsExcel();
} });
var ToggleItemCommand = Command.extend({ exec: function() {
var that = this, treelist = that.treelist, target = that.options.target, options = that.options, expand = options.expand === "true";
if (expand) {
treelist.expand(target);
} else {
treelist.collapse(target);
}
} });
kendo.ui.treelist = kendo.ui.treelist || {};
extend(kendo.ui.treelist, {
TreeListCommand: Command,
commands: {
SortCommand,
AddCommand,
CreateChildCommand,
EditCommand,
DeleteCommand,
SelectRowCommand,
SelectAllRowsCommand,
ClearSelectionCommand,
ExportPDFCommand,
ExportExcelCommand,
ToggleItemCommand
}
});
})(window.kendo.jQuery);
//#endregion
//#region ../src/kendo.treelist.js
const __meta__ = {
id: "treelist",
name: "TreeList",
category: "web",
description: "The TreeList widget displays self-referencing data and offers rich support for interacting with data, sorting, filtering, and selection.",
depends: [
"dom",
"data",
"pager",
"toolbar",
"icons",
"reorderable",
"menu"
],
features: [
{
id: "treelist-sorting",
name: "Sorting",
description: "Support for column sorting",
depends: ["columnsorter"]
},
{
id: "treelist-filtering",
name: "Filtering",
description: "Support for record filtering",
depends: ["filtermenu"]
},
{
id: "treelist-columnmenu",
name: "Column menu",
description: "Support for header column menu",
depends: ["columnmenu"]
},
{
id: "treelist-editing",
name: "Editing",
description: "Support for record editing",
depends: [
"editable",
"window",
"textbox",
"form"
]
},
{
id: "treelist-selection",
name: "Selection",
description: "Support for row selection",
depends: ["selectable"]
},
{
id: "treelist-column-resize",
name: "Column resizing",
description: "Support for column resizing",
depends: ["resizable"]
},
{
id: "treelist-dragging",
name: "Drag & Drop",
description: "Support for drag & drop of rows",
depends: ["treeview.draganddrop"]
},
{
id: "treelist-excel-export",
name: "Excel export",
description: "Export data as Excel spreadsheet",
depends: ["excel"]
},
{
id: "treelist-pdf-export",
name: "PDF export",
description: "Export data as PDF",
depends: [
"pdf",
"drawing",
"progressbar"
]
},
{
id: "treelist-paging",
name: "Paging",
description: "Support for treelist paging",
depends: ["pager"]
}
]
};
(function($, undefined) {
var data = kendo.data;
var encode = kendo.htmlEncode;
var kendoDom = kendo.dom;
var kendoDomElement = kendoDom.element;
var kendoTextElement = kendoDom.text;
var kendoHtmlElement = kendoDom.html;
var outerWidth = kendo._outerWidth;
var keys = $.extend({ F10: 121 }, kendo.keys);
var outerHeight = kendo._outerHeight;
var ui = kendo.ui;
var DataBoundWidget = ui.DataBoundWidget;
var DataSource = data.DataSource;
var ObservableArray = data.ObservableArray;
var Query = data.Query;
var Model = data.Model;
var browser = kendo.support.browser;
var kendoTemplate = kendo.template;
var toCamelCase = kendo.toCamelCase;
var activeElement = kendo._activeElement;
var touchDevice = kendo.support.touch;
var isArray = Array.isArray;
var extend = $.extend;
var map = $.map;
var grep = $.grep;
var inArray = $.inArray;
var isPlainObject = $.isPlainObject;
var push = Array.prototype.push;
var STRING = "string";
var CHANGE = "change";
var ITEM_CHANGE = "itemChange";
var ERROR = "error";
var PROGRESS = "progress";
var DOT = ".";
var NS = ".kendoTreeList";
var CLICK = "click";
var INPUT = "input";
var BEFORE_EDIT = "beforeEdit";
var EDIT = "edit";
var PAGE = "page";
var PAGE_CHANGE = "pageChange";
var SAVE = "save";
var SAVE_CHANGES = "saveChanges";
var EXPAND = "expand";
var COLLAPSE = "collapse";
var CELL_CLOSE = "cellClose";
var REMOVE = "remove";
var DATA_CELL = "td:not(.k-group-cell):not(.k-hierarchy-cell):visible,th:not(.k-group-cell):not(.k-hierarchy-cell):visible";
var FILTER_CELL = ".k-filter-row td:not(.k-group-cell):not(.k-hierarchy-cell):visible,.k-filter-row th:not(.k-group-cell):not(.k-hierarchy-cell):visible";
var DATABINDING = "dataBinding";
var DATABOUND = "dataBound";
var CANCEL = "cancel";
var TABINDEX = "tabIndex";
var FILTERMENUINIT = "filterMenuInit";
var FILTERMENUOPEN = "filterMenuOpen";
var COLUMNHIDE = "columnHide";
var COLUMNSHOW = "columnShow";
var HEADERCELLS = "th.k-header";
var COLUMNREORDER = "columnReorder";
var COLUMNRESIZE = "columnResize";
var COLUMNMENUINIT = "columnMenuInit";
var COLUMNMENUOPEN = "columnMenuOpen";
var COLUMNLOCK = "columnLock";
var COLUMNUNLOCK = "columnUnlock";
var FILTER = "filter";
var NAVIGATE = "navigate";
var SORT = "sort";
var PARENTIDFIELD = "parentId";
var DRAGSTART = "dragstart";
var DRAG = "drag";
var DROP = "drop";
var DRAGEND = "dragend";
var NAVROW = "tr:visible";
var NAVCELL = "td:visible";
var NAVHEADER = "th:visible";
var NORECORDSCLASS = "k-grid-norecords";
var ITEMROW = "tr:not(.k-footer-template):visible";
var isRtl = false;
var HEIGHT = "height";
var INCELL = "incell";
var INLINE = "inline";
var POPUP = "popup";
var TABLE = "table";
var CHECKBOX = "k-checkbox";
var CHECKBOXINPUT = "input[data-role='checkbox']." + CHECKBOX;
var SELECTCOLUMNTMPL = "<input class=\"" + CHECKBOX + "\" data-role=\"checkbox\" aria-label=\"Select row\" aria-checked=\"false\" type=\"checkbox\">";
var SELECTCOLUMNHEADERTMPL = "<input class=\"" + CHECKBOX + "\" data-role=\"checkbox\" aria-label=\"Select all rows\" aria-checked=\"false\" type=\"checkbox\">";
var DRAGHANDLECOLUMNTMPL = () => kendo.ui.icon("reorder");
var SELECTED = "k-selected";
var whitespaceRegExp = "[\\x20\\t\\r\\n\\f]";
var filterRowRegExp = new RegExp("(^|" + whitespaceRegExp + ")" + "(k-filter-row)" + "(" + whitespaceRegExp + "|$)");
var ICON_REFRESH_SELECTOR = "[class*='-i-arrow-rotate-cw']";
var ICON_EXPAND_COLLAPSE_SELECTOR = "[ref-treelist-expand-collapse-icon]";
var CARET_ALT_RIGHT = "caret-alt-right";
var CARET_ALT_LEFT = "caret-alt-left";
var ARIA_LABEL = "aria-label";
var ID = "id", PX = "px", TR = "tr", DIV = "div", ARIA_LABEL = "aria-label", ARIA_OWNS = "aria-owns", ARIA_ROWCOUNT = "aria-rowcount", ARIA_COLCOUNT = "aria-colcount", ARIA_CONTROLS = "aria-controls", ARIA_COLINDEX = "aria-colindex", ARIA_ROWINDEX = "aria-rowindex", ARIA_EXPANDED = "aria-expanded", ARIA_CHECKED = "aria-checked", ARIA_ACTIVEDESCENDANT = "aria-activedescendant", ROLE = "role", NONE = "none", ROW = "row", ROWGROUP = "rowgroup", COLUMNHEADER = "columnheader", GRIDCELL = "gridcell", BLANK_ICON_SELECTOR = "[ref-blank-icon]";
var classNames = {
wrapper: "k-treelist k-grid",
header: "k-header k-table-th",
button: "k-button",
alt: "k-table-alt-row",
editCell: "k-edit-cell",
editRow: "k-grid-edit-row",
dirtyCell: "k-dirty-cell",
toolbar: "k-toolbar",
gridToolbar: "k-grid-toolbar",
gridHeader: "k-grid-header",
gridHeaderWrap: "k-grid-header-wrap",
gridContent: "k-grid-content",
gridContentWrap: "k-grid-content",
gridFilter: "k-grid-filter-menu",
footerTemplate: "k-footer-template",
focused: "k-focus",
loading: "k-i-loading",
refresh: "arrow-rotate-cw",
retry: "k-request-retry",
selected: "k-selected",
status: "k-status",
link: "k-link",
filterable: "k-filterable",
icon: "k-icon",
iconFilter: "filter",
iconCollapse: "caret-alt-down",
iconExpand: "caret-alt-right",
iconPlaceHolder: "k-treelist-toggle k-icon k-svg-icon",
input: "k-input",
dropPositions: "k-i-insert-top k-i-insert-bottom k-i-plus k-i-insert-middle",
dropTop: "insert-top",
dropBottom: "insert-bottom",
dropAdd: "plus",
dropMiddle: "insert-middle",
dropDenied: "cancel",
dragStatus: "k-drag-status",
dragClue: "k-drag-clue",
dragClueText: "k-clue-text",
headerCellInner: "k-cell-inner",
columnTitle: "k-column-title"
};
var defaultCommands = {
create: {
icon: "plus",
className: "k-grid-add",
methodName: "addRow"
},
createchild: {
icon: "plus",
className: "k-grid-add",
methodName: "addRow"
},
destroy: {
icon: "x",
className: "k-grid-remove-command",
methodName: "removeRow"
},
edit: {
icon: "pencil",
className: "k-button-primary k-grid-edit-command",
methodName: "editRow"
},
update: {
icon: "save",
className: "k-button-primary k-grid-save-command",
methodName: "saveRow"
},
canceledit: {
icon: "cancel",
className: "k-grid-cancel-command",
methodName: "_cancelEdit"
},
cancel: {
icon: "cancel-outline",
text: "Cancel changes",
className: "k-grid-cancel-changes",
methodName: "cancelChanges"
},
save: {
icon: "check",
text: "Save changes",
className: "k-grid-save-changes",
methodName: "saveChanges"
},
excel: {
icon: "file-excel",
className: "k-grid-excel",
methodName: "saveAsExcel"
},
pdf: {
icon: "file-pdf",
className: "k-grid-pdf",
methodName: "saveAsPDF"
},
search: { template: ({ message }) => "<span class='k-spacer'></span>" + "<span class='k-searchbox k-input k-grid-search'>" + kendo.ui.icon({
icon: "search",
iconClass: "k-input-icon"
}) + `<input autocomplete='off' placeholder='${message}' title='${message}' aria-label='${message}' class='k-input-inner' />` + "</span>" }
};
var defaultBodyContextMenu = [
"create",
"createChild",
"edit",
"destroy",
"separator",
"select",
"separator",
"exportPDF",
"exportExcel",
"separator",
"expandItem",
"collapseItem",
"separator"
];
var defaultHeadContextMenu = [
"sortAsc",
"sortDesc",
"separator"
];
var TreeView = kendo.Class.extend({
init: function(data, options) {
var that = this;
that.data = data || [];
that.options = extend(that.options, options);
},
options: {
defaultParentId: null,
idField: "id",
parentIdField: PARENTIDFIELD
},
childrenMap: function() {
var that = this;
var childrenMap = {};
var dataLength = that.data.length;
var dataItem;
var dataItemId;
var dataItemParentId;
var idField = that.options.idField;
var parentIdField = that.options.parentIdField;
if (that._childrenMap) {
return that._childrenMap;
}
for (var i = 0; i < dataLength; i++) {
dataItem = this.data[i];
dataItemId = dataItem[idField];
dataItemParentId = dataItem[parentIdField];
childrenMap[dataItemId] = childrenMap[dataItemId] || [];
childrenMap[dataItemParentId] = childrenMap[dataItemParentId] || [];
childrenMap[dataItemParentId].push(dataItem);
}
that._childrenMap = childrenMap;
return childrenMap;
},
idsMap: function() {
var that = this;
var idsMap = {};
var data = that.data;
var dataLength = data.length;
var dataItem;
var idField = that.options.idField;
if (that._idMap) {
return that._idMap;
}
for (var i = 0; i < dataLength; i++) {
dataItem = data[i];
idsMap[dataItem[idField]] = dataItem;
}
that.idsMap = idsMap;
return idsMap;
},
dataMaps: function() {
var that = this;
var childrenMap = {};
var data = that.data;
var dataLength = data.length;
var idsMap = {};
var dataItem;
var dataItemId;
var dataItemParentId;
var idField = that.options.idField;
var parentIdField = that.options.parentIdField;
if (that._dataMaps) {
return that._dataMaps;
}
for (var i = 0; i < dataLength; i++) {
dataItem = data[i];
dataItemId = dataItem[idField];
dataItemParentId = dataItem[parentIdField];
idsMap[dataItemId] = dataItem;
childrenMap[dataItemId] = childrenMap[dataItemId] || [];
childrenMap[dataItemParentId] = childrenMap[dataItemParentId] || [];
childrenMap[dataItemParentId].push(dataItem);
}
that._dataMaps = {
children: childrenMap,
ids: idsMap
};
return that._dataMaps;
},
rootNodes: function() {
var that = this;
var data = that.data;
var defaultParentId = that.options.defaultParentId;
var dataLength = data.length;
var rootNodes = [];
var dataItem;
var parentIdField = that.options.parentIdField;
for (var i = 0; i < dataLength; i++) {
dataItem = data[i];
if (dataItem[parentIdField] === defaultParentId) {
rootNodes.push(dataItem);
}
}
return rootNodes;
},
removeCollapsedSubtreesFromRootNodes: function(options) {
options = options || {};
var that = this;
var rootNodes = that.rootNodes();
var result = [];
var prunedTree;
that._childrenMap = options.childrenMap = options.childrenMap || that.childrenMap();
options.maxDepth = options.maxDepth || Infinity;
for (var i = 0; i < rootNodes.length; i++) {
prunedTree = that.removeCollapsedSubtrees(rootNodes[i], options);
result = result.concat(prunedTree);
}
return result;
},
removeCollapsedSubtrees: function(rootNode, options) {
options = options || {};
var that = this;
var result = [];
var childIdx;
var prunedTree;
var childrenMap = options.childrenMap || {};
var maxDepth = options.maxDepth || Infinity;
var idField = that.options.idField;
var children = childrenMap[rootNode[idField]] || [];
var expanded = isUndefined(rootNode.expanded) ? options.expanded : rootNode.expanded;
result.push(rootNode);
if (children && expanded) {
for (childIdx = 0; childIdx < children.length; childIdx++) {
if (result.length >= maxDepth) {
break;
}
prunedTree = that.removeCollapsedSubtrees(children[childIdx], options);
result = result.concat(prunedTree);
}
}
return result;
}
});
var TreeQuery = function(data) {
this.data = data || [];
};
TreeQuery.prototype = new Query();
TreeQuery.prototype.constructor = TreeQuery;
TreeQuery.process = function(data, options, inPlace) {
options = options || {};
var query = new TreeQuery(data);
var group = options.group;
var sort = Query.normalizeGroup(group || []).concat(Query.normalizeSort(options.sort || []));
var filterCallback = options.filterCallback;
var filter = options.filter;
var skip = options.skip;
var take = options.take;
var total;
var childrenMap;
var filteredChildrenMap;
var view;
var prunedData;
if (sort && inPlace) {
query = query.sort(sort, undefined, undefined, inPlace);
}
if (filter) {
query = query.filter(filter);
if (filterCallback) {
query = filterCallback(query);
}
total = query.toArray().length;
}
if (sort && !inPlace) {
query = query.sort(sort);
if (group) {
data = query.toArray();
}
}
if (options.processFromRootNodes) {
view = new TreeView(query.toArray(), options);
if (filter) {
filteredChildrenMap = view.childrenMap();
}
prunedData = view.removeCollapsedSubtreesFromRootNodes({
childrenMap: filter || sort && sort.length ? undefined : options.childrenMap,
expanded: options.expanded,
maxDepth: skip + take || Infinity
});
childrenMap = view.childrenMap();
query = new TreeQuery(prunedData);
}
if (skip !== undefined && take !== undefined) {
query = query.range(skip, take);
}
if (group) {
query = query.group(group, data);
}
return {
total,
data: query.toArray(),
childrenMap,
filteredChildrenMap
};
};
var TreeListModel = Model.define({
id: "id",
parentId: PARENTIDFIELD,
fields: {
id: { type: "number" },
parentId: {
type: "number",
nullable: true
}
},
init: function(value) {
Model.fn.init.call(this, value);
this._loaded = false;
if (!this.parentIdField) {
this.parentIdField = PARENTIDFIELD;
}
this.parentId = this.get(this.parentIdField);
},
accept: function(data) {
Model.fn.accept.call(this, data);
this.parentId = this.get(this.parentIdField);
},
set: function(field, value, initiator) {
if (field == PARENTIDFIELD && this.parentIdField != PARENTIDFIELD) {
this[this.parentIdField] = value;
}
Model.fn.set.call(this, field, value, initiator);
if (field == this.parentIdField) {
this.parentId = this.get(this.parentIdField);
}
},
loaded: function(value) {
if (value !== undefined) {
this._loaded = value;
} else {
return this._loaded;
}
},
shouldSerialize: function(field) {
return Model.fn.shouldSerialize.call(this, field) && field !== "_loaded" && field != "_error" && field != "_edit" && !(this.parentIdField !== "parentId" && field === "parentId");
}
});
TreeListModel.parentIdField = PARENTIDFIELD;
TreeListModel.define = function(base, options) {
if (options === undefined) {
options = base;
base = TreeListModel;
}
var parentId = options.parentId || PARENTIDFIELD;
options.parentIdField = parentId;
var model = Model.define(base, options);
if (parentId) {
model.parentIdField = parentId;
}
return model;
};
function is(field) {
return function(object) {
return object[field];
};
}
function not(func) {
return function(object) {
return !func(object);
};
}
var TreeListDataSource = DataSource.extend({
init: function(options) {
options = options || {};
var that = this;
that._dataMaps = that._getDataMaps();
options.schema = extend(true, {}, {
modelBase: TreeListModel,
model: TreeListModel
}, options.schema);
DataSource.fn.init.call(this, options);
},
_addRange: function() {},
_createNewModel: function(data) {
var that = this;
var model = {};
var fromModel = data instanceof Model;
var parentIdField = this._modelParentIdField();
if (fromModel) {
model = data;
}
model = DataSource.fn._createNewModel.call(this, model);
if (!fromModel) {
if (data.parentId) {
data[model.parentIdField] = data.parentId;
} else if (that._isPageable() && data[parentIdField]) {
data[model.parentIdField] = data[parentIdField];
}
model.accept(data);
}
return model;
},
_shouldWrap: function() {
return true;
},
_push: function(result, operation) {
var data = DataSource.fn._readData.call(this, result);
if (!data) {
data = result;
}
this[operation](data);
},
_getData: function() {
return this._data || [];
},
_readData: function(newData) {
var that = this;
var data = that._isPageable() ? that._getData().toJSON() : that.data();
newData = DataSource.fn._readData.call(this, newData);
this._replaceData((data.toJSON ? data.toJSON() : data).concat(newData), data);
if (newData instanceof ObservableArray) {
return newData;
}
return data;
},
_replaceData: function(source, target) {
var sourceLength = source.length;
for (var i = 0; i < sourceLength; i++) {
target[i] = source[i];
}
target.length = sourceLength;
},
_readAggregates: function(data) {
var result = extend(this._aggregateResult, this.reader.aggregates(data));
if ("" in result) {
result[this._defaultParentId()] = result[""];
delete result[""];
}
return result;
},
read: function(data) {
var that = this;
if (that._isPageable()) {
that._dataMaps = {};
if (!that._modelOptions().expanded) {
that._skip = 0;
that._page = 1;
that._collapsedTotal = undefined;
}
}
return DataSource.fn.read.call(that, data);
},
remove: function(root) {
this._removeChildData(root);
this._removeFromDataMaps(root);
return DataSource.fn.remove.call(this, root);
},
_removeChildData: function(model, removePristine) {
var that = this;
var pageable = that._isPageable();
var data = pageable ? this._getData() : this.data();
var childrenMap = pageable ? that._getChildrenMap() || that.childrenMap(data) : that._childrenMap(data);
var items = this._subtree(childrenMap, model.id);
var shouldRemovePristine = isUndefined(removePristine) ? false : removePristine;
var removedItems = this._removeItems(items, shouldRemovePristine);
that._removeFromDataMaps(removedItems);
},
pushDestroy: function(items) {
var that = this;
if (!isArray(items)) {
items = [items];
}
for (var i = 0; i < items.length; i++) {
that._removeChildData(items[i], true);
that._removeFromDataMaps(items[i]);
}
DataSource.fn.pushDestroy.call(that, items);
},
insert: function(index, model) {
var that = this;
var newModel = that._createNewModel(model);
that._insertInDataMaps(newModel);
return DataSource.fn.insert.call(that, index, newModel);
},
_filterCallback: function(query) {
var that = this;
var i, item;
var map = {};
var result = [];
var data = query.toArray();
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var pageable = that._isPageable();
var parentSubtree = [];
var parent;
for (i = 0; i < data.length; i++) {
item = data[i];
if (pageable) {
parentSubtree = [];
if (!map[item[idField]]) {
map[item[idField]] = true;
parentSubtree.push(item);
}
parent = that._parentNode(item);
while (parent) {
if (!map[parent[idField]]) {
map[parent[idField]] = true;
parentSubtree.unshift(parent);
parent = that._parentNode(parent);
} else {
break;
}
}
if (parentSubtree.length) {
result = result.concat(parentSubtree);
}
} else {
while (item) {
if (!map[item[idField]]) {
map[item[idField]] = true;
result.push(item);
}
if (!map[item[parentIdField]]) {
map[item[parentIdField]] = true;
item = this.parentNode(item);
if (item) {
result.push(item);
}
} else {
break;
}
}
}
}
return new Query(result);
},
_subtree: function(map, id) {
var that = this;
var result = map[id] || [];
var defaultParentId = that._defaultParentId();
var idField = that._modelIdField();
for (var i = 0, len = result.length; i < len; i++) {
if (result[i][idField] !== defaultParentId) {
result = result.concat(that._subtree(map, result[i][idField]));
}
}
return result;
},
_childrenMap: function(data) {
var map = {};
var i, item, id, parentId;
data = this._observeView(data);
for (i = 0; i < data.length; i++) {
item = data[i];
id = item.id;
parentId = item.parentId;
map[id] = map[id] || [];
map[parentId] = map[parentId] || [];
map[parentId].push(item);
}
return map;
},
childrenMap: function(data) {
var view = this._createTreeView(data);
var map = view.childrenMap();
return map;
},
_getChildrenMap: function() {
var that = this;
var dataMaps = that._getDataMaps();
return dataMaps.children;
},
_initIdsMap: function(data) {
var that = this;
var dataMaps = that._getDataMaps();
if (isUndefined(dataMaps.ids)) {
dataMaps.ids = that._idsMap(data);
}
return dataMaps.ids;
},
_idsMap: function(data) {
var view = this._createTreeView(data);
var map = view.idsMap();
return map;
},
_getIdsMap: function() {
var that = this;
var dataMaps = that._getDataMaps();
return dataMaps.ids || {};
},
_getFilteredChildrenMap: function() {
var that = this;
var dataMaps = that._getDataMaps();
return dataMaps.filteredChildren;
},
_setFilteredChildrenMap: function(map) {
var that = this;
var dataMaps = that._getDataMaps();
dataMaps.filteredChildren = map;
},
_initDataMaps: function(data) {
var that = this;
var view = that._createTreeView(data);
that._dataMaps = view.dataMaps();
return that._dataMaps;
},
_initChildrenMapForParent: function(parent) {
var that = this;
var data = that._getData();
var childrenMap = that._getChildrenMap();
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var parentId = (parent || {})[idField];
if (childrenMap && parent) {
childrenMap[parentId] = [];
for (var i = 0; i < data.length; i++) {
if (data[i][parentIdField] === parentId) {
childrenMap[parentId].push(data[i]);
}
}
}
},
_getDataMaps: function() {
var that = this;
that._dataMaps = that._dataMaps || {};
return that._dataMaps;
},
_createTreeView: function(data, options) {
var view = new TreeView(data, extend(options, this._defaultTreeModelOptions()));
return view;
},
_defaultTreeModelOptions: function() {
var that = this;
var modelOptions = that._modelOptions();
return {
defaultParentId: that._defaultParentId(),
idField: that._modelIdField(),
parentIdField: that._modelParentIdField(),
expanded: modelOptions.expanded
};
},
_defaultDataItemType: function() {
return this.reader.model || kendo.data.ObservableObject;
},
_calculateAggregates: function(data, options) {
options = options || {};
var that = this;
var result = {};
var item, subtree, i;
var filter = options.filter;
var skip = options.skip;
var take = options.take;
var maxDepth = !isUndefined(skip) && !isUndefined(take) ? skip + take : Infinity;
var pageable = that._isPageable();
var filteredChildrenMap = options.filteredChildrenMap;
var childrenMap = options.childrenMap;
var pageableChildrenMap;
if (pageable) {
if (isUndefined(options.aggregate)) {
return result;
}
if (filteredChildrenMap) {
pageableChildrenMap = filteredChildrenMap;
} else if (childrenMap) {
pageableChildrenMap = childrenMap;
} else {
pageableChildrenMap = that.childrenMap(that._getData());
}
}
if (!pageable && filter) {
data = Query.process(data, {
filter,
filterCallback: this._filterCallback.bind(this)
}).data;
}
var map = pageable ? pageableChildrenMap : that._childrenMap(data);
result[this._defaultParentId()] = new Query(this._subtree(map, this._defaultParentId())).aggregate(options.aggregate);
for (i = 0; i < data.length; i++) {
if (i >= maxDepth) {
break;
}
item = data[i];
subtree = this._subtree(map, item.id);
result[item.id] = new Query(subtree).aggregate(options.aggregate);
}
return result;
},
_queryProcess: function(data, options) {
var that = this;
var result = {};
options = options || {};
options.filterCallback = this._filterCallback.bind(this);
if (that._isPageable()) {
return that._processPageableQuery(data, options);
} else {
var defaultParentId = this._defaultParentId();
result = Query.process(data, options);
var map = this._childrenMap(result.data);
var hasLoadedChildren, i, item, children;
data = map[defaultParentId] || [];
for (i = 0; i < data.length; i++) {
item = data[i];
if (item.id === defaultParentId) {
continue;
}
children = map[item.id];
hasLoadedChildren = !!(children && children.length);
if (!item.loaded()) {
item.loaded(hasLoadedChildren || !item.hasChildren);
}
if (item.loaded() || item.hasChildren !== true) {
item.hasChildren = hasLoadedChildren;
}
if (hasLoadedChildren) {
data = data.slice(0, i + 1).concat(children, data.slice(i + 1));
}
}
result.data = data;
}
return result;
},
_processPageableQuery: function(data, options) {
var that = this;
var dataMaps = that._getDataMaps();
var result;
var filteredChildrenMap;
if (that._getData() !== data || !dataMaps.children || !dataMaps.ids) {
dataMaps = that._initDataMaps(that._getData());
}
options.childrenMap = dataMaps.children || {};
options.idsMap = dataMaps.ids || {};
result = that._processTreeQuery(data, options);
that._replaceWithObservedData(result.data, data);
that._processDataItemsState(result.data, result.childrenMap);
that._replaceItemsInDataMaps(result.data);
result.dataToAggregate = that._dataToAggregate(result.data, options);
if (options.filter || that.filter()) {
filteredChildrenMap = result.filteredChildrenMap;
that._replaceInMapWithObservedData(filteredChildrenMap, data);
that._setFilteredChildrenMap(filteredChildrenMap);
options.filteredChildrenMap = filteredChildrenMap;
that._calculateCollapsedTotal(result.data);
} else {
that._collapsedTotal = undefined;
}
return result;
},
_dataToAggregate: function(data) {
var that = this;
var firstDataItem = data[0] || {};
var firstItemParents = that._parentNodes(firstDataItem);
var dataToAggregate = firstItemParents.concat(data);
return dataToAggregate;
},
_replaceItemsInDataMaps: function(observableArray) {
var that = this;
var view = isArray(observableArray) ? observableArray : [observableArray];
var itemType = that._defaultDataItemType();
var defaultParentId = that._defaultParentId();
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var dataMaps = that._getDataMaps();
var item;
var parents;
var directParent;
for (var viewIndex = 0; viewIndex < view.length; viewIndex++) {
item = view[viewIndex];
if (!(item instanceof itemType)) {
continue;
}
that._insertInIdsMap(item);
parents = that._parentNodes(item);
directParent = parents && parents.length ? parents[parents.length - 1] : undefined;
if (item[parentIdField] === defaultParentId) {
that._replaceInMap(dataMaps.children, defaultParentId, item, itemType);
} else if (directParent) {
that._replaceInMap(dataMaps.children, directParent[idField], item, itemType);
}
}
},
_replaceInMap: function(map, id, replacement, itemType) {
var idField = this._modelIdField();
map[id] = map[id] || [];
itemType = itemType || this._defaultDataItemType();
var itemInArray = map[id].filter(function(element) {
return replacement[idField] === element[idField];
})[0];
var itemIndex = itemInArray ? map[id].indexOf(itemInArray) : -1;
if (itemIndex !== -1 && !(itemInArray instanceof itemType)) {
map[id][itemIndex] = replacement;
}
},
_replaceWithObservedData: function(dataToReplace, replacementArray) {
var that = this;
var idsMap = that._getDataMaps().ids || {};
var idField = that._modelIdField();
var itemType = that._defaultDataItemType();
var itemToReplace;
var itemToReplaceId;
var dataItem;
var dataItemIndex;
var observableItem;
for (var i = 0; i < dataToReplace.length; i++) {
itemToReplace = dataToReplace[i];
itemToReplaceId = itemToReplace[idField];
if (!(itemToReplace instanceof itemType)) {
if (!(idsMap[itemToReplaceId] instanceof itemType)) {
dataItem = that._getById(itemToReplaceId);
dataItemIndex = replacementArray.indexOf(dataItem);
if (dataItem && dataItemIndex !== -1) {
observableItem = replacementArray.at(dataItemIndex);
dataToReplace[i] = observableItem;
}
} else {
dataToReplace[i] = idsMap[itemToReplaceId];
}
}
}
},
_replaceInMapWithObservedData: function(map, replacementArray) {
var that = this;
for (var key in map) {
that._replaceWithObservedData(map[key], replacementArray);
}
},
_insertInDataMaps: function(item) {
var that = this;
if (that._isPageable()) {
that._insertInIdsMap(item);
that._insertInChildrenMap(item);
}
},
_insertInIdsMap: function(item) {
var that = this;
var idsMap = that._getIdsMap();
var idField = that._modelIdField();
if (!isUndefined(item[idField])) {
idsMap[item[idField]] = item;
}
},
_insertInChildrenMap: function(item, index) {
var that = this;
var childrenMap = that._getChildrenMap() || {};
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var itemId = item[idField];
var parentId = item[parentIdField];
index = index || 0;
childrenMap[itemId] = childrenMap[itemId] || [];
childrenMap[parentId] = childrenMap[parentId] || [];
childrenMap[parentId].splice(index, 0, item);
},
_removeFromDataMaps: function(items) {
var that = this;
items = isArray(items) ? items : [items];
if (that._isPageable()) {
for (var i = 0; i < items.length; i++) {
that._removeFromIdsMap(items[i]);
that._removeFromChildrenMap(items[i]);
}
}
},
_removeFromIdsMap: function(item) {
var that = this;
var idsMap = that._getIdsMap();
var idField = that._modelIdField();
if (!isUndefined(item[idField])) {
idsMap[item[idField]] = undefined;
}
},
_removeFromChildrenMap: function(item) {
var that = this;
var childrenMap = that._getChildrenMap() || {};
var parentIdField = that._modelParentIdField();
var parentId = item[parentIdField];
childrenMap[parentId] = childrenMap[parentId] || [];
var itemIndex = that._indexInChildrenMap(item);
if (itemIndex !== -1) {
childrenMap[parentId].splice(itemIndex, 1);
}
},
_indexInChildrenMap: function(item) {
var that = this;
return that._itemIndexInMap(item, that._getChildrenMap());
},
_itemIndexInMap: function(item, dataMap) {
var that = this;
var map = dataMap || {};
var parentIdField = that._modelParentIdField();
var parentId = item[parentIdField];
map[parentId] = map[parentId] || [];
var itemInArray = map[parentId].filter(function(element) {
return item.uid === element.uid;
})[0];
var itemIndex = itemInArray ? map[parentId].indexOf(itemInArray) : -1;
return itemIndex;
},
_getById: function(id) {
var that = this;
var idField = that._modelIdField();
var data = that._getData();
for (var i = 0; i < data.length; i++) {
if (data[i][idField] === id) {
return data[i];
}
}
},
_isLastItemInView: function(dataItem) {
var view = this.view();
return view.length && view[view.length - 1] === dataItem;
},
_defaultPageableQueryOptions: function() {
var that = this;
var dataMaps = that._getDataMaps();
var options = {
skip: that.skip(),
take: that.take(),
page: that.page(),
pageSize: that.pageSize(),
sort: that.sort(),
filter: that.filter(),
group: that.group(),
aggregate: that.aggregate(),
filterCallback: that._filterCallback.bind(that),
childrenMap: dataMaps.children,
idsMap: dataMaps.ids
};
return options;
},
_isPageable: function() {
var pageSize = this.pageSize();
return !isUndefined(pageSize) && pageSize > 0 && !this.options.serverPaging;
},
_updateTotalForAction: function(action, items) {
var that = this;
DataSource.fn._updateTotalForAction.call(that, action, items);
if (that._isPageable()) {
that._updateCollapsedTotalForAction(action, items);
}
},
_updateCollapsedTotalForAction: function(action, items) {
var that = this;
var total = parseInt(that._collapsedTotal, 10);
if (!isNumber(that._collapsedTotal)) {
that._calculateCollapsedTotal();
return;
}
if (action === "add") {
total += items.length;
} else if (action === "remove") {
total -= items.length;
} else if (action !== "itemchange" && action !== "sync" && !that.options.serverPaging) {
total = that._calculateCollapsedTotal();
} else if (action === "sync") {
total = that._calculateCollapsedTotal();
}
that._collapsedTotal = total;
},
_setFilterTotal: function(filterTotal, setDefaultValue) {
var that = this;
DataSource.fn._setFilterTotal.call(that, filterTotal, setDefaultValue);
},
collapsedTotal: function() {
var that = this;
if (!isUndefined(that._collapsedTotal)) {
return that._collapsedTotal;
}
return that._calculateCollapsedTotal();
},
_calculateCollapsedTotal: function(filteredData) {
var that = this;
var data = that._dataWithoutCollapsedSubtrees(filteredData);
if (data.length) {
that._collapsedTotal = data.length;
}
return that._collapsedTotal;
},
_dataWithoutCollapsedSubtrees: function(filteredData) {
return this._removeCollapsedSubtrees(filteredData || this._getData());
},
_removeCollapsedSubtrees: function(data) {
var that = this;
var view = that._createTreeView(data);
var result = view.removeCollapsedSubtreesFromRootNodes({
expanded: that._modelOptions().expanded,
childrenMap: that.filter() ? that._getFilteredChildrenMap() : that._getChildrenMap()
});
return result;
},
_processTreeQuery: function(data, options) {
var result = TreeQuery.process(data, extend(options, this._defaultTreeModelOptions(), { processFromRootNodes: true }));
return result;
},
_processDataItemsState: function(data, childrenMap) {
var dataLength = data.length;
var i;
for (i = 0; i < dataLength; i++) {
this._processDataItemState(data[i], childrenMap);
}
},
_processDataItemState: function(dataItem, childrenMap) {
var defaultParentId = this._defaultParentId();
if (dataItem.id === defaultParentId) {
return;
}
var children = childrenMap[dataItem.id] || [];
var hasLoadedChildren = !!(children && children.length);
if (!dataItem.loaded) {
return;
}
if (!dataItem.loaded()) {
dataItem.loaded(hasLoadedChildren || !dataItem.hasChildren);
}
if (dataItem.loaded() || dataItem.hasChildren !== true) {
dataItem.hasChildren = hasLoadedChildren;
}
},
_queueRequest: function(options, callback) {
callback.call(this);
},
_modelLoaded: function(id) {
var model = this.get(id);
model.loaded(true);
model.hasChildren = this.childNodes(model).length > 0;
},
_modelError: function(id, e) {
this.get(id)._error = e;
},
success: function(data, requestParams) {
if (!requestParams || typeof requestParams.id == "undefined") {
this._data = this._observe([]);
}
DataSource.fn.success.call(this, data, requestParams);
this._total = this._data.length;
},
load: function(model) {
var method = "_query";
var remote = this.options.serverSorting || this.options.serverPaging || this.options.serverFiltering || this.options.serverGrouping || this.options.serverAggregates;
var defaultPromise = $.Deferred().resolve().promise();
if (model.loaded()) {
if (remote) {
return defaultPromise;
}
} else if (model.hasChildren) {
method = "read";
this._removeChildData(model);
}
return this[method]({ id: model.id }).done(this._modelLoaded.bind(this, model.id)).fail(this._modelError.bind(this, model.id));
},
contains: function(root, child) {
var that = this;
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var rootId = root[idField];
var pageable = that._isPageable();
while (child) {
if (child[parentIdField] === rootId) {
return true;
}
child = pageable ? that._parentNode(child) : that.parentNode(child);
}
return false;
},
_byParentId: function(id, defaultId) {
var result = [];
var view = this.view();
var current;
if (id === defaultId) {
return [];
}
for (var i = 0; i < view.length; i++) {
current = view.at(i);
if (current.parentId == id) {
result.push(current);
}
}
return result;
},
_defaultParentId: function() {
return this.reader.model.fn.defaults[this.reader.model.parentIdField];
},
_modelOptions: function() {
var modelOptions = (this.options.schema || {}).model || {};
return modelOptions;
},
_modelIdField: function() {
var modelOptions = this._modelOptions();
return modelOptions.id || "id";
},
_modelParentIdField: function() {
var modelOptions = this._modelOptions();
return modelOptions.parentId || PARENTIDFIELD;
},
childNodes: function(model) {
return this._byParentId(model.id, this._defaultParentId());
},
allChildNodes: function(model, result) {
var directChildren = this.data().filter(function(item) {
return item.parentId === model.id;
});
for (var i = 0; i < directChildren.length; i++) {
result.push(directChildren[i]);
this.allChildNodes(directChildren[i], result);
}
},
rootNodes: function() {
return this._byParentId(this._defaultParentId());
},
_rootNode: function(child) {
return this._parentNodes(child)[0];
},
_pageableRootNodes: function(options) {
options = options || {};
var that = this;
var defaultParentId = that._defaultParentId();
var parentIdField = that._modelParentIdField();
var result = [];
var nodesWithoutParentInView = that._nodesWithoutParentInView(options);
var node;
var root;
for (var i = 0; i < nodesWithoutParentInView.length; i++) {
node = nodesWithoutParentInView[i];
if (node[parentIdField] === defaultParentId) {
result.push(node);
} else {
root = that._rootNode(node);
if (root && result.indexOf(root) === -1) {
result.push(root);
}
}
}
return result;
},
parentNode: function(model) {
return this.get(model.parentId);
},
_parentNode: function(child) {
var that = this;
var parentIdField = that._modelParentIdField();
var idsMap = that._initIdsMap(that._getData());
var parentId = child[parentIdField];
var parent = idsMap[parentId] || that._getById(parentId);
return parent;
},
_parentNodes: function(child) {
var that = this;
var parent = that._parentNode(child);
var parents = [];
while (parent) {
parents.unshift(parent);
parent = that._parentNode(parent);
}
return parents;
},
_parentNodesNotInView: function() {
var that = this;
var view = that.view();
var result = [];
var defaultParentId = that._defaultParentId();
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var parentInView;
var parents = [];
var directParent;
var dataItem;
var dataItemId;
var dataItemParentId;
for (var i = 0; i < view.length; i++) {
dataItem = view[i];
dataItemId = dataItem[idField];
dataItemParentId = dataItem[parentIdField];
parentInView = that._parentInView(dataItemParentId);
if (!parentInView && dataItemParentId !== defaultParentId) {
parents = that._parentNodes(dataItem);
directParent = parents && parents.length ? parents[parents.length - 1] : that._getById(dataItemParentId);
if (directParent && result.indexOf(directParent) === -1) {
result.push(directParent);
}
}
}
return result;
},
_nodesWithoutParentInView: function(options) {
options = options || {};
var that = this;
var view = that.view();
var childrenMap = options.childrenMap || that.childrenMap(that._getData());
var idField = that._modelIdField();
var parentIdField = that._modelParentIdField();
var dataItem;
var parentInView;
var children = [];
var result = [];
for (var i = 0; i < view.length; i++) {
dataItem = view[i];
children = childrenMap[dataItem[idField]];
parentInView = that._parentInView(dataItem[parentIdField]);
if (!parentInView) {
result.push(dataItem);
}
}
return result;
},
_parentInView: function(parentId) {
var view = this.view();
for (var i = 0; i < view.length; i++) {
if (view[i].id === parentId) {
return view[i];
}
}
},
level: function(model) {
var result = -1;
if (!(model instanceof TreeListModel)) {
model = this.get(model);
}
do {
model = this.parentNode(model);
result++;
} while (model);
return result;
},
_pageableModelLevel: function(model) {
var that = this;
if (!model || !that._isPageable()) {
return 0;
}
var parents = that._parentNodes(model);
return parents.length;
},
filter: function(value) {
var baseFilter = DataSource.fn.filter;
if (value === undefined) {
return baseFilter.call(this, value);
}
baseFilter.call(this, value);
},
_pageableQueryOptions: function(options) {
var dataMaps = this._getDataMaps();
options.childrenMap = dataMaps.children;
options.idsMap = dataMaps.ids;
return options;
},
_flatData: function(data, skip) {
skip = this._isPageable() ? true : skip;
return DataSource.fn._flatData.call(this, data, skip);
},
data: function(data) {
var that = this;
var result = DataSource.fn.data.call(that, data);
if (that._isPageable()) {
that._initDataMaps(that._getData());
that._calculateCollapsedTotal();
}
return result;
},
cancelChanges: function(model) {
var that = this;
DataSource.fn.cancelChanges.call(that, model);
that._restorePageSizeAfterAddChild();
},
_modelCanceled: function(model) {
var that = this;
if (that._isPageable()) {
that._removeFromDataMaps(model);
}
},
_changesCanceled: function() {
var that = this;
if (that._isPageable()) {
that._initDataMaps(that._getData());
}
},
_setAddChildPageSize: function() {
var that = this;
var queryOptions = {};
if (that._isPageable()) {
that._addChildPageSize = that.pageSize() + 1;
queryOptions = that._defaultPageableQueryOptions();
queryOptions.take = that._addChildPageSize;
queryOptions.pageSize = that._addChildPageSize;
that._query(queryOptions);
}
},
_restorePageSizeAfterAddChild: function() {
var that = this;
var queryOptions = {};
if (that._isPageable()) {
if (!isUndefined(that._addChildPageSize)) {
queryOptions = that._defaultPageableQueryOptions();
queryOptions.take = that._addChildPageSize - 1;
queryOptions.pageSize = that._addChildPageSize - 1;
that._query(queryOptions);
}
}
that._addChildPageSize = undefined;
},
sync: function() {
var that = this;
return DataSource.fn.sync.call(that).then(function() {
that._restorePageSizeAfterAddChild();
});
},
_syncEnd: function() {
var that = this;
if (that._isPageable()) {
that._initDataMaps(that._getData());
}
}
});
TreeListDataSource.create = function(options) {
if (Array.isArray(options)) {
options = { data: options };
} else if (options instanceof ObservableArray) {
options = { data: options.toJSON() };
}
return options instanceof TreeListDataSource ? options : new TreeListDataSource(options);
};
function isCellVisible() {
return this.style.display !== "none";
}
function sortCells(cells) {
var indexAttr = kendo.attr("index");
return [].sort.call(cells, function(a, b) {
a = $(a);
b = $(b);
var indexA = a.attr(indexAttr);
var indexB = b.attr(indexAttr);
if (indexA === undefined) {
indexA = $(a).index();
}
if (indexB === undefined) {
indexB = $(b).index();
}
indexA = parseInt(indexA, 10);
indexB = parseInt(indexB, 10);
return indexA > indexB ? 1 : indexA < indexB ? -1 : 0;
});
}
function leafDataCells(container) {
var rows = container.find(">tr:not(.k-filter-row)");
var filter = function() {
var el = $(this);
return !el.hasClass("k-group-cell") && !el.hasClass("k-hierarchy-cell");
};
var cells = $();
if (rows.length > 1) {
cells = rows.find("th[data-index]").filter(filter);
}
cells = cells.add(rows.last().find("th").filter(filter));
return sortCells(cells);
}
function createPlaceholders(options) {
var spans = [];
var className = options.className;
const blankIcon = className === classNames.iconPlaceHolder ? { "ref-blank-icon": "" } : {};
for (var i = 0, level = options.level; i < level; i++) {
spans.push(kendoDomElement("span", {
className,
"aria-hidden": true,
...blankIcon
}));
}
return spans;
}
function columnsWidth(cols) {
var colWidth, width = 0;
for (var idx = 0, length = cols.length; idx < length; idx++) {
colWidth = cols[idx].style.width;
if (colWidth && colWidth.indexOf("%") == -1) {
width += parseInt(colWidth, 10);
}
}
return width;
}
function syncTableHeight(table1, table2) {
table1 = table1[0];
table2 = table2[0];
if (table1.rows.length && table2.rows.length && table1.rows.length !== table2.rows.length) {
var lockedHeigth = table1.offsetHeight;
var tableHeigth = table2.offsetHeight;
var row;
var diff;
if (lockedHeigth > tableHeigth) {
row = table2.rows[table2.rows.length - 1];
if (filterRowRegExp.test(row.className)) {
row = table2.rows[table2.rows.length - 2];
}
diff = lockedHeigth - tableHeigth;
} else {
row = table1.rows[table1.rows.length - 1];
if (filterRowRegExp.test(row.className)) {
row = table1.rows[table1.rows.length - 2];
}
diff = tableHeigth - lockedHeigth;
}
row.style.height = row.offsetHeight + diff + "px";
}
}
var TreeListPager = ui.Pager.extend({
options: { name: "TreeListPager" },
totalPages: function() {
var that = this;
var dataSource = that.dataSource;
if (dataSource && dataSource._filter) {
return ui.Pager.fn.totalPages.call(that);
}
return Math.ceil((that._collapsedTotal() || 0) / (that.pageSize() || 1));
},
_createDataSource: function(options) {
this.dataSource = kendo.data.TreeListDataSource.create(options.dataSource);
},
_collapsedTotal: function() {
var dataSource = this.dataSource;
return dataSource ? dataSource.collapsedTotal() || 0 : 0;
}
});
var Editor = kendo.Observable.extend({
init: function(element, options) {
kendo.Observable.fn.init.call(this);
options = this.options = extend(true, {}, this.options, options);
this.element = element;
this.bind(this.events, options);
this.model = this.options.model;
this.fields = this._fields(this.options.columns);
this._initContainer();
this.createEditable();
},
options: { renderForm: false },
events: [],
_initContainer: function() {
this.wrapper = this.element;
},
createEditable: function() {
var options = this.options;
if (options.renderForm) {
this.form = new ui.Form(this.wrapper.find(".k-treelist-form"), {
items: this.fields,
buttonsTemplate: () => "",
formData: this.model,
change: options.change
});
this.editable = this.form.editable;
} else {
this.editable = new ui.Editable(this.wrapper, {
fields: this.fields,
target: options.target,
skipFocus: options.skipFocus || false,
clearContainer: options.clearContainer,
model: this.model,
change: options.change
});
}
},
_isEditable: function(column) {
return isColumnEditable(column, this.model);
},
_fields: function(columns) {
var fields = [];
var idx, length, column;
for (idx = 0, length = columns.length; idx < length; idx++) {
column = columns[idx];
if (this._isEditable(column)) {
fields.push({
field: column.field,
format: column.format,
editor: column.editor,
editorOptions: extend(true, { format: column.format }, column.editorOptions),
label: column.title || column.field || ""
});
}
}
return fields;
},
end: function() {
return this.editable.end();
},
close: function() {
this.destroy();
},
destroy: function() {
this.editable.destroy();
this.editable.element.find("[" + kendo.attr("container-for") + "]").empty().end().removeAttr(kendo.attr("role"));
this.model = this.wrapper = this.element = this.columns = this.editable = null;
}
});
var PopupEditor = Editor.extend({
init: function(element, options) {
Editor.fn.init.call(this, element, options);
this._attachHandlers();
kendo.cycleForm(this.wrapper);
this.open();
},
events: [CANCEL, SAVE],
options: { window: {
modal: true,
resizable: false,
draggable: true,
title: "Edit",
visible: false
} },
_initContainer: function() {
var options = this.options;
var formContent = [];
this.wrapper = $("<div class=\"k-popup-edit-form\"/>").attr(kendo.attr("uid"), this.model.uid).append("<div class=\"k-edit-form-container\"/>");
if (options.template) {
this._appendTemplate(formContent);
this.fields = [];
} else {
this.options.renderForm = true;
formContent.push(kendoHtmlElement("<div class=\"k-treelist-form\"></div>"));
}
new kendoDom.Tree(this.wrapper.children()[0]).render(formContent);
this.wrapper.appendTo(options.appendTo);
this.window = new ui.Window(this.wrapper, options.window);
},
_appendTemplate: function(form) {
var template = this.options.template;
if (typeof template === STRING) {
template = kendo.unescape(template);
}
template = kendo.template(template)(this.model);
form.push(kendoHtmlElement(template));
},
_attachHandlers: function() {
var closeHandler = this._cancelProxy = this._cancel.bind(this);
this.window.wrapper.on(CLICK + NS, "button[data-command='canceledit']", this._cancelProxy);
this._saveProxy = this._save.bind(this);
this.window.wrapper.on(CLICK + NS, "button[data-command='update']", this._saveProxy);
this.window.bind("close", function(e) {
if (e.userTriggered) {
closeHandler(e);
}
});
},
_detachHandlers: function() {
this._cancelProxy = null;
this._saveProxy = null;
this.window.wrapper.off(NS);
},
_cancel: function(e) {
this.trigger(CANCEL, e);
},
_save: function() {
this.trigger(SAVE);
},
open: function() {
this.window.center().open();
},
close: function() {
this.window.bind("deactivate", this.destroy.bind(this)).close();
},
destroy: function() {
if (this.form) {
this.form.destroy();
}
this._detachHandlers();
this.window.destroy();
this.window = null;
Editor.fn.destroy.call(this);
}
});
var IncellEditor = Editor.extend({ destroy: function() {
var that = this;
that.editable.destroy();
that.editable.element.off().empty().removeAttr(kendo.attr("role"));
that.model = that.wrapper = that.element = that.columns = that.editable = null;
} });
var TreeList = DataBoundWidget.extend({
init: function(element, options, events) {
DataBoundWidget.fn.init.call(this, element, options);
if (events) {
this._events = events;
}
isRtl = kendo.support.isRtl(element);
classNames.iconExpand = isRtl ? CARET_ALT_LEFT : CARET_ALT_RIGHT;
this._dataSource(this.options.dataSource);
this._columns();
this._layout();
this._aria();
this._ariaId();
this._navigatable();
this._selectable();
this._sortable();
this._resizable();
this._filterable();
this._filterRow();
this._attachEvents();
this._toolbar();
this._scrollable();
this._reorderable();
this._columnMenu();
this._minScreenSupport();
this._draggable();
this._pageable();
if (this.options.autoBind) {
this.dataSource.fetch();
}
if (this._hasLockedColumns) {
var widget = this;
this.wrapper.addClass("k-grid-lockedcolumns");
this._resizeHandler = function() {
widget.resize();
};
$(window).on("resize" + NS, this._resizeHandler);
}
if (this.options.contextMenu) {
this._initContextMenu();
}
kendo.notify(this);
},
_draggable: function() {
var that = this;
var editable = this.options.editable;
var dataSource = that.dataSource;
var idField = dataSource._modelIdField();
var parentIdField = dataSource._modelParentIdField();
var pageable = that._isPageable();
var reorderable, clickMoveClick;
if (!editable || !editable.move) {
return;
}
reorderable = editable.move.reorderable;
if (editable.move.clickMoveClick !== false && this._hasDragHandleColumn) {
clickMoveClick = true;
}
this._dragging = new kendo.ui.HierarchicalDragAndDrop(this.wrapper, {
autoScroll: true,
holdToDrag: touchDevice,
filter: that._hasDragHandleColumn ? "[ref-treelist-drag-cell]" : "tbody>tr",
itemSelector: "tr",
allowedContainers: this.table,
clickMoveClick,
hintText: function(row) {
var text = function() {
return $(this).text().replace(/<(\/?)script([^>]*)>/gi, "");
};
var separator = "<span class='k-drag-separator'></span>";
row = row.closest("tr");
return row.children("td").map(text).toArray().join(separator);
},
contains: (function(source, destination) {
var dest = this.dataItem(destination);
var src = this.dataItem(source);
return src == dest || this.dataSource.contains(src, dest);
}).bind(this),
itemFromTarget: function(target) {
var tr = target.closest("tr");
var prevRow = tr.prev();
var nextRow = tr.next();
var first;
var last;
if (prevRow) {
first = !that.sameLevel(prevRow, tr);
}
if (nextRow) {
last = !that.sameLevel(nextRow, tr);
}
return {
item: tr,
content: tr,
first,
last
};
},
dragstart: (function(source) {
this.wrapper.addClass("k-treelist-dragging");
if (this.wrapper.find(".k-grid-content").length) {
this.wrapper.find(".k-grid-content table, .k-grid-content-locked table").css("position", "relative");
}
var model = this.dataItem(source);
return this.trigger(DRAGSTART, { source: model });
}).bind(this),
drag: (function(e) {
e.source = this.dataItem(e.source);
this.trigger(DRAG, e);
}).bind(this),
drop: (function(e) {
e.source = this.dataItem(e.source);
e.destination = this.dataItem(e.destination);
this.wrapper.removeClass("k-treelist-dragging");
if (this.wrapper.find(".k-grid-content").length) {
this.wrapper.find(".k-grid-content table, .k-grid-content-locked table").css("position", "static");
}
return this.trigger(DROP, e);
}).bind(this),
dragend: (function(e) {
var dest = this.dataItem(e.destination);
var src = this.dataItem(e.source);
var originalSrcParentId = src[parentIdField];
var originalSrcIndex = dataSource._indexInChildrenMap(src);
var position = e.position;
if (position == "over") {
if (pageable) {
dataSource._removeFromChildrenMap(src);
src[parentIdField] = dest ? dest[idField] : null;
dataSource._initChildrenMapForParent(dest);
src[parentIdField] = originalSrcParentId;
}
var isPrevented = src.set("parentId", dest ? dest.id : null);
if (pageable && isPrevented) {
dataSource._removeFromChildrenMap(src);
src[parentIdField] = originalSrcParentId;
dataSource._removeFromChildrenMap(src);
dataSource._insertInChildrenMap(src, originalSrcIndex);
}
} else {
if (position == "before") {
that.insertBefore(src, dest);
} else if (position == "after") {
that.insertAfter(src, dest);
}
}
e.source = src;
e.destination = dest;
this.trigger(DRAGEND, e);
}).bind(this),
reorderable,
dropHintContainer: function(item) {
return item.children("td:visible").eq(0);
},
dropPositionFrom: function(dropHint) {
const dropHintParent = dropHint.parent(), contents = dropHint.parent().contents(), dropHintElement = dropHint[0];
let isAfter = false;
if (dropHintParent.find(BLANK_ICON_SELECTOR).length) {
return dropHint.prevAll(BLANK_ICON_SELECTOR).length > 0 ? "after" : "before";
} else if (dropHintParent.is("[ref-treelist-drag-cell]")) {
isAfter = contents[0] !== dropHintElement;
} else {
const length = contents.length;
for (let i = 0; i < length; i++) {
if (contents[i] === dropHintElement) {
break;
}
if (contents[i].nodeType === 3) {
isAfter = true;
}
}
}
return isAfter ? "after" : "before";
}
});
},
sameLevel: function() {
return arguments[0].find(BLANK_ICON_SELECTOR).length === arguments[1].find(BLANK_ICON_SELECTOR).length;
},
insertAfter: function(nodeData, referenceNode) {
this.insertAction(nodeData, referenceNode, 1);
},
insertBefore: function(nodeData, referenceNode) {
this.insertAction(nodeData, referenceNode, 0);
},
insertAction: function(nodeData, referenceNode, indexOffset) {
var that = this;
var dataSource = that.dataSource;
var parentIdField = dataSource._modelParentIdField();
var referenceNodeIndex;
var nodeDataIndex = dataSource.indexOf(nodeData);
var pageable = that._isPageable();
var originalDestIndex = dataSource._indexInChildrenMap(referenceNode);
var destIndex;
var childrenMap = dataSource._getChildrenMap() || {};
var parentId = nodeData[parentIdField];
that._unbindDataSource();
that._unbindDataChange();
if (pageable) {
dataSource._removeFromChildrenMap(nodeData);
}
if (nodeData[parentIdField] != referenceNode[parentIdField]) {
nodeData.set("parentId", referenceNode && referenceNode.parentId ? referenceNode.parentId : null);
}
dataSource._data.splice(nodeDataIndex, 1);
referenceNodeIndex = dataSource.indexOf(referenceNode);
destIndex = referenceNodeIndex + indexOffset;
if (pageable) {
originalDestIndex += indexOffset;
if (childrenMap[parentId].length <= originalDestIndex) {
originalDestIndex = childrenMap[parentId].length;
}
dataSource._insertInChildrenMap(nodeData, originalDestIndex);
}
dataSource._data.splice(destIndex, 0, nodeData);
dataSource._destroyed.pop();
that._bindDataChange();
that._bindDataSource();
that.refresh();
},
_bindDataChange: function() {
var dataSource = this.dataSource;
if (dataSource._data && dataSource._changeHandler) {
dataSource._data.bind(CHANGE, dataSource._changeHandler);
dataSource._data.trigger(CHANGE);
}
},
_unbindDataChange: function() {
var dataSource = this.dataSource;
if (dataSource._data && dataSource._changeHandler) {
dataSource._data.unbind(CHANGE, dataSource._changeHandler);
}
},
_bindDataSource: function() {
var that = this;
var dataSource = that.dataSource;
if (dataSource) {
dataSource.bind(CHANGE, that._refreshHandler);
}
},
_unbindDataSource: function() {
var that = this;
var dataSource = that.dataSource;
if (dataSource) {
dataSource.unbind(CHANGE, that._refreshHandler);
}
},
itemFor: function(model) {
if (typeof model == "number") {
model = this.dataSource.get(model);
}
return this.tbody.find("[" + kendo.attr("uid") + "=" + model.uid + "]");
},
_itemFor: function(model) {
var that = this;
var table = that.lockedContent ? that.lockedTable : that.table;
if (typeof model == "number") {
model = this.dataSource.get(model);
}
return table.find("[" + kendo.attr("uid") + "=" + model.uid + "]");
},
_scrollable: function() {
if (this.options.scrollable) {
var scrollables = this.thead.closest(".k-grid-header-wrap");
var lockedContent = $(this.lockedContent).on("DOMMouseScroll" + NS + " mousewheel" + NS, this._wheelScroll.bind(this));
this.content.on("scroll" + NS, function() {
kendo.scrollLeft(scrollables, this.scrollLeft);
lockedContent.scrollTop(this.scrollTop);
});
this.element.find(".k-grid-content, .k-grid-content-locked").wrapAll("<div class='k-grid-container' />");
var touchScroller = kendo.touchScroller(this.content);
if (touchScroller && touchScroller.movable) {
this._touchScroller = touchScroller;
touchScroller.movable.bind("change", function(e) {
kendo.scrollLeft(scrollables, -e.sender.x);
if (lockedContent) {
lockedContent.scrollTop(-e.sender.y);
}
});
}
}
},
_wheelScroll: function(e) {
if (e.ctrlKey) {
return;
}
var delta = kendo.wheelDeltaY(e);
var lockedDiv = $(e.currentTarget);
if (delta) {
if (lockedDiv[0].scrollHeight > lockedDiv[0].clientHeight && (lockedDiv[0].scrollTop < lockedDiv[0].scrollHeight - lockedDiv[0].clientHeight && delta < 0 || lockedDiv[0].scrollTop > 0 && delta > 0)) {
e.preventDefault();
}
lockedDiv.one("wheel" + NS, false);
this.content.scrollTop(this.content.scrollTop() + -delta);
}
},
_progress: function() {
var messages = this.options.messages;
if (!this.tbody.find("tr").length) {
this._showStatus(kendo.template(({ className, messages }) => `<span class='${className}'></span> ${encode(messages.loading)}`)({
className: classNames.icon + " " + classNames.loading,
messages
}));
}
},
_error: function(e) {
if (!this.dataSource.rootNodes().length) {
this._render({ error: e });
}
},
refresh: function(e) {
var that = this;
e = e || {};
if (e.action == "itemchange" && this.editor) {
return;
}
if (this.trigger(DATABINDING)) {
return;
}
var current = $(this.current());
var isCurrentInHeader = false;
var currentIndex, currentRowIndex;
this._cancelEditor();
this._render();
this._adjustHeight();
if (this.options.navigatable) {
if (this._isActiveInTable() || this.editor) {
isCurrentInHeader = current.is("th");
currentIndex = isCurrentInHeader ? current.parent().children(":not(.k-group-cell)").index(current[0]) : Math.max(this.cellIndex(current), 0);
currentRowIndex = !isCurrentInHeader && current.parent().index();
}
this._restoreCurrent(currentIndex, isCurrentInHeader, currentRowIndex);
}
if (that._checkBoxSelection) {
that._deselectCheckRows(that.items(), true);
}
that._aria();
this.trigger(DATABOUND);
},
items: function() {
if (this._hasLockedColumns) {
return this._items(this.tbody).add(this._items(this.lockedTable));
} else {
return this._items(this.tbody);
}
},
_items: function(container) {
return container.find("tr[data-uid]").filter(function() {
return !$(this).hasClass(classNames.footerTemplate);
});
},
_footerItems: function() {
var container = this.tbody;
if (this._hasLockedColumns) {
container = container.add(this.lockedTable);
}
return container.find("tr").filter(function() {
return $(this).hasClass(classNames.footerTemplate);
});
},
dataItems: function() {
var dataItems = kendo.ui.DataBoundWidget.fn.dataItems.call(this);
if (this._hasLockedColumns) {
var n = dataItems.length, tmp = new Array(2 * n);
for (var i = n; --i >= 0;) {
tmp[i] = tmp[i + n] = dataItems[i];
}
dataItems = tmp;
}
return dataItems;
},
_showNoRecordsTemplate: function() {
var wrapper = "<div class=\"{0}\">{1}</div>";
var defaultTemplate = "<div class=\"k-grid-norecords-template\"{1}>{0}</div>";
var scrollableNoGridHeightStyles = this.options.scrollable && !this.wrapper[0].style.height ? ` ${kendo.attr("style-margin")}="0 auto" ${kendo.attr("style-position")}="static"` : "";
var template;
var noRecordsElement;
this._contentTree.render([]);
if (this._hasLockedColumns) {
this._lockedContentTree.render([]);
}
template = kendo.format(defaultTemplate, this.options.messages.noRows, scrollableNoGridHeightStyles);
noRecordsElement = $(kendo.template(() => kendo.format(wrapper, NORECORDSCLASS, template))({}));
kendo.applyStylesFromKendoAttributes(noRecordsElement, ["margin", "position"]);
noRecordsElement.insertAfter(this.table);
},
_showStatus: function(message) {
var status = this.element.find(".k-status");
var content = $(this.content).add(this.lockedContent);
if (!status.length) {
status = $("<div class='k-status' role='alert' aria-live='polite' />").appendTo(this.element);
}
this._contentTree.render([]);
if (this._hasLockedColumns) {
this._lockedContentTree.render([]);
}
content.hide();
status.html(message);
},
_hideStatus: function() {
this.element.find(".k-status").remove();
this._hideNoRecordsTempalte();
$(this.content).add(this.lockedContent).show();
},
_hideNoRecordsTempalte: function() {
this.element.find("." + NORECORDSCLASS).remove();
},
_adjustHeight: function() {
var that = this;
var element = this.element;
var contentWrap = element.find(DOT + classNames.gridContentWrap);
var header = element.find(DOT + classNames.gridHeader);
var toolbar = element.find(DOT + classNames.gridToolbar);
var status = element.find(DOT + classNames.status);
var pagerHeight = that._isPageable() && that.pager && that.pager.element.is(":visible") ? outerHeight(that.pager.element) : 0;
var height;
var scrollbar = kendo.support.scrollbar();
element.css(HEIGHT, this.options.height);
var isHeightSet = function(el) {
var initialHeight, newHeight;
if (el[0].style.height) {
return true;
} else {
initialHeight = el.height();
}
el.height("auto");
newHeight = el.height();
el.height("");
return initialHeight != newHeight;
};
if (isHeightSet(element)) {
height = that.options.hasHeader ? element.height() - outerHeight(header) - outerHeight(toolbar) - outerHeight(status) - pagerHeight : element.height() - outerHeight(toolbar) - outerHeight(status) - pagerHeight;
contentWrap.height(height);
if (this._hasLockedColumns) {
scrollbar = this.table[0].offsetWidth > this.table.parent()[0].clientWidth ? scrollbar : 0;
this.lockedContent.height(height - scrollbar);
}
}
},
_resize: function(size, force) {
this._applyLockedContainersWidth();
this._adjustHeight();
if (this.pager && this.pager.element) {
this.pager.resize(force);
}
},
_minScreenSupport: function() {
var any = this.hideMinScreenCols();
if (any) {
this.minScreenResizeHandler = this.hideMinScreenCols.bind(this);
$(window).on("resize", this.minScreenResizeHandler);
}
},
_iterateMinScreenCols: function(cols, screenWidth) {
var any = false;
for (var i = 0; i < cols.length; i++) {
var col = cols[i];
var minWidth = col.minScreenWidth;
if (minWidth !== undefined && minWidth !== null) {
any = true;
if (minWidth > screenWidth) {
this.hideColumn(col);
} else {
this.showColumn(col);
}
}
if (!col.hidden && col.columns) {
any = this._iterateMinScreenCols(col.columns, screenWidth) || any;
}
}
return any;
},
hideMinScreenCols: function() {
var cols = this.columns, screenWidth = window.innerWidth > 0 ? window.innerWidth : screen.width;
return this._iterateMinScreenCols(cols, screenWidth);
},
destroy: function() {
this._destroyColumnAttachments();
DataBoundWidget.fn.destroy.call(this);
var dataSource = this.dataSource;
dataSource.unbind(CHANGE, this._refreshHandler);
dataSource.unbind(ERROR, this._errorHandler);
dataSource.unbind(PROGRESS, this._progressHandler);
if (this._navigatableTables) {
this._navigatableTables.off(NS);
this._navigatableTables = null;
this._headertables = null;
}
this._current = null;
if (this._resizeHandler) {
$(window).off("resize" + NS, this._resizeHandler);
}
if (this._dragging) {
this._dragging.destroy();
this._dragging = null;
}
if (this.resizable) {
this.resizable.destroy();
this.resizable = null;
}
if (this.reorderable) {
this.reorderable.destroy();
this.reorderable = null;
}
if (this._draggableInstance && this._draggableInstance.element) {
this._draggableInstance.destroy();
this._draggableInstance = null;
}
if (this.selectable) {
this.selectable.destroy();
}
if (this._userEvents) {
this._userEvents.destroy();
this._userEvents = null;
}
if (this.minScreenResizeHandler) {
$(window).off("resize", this.minScreenResizeHandler);
}
this._destroyEditor();
this.element.off(NS);
if (this.wrapper) {
this.wrapper.off(NS);
}
if (this._touchScroller) {
this._touchScroller.destroy();
}
this._destroyPager();
if (dataSource) {
dataSource._dataMaps = null;
}
this._autoExpandable = null;
this._refreshHandler = this._errorHandler = this._progressHandler = this._dataSourceFetchProxy = null;
this.thead = this.content = this.tbody = this.table = this.element = this.lockedHeader = this.lockedContent = null;
this._statusTree = this._headerTree = this._contentTree = this._lockedHeaderColsTree = this._lockedContentColsTree = this._lockedHeaderTree = this._lockedContentTree = null;
kendo.destroy(this.wrapper);
},
options: {
name: "TreeList",
columns: [],
autoBind: true,
scrollable: true,
selectable: false,
sortable: false,
toolbar: null,
height: null,
columnMenu: false,
messages: {
noRows: "No records to display",
loading: "Loading...",
requestFailed: "Request failed.",
retry: "Retry",
dragHandleLabel: "Drag row",
commands: {
edit: "Edit",
update: "Save",
canceledit: "Cancel",
create: "Add new record",
createchild: "Add child record",
destroy: "Delete",
excel: "Export to Excel",
pdf: "Export to PDF",
search: "Search...",
select: "Select",
selectRow: "Select Row",
selectAllRows: "All rows",
clearSelection: "Clear selection",
exportPdf: "Export to PDF",
exportExcel: "Export to Excel",
sortAsc: "Sort Ascending",
sortDesc: "Sort Descending",
expandItem: "Expand Item",
collapseItem: "Collapse Item"
},
sortHeader: "Press Enter to sort",
filterCellTitle: "filter cell"
},
excel: { hierarchy: true },
resizable: false,
search: false,
filterable: false,
editable: false,
reorderable: false,
pageable: false,
renderAllRows: true,
rowTemplate: null,
altRowTemplate: null,
hasHeader: true,
contextMenu: false
},
events: [
CHANGE,
BEFORE_EDIT,
EDIT,
PAGE,
SAVE,
SAVE_CHANGES,
REMOVE,
EXPAND,
COLLAPSE,
DATABINDING,
DATABOUND,
CANCEL,
DRAGSTART,
DRAG,
DROP,
DRAGEND,
FILTERMENUINIT,
ITEM_CHANGE,
CELL_CLOSE,
FILTERMENUOPEN,
COLUMNHIDE,
COLUMNSHOW,
COLUMNREORDER,
COLUMNRESIZE,
COLUMNMENUINIT,
COLUMNMENUOPEN,
COLUMNLOCK,
COLUMNUNLOCK,
FILTER,
NAVIGATE,
SORT
],
getOptions: function() {
var options = this.options;
options.dataSource = null;
var result = extend(true, {}, this.options);
result.columns = kendo.deepExtend([], this.columns);
var dataSource = this.dataSource;
var initialData = dataSource.options.data && dataSource._data;
dataSource.options.data = null;
result.dataSource = $.extend(true, {}, dataSource.options);
dataSource.options.data = initialData;
result.dataSource.data = initialData;
result.dataSource.page = dataSource.page();
result.dataSource.filter = $.extend(true, {}, dataSource.filter());
result.dataSource.pageSize = dataSource.pageSize();
result.dataSource.sort = dataSource.sort();
result.dataSource.group = dataSource.group();
result.dataSource.aggregate = dataSource.aggregate();
if (result.dataSource.transport) {
result.dataSource.transport.dataSource = null;
}
if (result.pageable && result.pageable.pageSize) {
result.pageable.pageSize = dataSource.pageSize();
}
return result;
},
setOptions: function(options) {
var currentOptions = this.getOptions();
kendo.deepExtend(currentOptions, options);
if (!options.dataSource) {
currentOptions.dataSource = this.dataSource;
}
var wrapper = this.wrapper;
var events = this._events;
var element = this.element;
this.destroy();
this.options = null;
if (wrapper[0] !== element[0]) {
wrapper.before(element);
wrapper.remove();
}
element.empty();
this.init(element, currentOptions, events);
this._setEvents(currentOptions);
},
_destroyColumnAttachments: function() {
var that = this;
if (!that.thead) {
return;
}
that.thead.add(that.lockedHeader).find("th").each(function() {
var th = $(this), filterMenu = th.data("kendoFilterMenu"), sortable = th.data("kendoColumnSorter"), columnMenu = th.data("kendoColumnMenu");
if (filterMenu) {
filterMenu.destroy();
}
if (sortable) {
sortable.destroy();
}
if (columnMenu) {
columnMenu.destroy();
}
});
},
_toggle: function(model, expand) {
var that = this;
var defaultPromise = $.Deferred().resolve().promise();
var loaded = model.loaded();
if (that._isIncellEditable() && that.editor) {
$(activeElement()).change();
that.closeCell();
}
if (model._error) {
model.expanded = false;
model._error = undefined;
}
if (!loaded && model.expanded) {
return defaultPromise;
}
if (typeof expand == "undefined") {
expand = !model.expanded;
}
model.expanded = expand;
function afterModelLoaded() {
that._toggleData();
if (that._isPageable()) {
that.refresh();
} else {
that._render();
}
that._syncLockedContentHeight();
}
if (!loaded) {
defaultPromise = this.dataSource.load(model).always((function() {
afterModelLoaded();
}));
}
afterModelLoaded();
return defaultPromise;
},
_toggleData: function() {
var that = this;
if (that._isPageable()) {
that._togglePageableData();
}
},
_togglePageableData: function() {
var that = this;
var dataSource = that.dataSource;
var data = dataSource._getData();
var result;
var queryOptions = dataSource._defaultPageableQueryOptions();
that._renderProgress(true);
var childrenMap = dataSource._getChildrenMap() || dataSource.childrenMap(dataSource._getData());
dataSource._processDataItemsState(data, childrenMap);
result = dataSource._processPageableQuery(data, queryOptions);
queryOptions.childrenMap = result.childrenMap;
queryOptions.filteredChildrenMap = result.filteredChildrenMap;
dataSource._aggregateResult = dataSource._calculateAggregates(result.dataToAggregate, queryOptions);
dataSource.view(result.data);
if (!dataSource.filter()) {
dataSource._calculateCollapsedTotal();
}
that._refreshPager();
that._renderProgress(false);
},
_refreshPager: function() {
var pager = this.pager;
if (pager) {
pager.refresh();
}
},
expand: function(row) {
return this._toggle(this.dataItem(row), true);
},
collapse: function(row) {
return this._toggle(this.dataItem(row), false);
},
_toggleChildren: function(e) {
var icon = $(e.target);
var model = this.dataItem(icon);
if (!model) {
return;
}
var event = !model.expanded ? EXPAND : COLLAPSE;
if (!this.trigger(event, { model })) {
this._toggle(model);
}
e.preventDefault();
},
_navigatable: function() {
var that = this;
if (!that.options.navigatable) {
that.table.attr("tabindex", 0);
return;
}
var tables = that.table.add(that.lockedTable);
var headerTables = that.thead.parent().add($(">table", that.lockedHeader));
if (that.options.scrollable) {
tables = tables.add(headerTables);
}
headerTables.find("a.k-link").attr("tabIndex", -1);
this._navigatableTables = tables;
this._headertables = headerTables;
tables.on(kendo.support.touch ? "touchstart" + NS : "mousedown" + NS, NAVROW + ">:visible", that._tableClick.bind(that)).on("focus" + NS, that._tableFocus.bind(that)).on("focusout" + NS, that._tableBlur.bind(that)).on("keydown" + NS, that._tableKeyDown.bind(that));
},
cellIndex: function(td) {
var lockedColumnOffset = 0;
if (this.lockedTable && !$.contains(this.lockedTable[0], td[0])) {
lockedColumnOffset = leafColumns(lockedColumns(this.columns)).length;
}
return $(td).parent().children().index(td) + lockedColumnOffset;
},
_isActiveInTable: function() {
var active = kendo._activeElement();
if (!active) {
return false;
}
return this.table[0] === active || $.contains(this.table[0], active) || this.lockedTable && (this.lockedTable[0] === active || $.contains(this.lockedTable[0], active));
},
_restoreCurrent: function(currentIndex, isCurrentInHeader, currentRowIndex) {
var rowIndex;
var row;
var td;
if (currentIndex === undefined || currentIndex < 0) {
return;
}
if (this._current) {
this._current.removeClass("k-focus");
}
if (isCurrentInHeader) {
this._setCurrent(this.thead.find("th").eq(currentIndex));
} else {
rowIndex = currentRowIndex || 0;
currentIndex = currentIndex || 0;
row = $();
if (this.lockedTable) {
row = this.lockedTable.find(">tbody>tr:visible").eq(rowIndex);
}
row = row.add(this.tbody.children().eq(rowIndex));
td = row.find(">td:visible").eq(currentIndex);
this._setCurrent(td);
}
if (this._current) {
focusTable(this.table, true);
this._current.addClass("k-focus");
}
},
current: function(newCurrent) {
return this._setCurrent(newCurrent, true);
},
_setCurrent: function(newCurrent, preventTrigger, isIncellEditable) {
var that = this;
var current = that._current;
newCurrent = $(newCurrent);
if (isIncellEditable) {
if (newCurrent[0]) {
that._current = newCurrent;
that._updateCurrentAttr(that._current, newCurrent);
that._scrollCurrent();
if (!preventTrigger) {
this.trigger(NAVIGATE, { element: newCurrent });
}
}
} else {
if (newCurrent.length && (!current || current[0] !== newCurrent[0])) {
this._updateCurrentAttr(current, newCurrent);
this._scrollCurrent();
if (!preventTrigger) {
this.trigger(NAVIGATE, { element: newCurrent });
}
}
if (newCurrent && newCurrent.length) {
this._lastCellIndex = newCurrent.parent().children(DATA_CELL).index(newCurrent);
}
}
return that._current;
},
_scrollCurrent: function() {
var current = this._current;
var scrollable = this.options.scrollable;
if (!current || !scrollable) {
return;
}
var row = current.parent();
var tableContainer = row.closest("table").parent();
var isInLockedContainer = tableContainer.is(".k-grid-content-locked,.k-grid-header-locked");
var isInContent = tableContainer.is(".k-grid-content-locked,.k-grid-content");
var scrollableContainer = $(this.content)[0];
if (isInContent) {
this._scrollTo(this._relatedRow(row)[0], scrollableContainer);
}
if (this.lockedContent) {
this.lockedContent[0].scrollTop = scrollableContainer.scrollTop;
}
if (!isInLockedContainer) {
this._scrollTo(current[0], scrollableContainer);
}
},
_findCurrentCell: function() {
var that = this;
var current = that.current();
var elements = $(that.table).add(that.header).add(that.lockedTable).add(that.lockedHeader);
if (current && elements.find(current).length > 0) {
return current;
} else {
return elements.find(DOT + classNames.focused);
}
},
_scrollTo: function(element, container) {
var elementToLowercase = element.tagName.toLowerCase();
var isHorizontal = elementToLowercase === "td" || elementToLowercase === "th";
var table = $(element).closest("table")[0];
var elementOffsetDir = element[isHorizontal ? "offsetWidth" : "offsetHeight"];
var containerScroll = container[isHorizontal ? "scrollLeft" : "scrollTop"];
var containerOffsetDir = container[isHorizontal ? "clientWidth" : "clientHeight"];
var elementOffset = $(element).css("position") === "relative" && isRtl && isHorizontal ? Math.abs(table.offsetLeft - element.offsetLeft) : element[isHorizontal ? "offsetLeft" : "offsetTop"];
var bottomDistance = elementOffset + elementOffsetDir;
var result = 0;
var ieCorrection = 0;
var firefoxCorrection = 0;
if (isRtl && isHorizontal) {
if (browser.msie || browser.edge) {
ieCorrection = table.offsetLeft;
} else if (browser.mozilla || browser.webkit && browser.version > 85) {
firefoxCorrection = table.offsetLeft - kendo.support.scrollbar();
}
}
containerScroll = Math.abs(containerScroll + ieCorrection - firefoxCorrection);
if (containerScroll > elementOffset) {
result = elementOffset;
} else if (bottomDistance > containerScroll + containerOffsetDir) {
if (elementOffsetDir <= containerOffsetDir) {
result = bottomDistance - containerOffsetDir;
} else {
result = elementOffset;
}
} else {
result = containerScroll;
}
result = Math.abs(result + ieCorrection) + firefoxCorrection;
container[isHorizontal ? "scrollLeft" : "scrollTop"] = result;
},
_aria: function() {
var wrapper = this.wrapper, gridRole = "treegrid", table = this.table, toolbar = wrapper.find(".k-grid-toolbar"), groupingHeader = wrapper.find(".k-grouping-header"), gridId = table.attr("id"), tableTabindex = table.attr("tabindex"), tbodyId, headerGroupId, footerGroupId, tableOwned, numberOfFixedRows = this.thead.find("tr").length + this.wrapper.find(".k-grid-footer-wrap table tr").length, trailingColumns = this._trailingColumns(), virtual = this.virtualScroll, pageable = this.options.pageable, rowsCount;
table.attr({
role: gridRole,
tabindex: tableTabindex >= 0 ? tableTabindex : 0
});
table.find("tbody, thead, tfoot").attr("role", "rowgroup");
table.find("tr").attr("role", "row");
table.find("th").attr("role", "columnheader");
table.find("td").attr("role", "gridcell");
if (pageable && this.dataSource.totalPages() > 1 || virtual && virtual.rows) {
if (this._groups() > 0) {
rowsCount = -1;
} else {
rowsCount = numberOfFixedRows + this.dataSource.total();
}
table.attr("aria-rowcount", rowsCount);
}
if (rowsCount && rowsCount > 0) {
this._ariaRowIndex();
}
if (virtual && virtual.columns || !table.attr("aria-colcount") && (table.find("td:hidden").length > 0 || wrapper.find(".k-grid-content-locked td:hidden").length > 0)) {
table.attr("aria-colcount", trailingColumns + leafColumns(this.columns).length);
this._ariaColumnIndex();
}
if (!gridId) {
gridId = kendo.guid();
table.attr("id", gridId);
}
if (this.pager) {
this.pager.element.attr("aria-controls", gridId);
}
toolbar.attr({
role: "toolbar",
"aria-label": this.options.messages.toolbarLabel,
"aria-controls": gridId
});
groupingHeader.attr({
role: "toolbar",
"aria-label": this.options.messages.groupingHeaderLabel,
"aria-controls": gridId
});
headerGroupId = this._ariaHeaderFooter("header", "thead", "th, td", "columnheader");
footerGroupId = this._ariaHeaderFooter("footer", "tfoot", "td", "gridcell");
if (wrapper.find(".k-grid-content-locked").length > 0) {
this._ariaLockedContent();
}
if (!!headerGroupId || !!footerGroupId) {
tbodyId = this.tbody.attr("id") || kendo.guid();
tableOwned = [
headerGroupId,
tbodyId,
footerGroupId
].join(" ");
this.tbody.attr("id", tbodyId);
table.attr("aria-owns", tableOwned);
}
},
_ariaColumnIndex: function() {
var trailingColumns = this._trailingColumns(), dataVirtual = this.tbody.find(">tr").last().find("> td[data-virtual]"), headerRows = this.thead.find(">tr").not(".k-filter-row"), lockedHeaderRows = this.wrapper.find(".k-grid-header-locked thead > tr").not(".k-filter-row"), firstIndex = Number.MAX_VALUE, lastIndex = 0, lockedLastIndex = 0, previousVirtual = 0, nextVirtual = 0, previousIndex, i, cells, dataIndex, cellsIndex, eachHeaderCell = function(j, cell) {
var current = cell.getAttribute("data-index"), currentIndex = Number(current), lockedParent = $(cell).closest(".k-grid-header-locked");
if (lockedParent.length === 0 && currentIndex < firstIndex) {
firstIndex = currentIndex;
}
if (lockedParent.length > 0 && lockedLastIndex < currentIndex) {
lockedLastIndex = currentIndex;
}
if (lockedParent.length === 0 && lastIndex < currentIndex) {
lastIndex = currentIndex;
}
if (current !== null) {
cell.setAttribute("aria-colindex", Number(currentIndex) + 1);
previousIndex = Number(currentIndex) + 1 + cell.getAttribute("colspan");
} else {
cell.setAttribute("aria-colindex", previousIndex + 1);
previousIndex = previousIndex + cell.getAttribute("colspan");
}
};
if (dataVirtual.length === 2) {
previousVirtual = Number(dataVirtual[0].getAttribute("colspan"));
nextVirtual = Number(dataVirtual[1].getAttribute("colspan"));
} else if (dataVirtual.length === 1 && dataVirtual.prev().length === 0) {
previousVirtual = Number(dataVirtual[0].getAttribute("colspan"));
} else if (dataVirtual.length === 1 && dataVirtual.prev().length === 1) {
nextVirtual = Number(dataVirtual[0].getAttribute("colspan"));
}
for (i = 0; i < lockedHeaderRows.length; i++) {
previousIndex = 0;
lockedHeaderRows.eq(i).find("th").each(eachHeaderCell);
}
for (i = 0; i < headerRows.length; i++) {
previousIndex = 0;
headerRows.eq(i).find("th").each(eachHeaderCell);
}
for (i = 0; i <= lockedLastIndex; i++) {
dataIndex = i + trailingColumns;
cells = this.wrapper.find(".k-grid-content-locked tbody > tr > td:nth-child(" + (i + 1) + ")");
cells.attr("aria-colindex", dataIndex + 1);
}
for (i = previousVirtual; i <= lastIndex - firstIndex - nextVirtual; i++) {
if (previousVirtual === 0) {
cellsIndex = i + 1;
} else {
cellsIndex = i - previousVirtual + 2;
}
dataIndex = firstIndex + i + trailingColumns;
cells = this.tbody.find("> tr > td:nth-child(" + cellsIndex + ")");
cells.attr("aria-colindex", dataIndex + 1);
}
},
_ariaHeaderFooter: function(type, group, el, role) {
var that = this, wrapper = that.wrapper, table = wrapper.find(".k-grid-" + type + " .k-grid-" + type + "-wrap table"), lockedTable = wrapper.find(".k-grid-" + type + " .k-grid-" + type + "-locked table"), groupId = "", rowGroup;
if (table.length > 0) {
rowGroup = table.find(group + ", tbody");
groupId = rowGroup.attr("id") || kendo.guid();
table.attr("role", "none");
table.find("tr").attr("role", "row");
table.find(el).attr("role", role);
rowGroup.attr({
role: "rowgroup",
id: groupId
});
}
if (lockedTable.length > 0) {
that._ariaLocked(type, group, el, role);
}
lockedTable.find("td").attr("role", "gridcell");
table.find("td").attr("role", "gridcell");
return groupId;
},
_ariaId: function() {
var id = this.element.attr("id") || "aria";
if (id) {
this._cellId = id + "_active_cell";
}
},
_ariaLocked: function(type, group, el, role) {
var that = this, wrapper = that.wrapper, table = wrapper.find(".k-grid-" + type + " .k-grid-" + type + "-wrap table"), lockedTable = wrapper.find(".k-grid-" + type + " .k-grid-" + type + "-locked table"), rows = table.find("tr"), lockedRows = lockedTable.find("tr");
lockedTable.attr("role", "none");
lockedTable.find(group + ", tbody").attr("role", "none");
lockedRows.attr("role", "none");
lockedTable.find(el).attr("role", role);
rows.each(function(i, row) {
var ownedCells = [];
ownedCells = that._cellsIds(lockedRows.eq(i).find(el), "locked_" + type, i);
ownedCells = ownedCells.concat(that._cellsIds($(row).find(el), type, i));
row.setAttribute("aria-owns", ownedCells.join(" "));
});
},
_ariaLockedContent: function() {
var that = this, table = that.table, tableRows = table.find("tr"), lockedTable = that.wrapper.find(".k-grid-content-locked table"), lockedRows = lockedTable.find("tr");
lockedTable.attr("role", "none");
lockedTable.find("tbody").attr("role", "none");
lockedRows.attr("role", "none");
lockedTable.find("td").attr("role", "gridcell");
tableRows.each(function(i, row) {
var ownedCells = [];
ownedCells = that._cellsIds(lockedRows.eq(i).find("td"), "locked_datacell", i);
ownedCells = ownedCells.concat(that._cellsIds($(row).find("td"), "datacell", i));
row.setAttribute("aria-owns", ownedCells.join(" "));
});
},
_ariaAddHiddenColIndex: function() {
var virtualScroll = this.virtualScroll || {}, columns = this.columns, table = this.table, leafColsCount = leafColumns(columns).length;
if (!virtualScroll.columns && !table.attr("aria-colcount")) {
this._ariaColumnIndex();
table.attr("aria-colcount", leafColsCount);
}
},
_ariaRemoveHiddenColIndex: function() {
var virtualScroll = this.virtualScroll || {}, columns = this.columns, leafColsCount = leafColumns(columns).length;
if (!virtualScroll.columns) {
this.wrapper.find("td, th").removeAttr("aria-colindex");
this.table.removeAttr("aria-colcount");
}
},
_ariaRowIndex: function() {
var headerRows = this.thead.find(">tr"), numberOfHeaderRows = headerRows.length, bodyRows = this.tbody.find(">tr"), footerRows = this.wrapper.find(".k-grid-footer-wrap tfoot > tr"), totalNumberOfItems = this.dataSource.total(), previousItems = this.dataSource.skip() || 0, currentIndex = 1, previousMaster = false, i, currentRow;
for (i = 0; i < numberOfHeaderRows; i++) {
headerRows.eq(i).attr("aria-rowindex", currentIndex + i);
}
currentIndex = numberOfHeaderRows + previousItems;
for (i = 0; i < bodyRows.length; i++) {
currentRow = bodyRows.eq(i);
currentIndex = currentIndex + 1;
currentRow.attr("aria-rowindex", currentIndex);
}
currentIndex = numberOfHeaderRows + totalNumberOfItems + 1;
for (i = 0; i < footerRows.length; i++) {
footerRows.eq(i).attr("aria-rowindex", currentIndex + i);
}
},
_cellsIds: function(elements, prefix, i) {
var ownedCells = [];
elements.each(function(j, cell) {
var id = cell.getAttribute("id") || prefix + "_" + i + "_" + j;
cell.setAttribute("id", id);
ownedCells.push(id);
});
return ownedCells;
},
_trailingColumns: function() {
return this._groups();
},
_groups: function() {
var group = this.dataSource.group();
return group ? group.length : 0;
},
_currentDataIndex: function(table, current) {
var index = current.attr("data-index");
if (!index) {
return undefined;
}
var lockedColumnsCount = lockedColumns(this.columns).length;
if (lockedColumnsCount && !table.closest("div").hasClass("k-grid-content-locked")[0]) {
return index - lockedColumnsCount;
}
return index;
},
_prevVerticalCell: function(container, current) {
var cells;
var row = current.parent();
var rows = container.children(NAVROW);
var rowIndex = rows.index(row);
var index = this._currentDataIndex(container, current);
var cellSelector = DATA_CELL + "," + FILTER_CELL;
if ((index || current.hasClass("k-header")) && !row.hasClass("k-filter-row")) {
cells = parentColumnsCells(current);
return cells.eq(cells.length - 2);
}
index = Math.max(row.children(cellSelector).index(current), this._lastCellIndex || 0);
if (row.hasClass("k-filter-row")) {
return leafDataCells(container).filter(isCellVisible).eq(index);
}
if (rowIndex == -1) {
row = container.find("tr.k-filter-row:visible");
if (!row[0]) {
return leafDataCells(container).filter(isCellVisible).eq(index);
}
} else {
row = rowIndex === 0 ? $() : rows.eq(rowIndex - 1);
}
cells = row.children(cellSelector);
if (cells.length > index) {
return cells.eq(index);
}
return cells.eq(0);
},
_nextVerticalCell: function(container, current) {
var cells;
var row = current.parent();
var rows = container.children(NAVROW);
var rowIndex = rows.index(row);
var index = this._currentDataIndex(container, current);
var cellSelector = DATA_CELL + "," + FILTER_CELL;
if (rowIndex != -1 && index === undefined && current.hasClass("k-header")) {
return childColumnsCells(current).eq(1);
}
index = index ? parseInt(index, 10) : row.children(cellSelector).index(current);
index = Math.max(index, this._lastCellIndex || 0);
if (rowIndex == -1) {
row = rows.eq(0);
} else {
row = rows.eq(rowIndex + current[0].rowSpan);
}
var tmpIndex = index;
if (this._currentDataIndex(container, current) !== undefined) {
var currentRowCells = row.children(":not(.k-group-cell):not(.k-hierarchy-cell)");
var hiddenColumns = currentRowCells.filter(":hidden");
for (var idx = 0, length = hiddenColumns.length; idx < length; idx++) {
if (currentRowCells.index(hiddenColumns[idx]) < index) {
tmpIndex--;
}
}
}
index = tmpIndex;
cells = row.children(cellSelector);
if (cells.length > index) {
return cells.eq(index);
}
return cells.eq(0);
},
_verticalContainer: function(container, up) {
var table = container.parent();
var length = this._navigatableTables.length;
var step = Math.floor(length / 2);
var index = inArray(table[0], this._navigatableTables);
if (up) {
step *= -1;
}
index += step;
if (index >= 0 || index < length) {
table = this._navigatableTables.eq(index);
}
return table.find(up ? "thead" : "tbody");
},
_filterFocusable: function() {
return this.wrapper.find(".k-filter-row").find(".k-dropdownlist, .k-input .k-input-inner:visible, input[type='radio']:visible, input[type='checkbox']:visible");
},
_updateCurrentAttr: function(current, next) {
var headerId = $(current).data("headerId");
$(current).removeClass(classNames.focused);
this.table.removeAttr(ARIA_ACTIVEDESCENDANT);
if (headerId) {
headerId = headerId.replace(this._cellId, "");
$(current).attr("id", headerId);
} else {
$(current).removeAttr("id");
}
next.data("headerId", next.attr("id")).attr("id", this._cellId).addClass(classNames.focused);
this.table.attr(ARIA_ACTIVEDESCENDANT, this._cellId);
this._current = next;
},
_tableKeyDown: function(e) {
var handled = false;
var current = this.current();
var target = $(e.target);
var canHandle = !e.isDefaultPrevented() && !target.is(":button,a,:input,a>.k-icon,a>.k-svg-icon");
current = current ? current : $(this.lockedTable).add(this.table).find(NAVROW + " > td:visible").first();
if (e.altKey && e.keyCode == keys.DOWN) {
current.find(".k-grid-filter-menu, .k-grid-column-menu").click();
e.stopImmediatePropagation();
return;
}
if (e.keyCode === keys.F10 && this.toolbar && this.toolbar.length) {
this.toolbar.find("[tabindex=0]:visible").first().trigger("focus");
handled = true;
}
if (canHandle && e.keyCode == keys.UP) {
handled = this._moveUp(current, e.shiftKey);
}
if (canHandle && e.keyCode == keys.DOWN) {
handled = this._moveDown(current, e.shiftKey);
}
if (canHandle && e.ctrlKey && current.is(".k-header") && this.options.reorderable && e.keyCode == (isRtl ? keys.RIGHT : keys.LEFT)) {
this._moveColumn(current, true);
} else if (canHandle && e.ctrlKey && current.is(".k-header") && this.options.reorderable && e.keyCode == (isRtl ? keys.LEFT : keys.RIGHT)) {
this._moveColumn(current, false);
} else if (canHandle && e.keyCode == (isRtl ? keys.LEFT : keys.RIGHT)) {
if (e.altKey) {
this._handleExpand(current);
handled = true;
} else {
handled = this._moveRight(current);
}
} else if (canHandle && e.keyCode == (isRtl ? keys.RIGHT : keys.LEFT)) {
if (e.altKey) {
this._handleCollapse(current);
handled = true;
} else {
handled = this._moveLeft(current);
}
}
if (canHandle && e.keyCode == keys.PAGEDOWN) {
handled = this._handlePageDown();
}
if (canHandle && e.keyCode == keys.PAGEUP) {
handled = this._handlePageUp();
}
if (e.keyCode == keys.ENTER || e.keyCode == keys.F2) {
handled = this._handleEnterKey(current, e.currentTarget, target);
}
if (e.keyCode == keys.ESC) {
handled = this._handleEscKey(current, e.currentTarget);
}
if (canHandle && e.keyCode == keys.HOME) {
handled = this._handleHome(current, e.ctrlKey);
}
if (canHandle && e.keyCode == keys.END) {
handled = this._handleEnd(current, e.ctrlKey);
}
if (e.keyCode == keys.TAB) {
handled = this._handleTabKey(current, e.currentTarget, e.shiftKey, target);
}
if (handled) {
e.preventDefault();
e.stopPropagation();
}
},
_moveColumn: function(current, isLeft) {
var elements = this.wrapper.data().kendoReorderable.element.find(this._draggableInstance.options.filter + ":visible");
var columns = visibleColumns(flatColumnsInDomOrder(this.columns));
var oldIndex = elements.index($(current));
var offset = isLeft ? -1 : 1;
var column = columns[oldIndex];
var newIndex = targetParentContainerIndex(columns, this.columns, oldIndex, oldIndex + offset);
if (newIndex >= 0) {
this.reorderColumn(newIndex, column, isLeft);
this.trigger(COLUMNREORDER, {
newIndex,
oldIndex,
column
});
}
},
_handleExpand: function(current) {
var that = this;
var row = current.parent();
var model = that.dataItem(row);
if (current.hasClass("k-header")) {
return false;
}
if (model && model.hasChildren && !model.expanded && !that.trigger(EXPAND, { model })) {
this.expand(row);
return true;
}
return false;
},
_handleCollapse: function(current) {
var that = this;
var row = current.parent();
var model = that.dataItem(row);
if (current.hasClass("k-header")) {
return false;
}
if (model && model.hasChildren && model.expanded && !that.trigger(COLLAPSE, { model })) {
that.collapse(row);
return true;
}
return false;
},
_handleHome: function(current, ctrl) {
var row = current.parent();
var rowContainer = row.parent();
var isInLockedTable = this.lockedTable && this.lockedTable.children("tbody")[0] === rowContainer[0];
var isInBody = rowContainer[0] === this.tbody[0];
var prev;
if (ctrl) {
if (this.lockedTable) {
prev = this.lockedTable.find(NAVROW + " > td:visible").first();
} else {
prev = this.table.find(NAVROW + " > td:visible").first();
}
} else if (isInBody || isInLockedTable) {
if (isInBody && this.lockedTable) {
row = this._relatedRow(row);
}
prev = row.children(NAVCELL).first();
}
if (prev && prev.length) {
this._setCurrent(prev);
return true;
}
},
_handleEnd: function(current, ctrl) {
var row = current.parent();
var rowContainer = row.parent();
var isInLockedTable = this.lockedTable && this.lockedTable.children("tbody")[0] === rowContainer[0];
var isInBody = rowContainer[0] === this.tbody[0];
var next;
if (ctrl) {
next = this.table.find(ITEMROW).last().children(NAVCELL).last();
} else if (isInBody || isInLockedTable) {
if (!isInBody && this.lockedTable) {
row = this._relatedRow(row);
}
next = row.children(NAVCELL).last();
}
if (next && next.length) {
this._setCurrent(next);
return true;
}
},
_handlePageDown: function() {
var that = this;
if (!that._isPageable()) {
return false;
}
that.dataSource._restorePageSizeAfterAddChild();
that.dataSource.page(that.dataSource.page() + 1);
return true;
},
_handlePageUp: function() {
var that = this;
if (!that._isPageable()) {
return false;
}
that.dataSource._restorePageSizeAfterAddChild();
that.dataSource.page(that.dataSource.page() - 1);
return true;
},
_handleEscKey: function(current, currentTable) {
var active = kendo._activeElement();
var currentIndex;
var that = this;
var row;
var rowIndex;
var cellIndex;
var tbody;
if (!current || !current.parent().hasClass("k-grid-edit-row")) {
if (current.has(active).length) {
focusTable(that.table, true);
return true;
}
if (current.parent().hasClass("k-filter-row")) {
this._filterFocusable().attr(TABINDEX, -1);
focusTable(this.table, true);
return true;
}
return false;
}
if (that._isIncellEditable()) {
row = current.parent();
cellIndex = current.index();
rowIndex = row.index();
tbody = row.closest("tbody");
that.closeCell(true);
that._setCurrent(tbody.children().eq(rowIndex).children().eq(cellIndex), false, true);
} else {
currentIndex = $(current).parent().index();
if (active) {
active.blur();
}
this.cancelRow();
if (currentIndex >= 0) {
this._setCurrent(this.items().eq(currentIndex).children(NAVCELL).first());
}
}
focusTable(that.table, true);
return true;
},
_handleEnterKey: function(current, currentTable, target) {
var editable = this.options.editable;
var container = target.closest("[role=gridcell]");
var focusable, link, filterFocusable;
if (!target.is("table") && !$.contains(current[0], target[0])) {
current = container;
}
if (current.is("th")) {
link = current.find(".k-link");
if (current.has($(activeElement())).length > 0) {
return false;
} else if (link.length) {
link.click();
} else if (current.parent().hasClass("k-filter-row")) {
filterFocusable = this._filterFocusable();
filterFocusable.attr(TABINDEX, 0);
current.find(":kendoFocusable").first().trigger("focus");
} else {
current.find(CHECKBOXINPUT).trigger("focus");
}
return true;
}
focusable = current.find(":kendoFocusable").first();
if (focusable[0] && current.hasClass("k-focus")) {
focusable.trigger("focus");
return true;
}
if (editable && !target.is(":button,.k-button,textarea")) {
if (!container[0]) {
container = current;
}
this._handleEditing(container, false, currentTable);
return true;
}
if (!editable && current.is("td[aria-expanded]")) {
if (current.is("[aria-expanded=false]")) {
this._handleExpand(current);
} else {
this._handleCollapse(current);
}
}
return false;
},
_handleTabKey: function(current, currentTable, shiftKey, target) {
var that = this;
var incellEditing = that.options.editable && that._isIncellEditable();
var cell, filterFocusable;
if (!incellEditing || current.is("th") || (this.options.scrollable ? this._headertables.filter(currentTable).length : this.thead.filter(target).length)) {
if (current.parent().hasClass("k-filter-row")) {
filterFocusable = this._filterFocusable();
if (!shiftKey && filterFocusable[filterFocusable.length - 1] === document.activeElement) {
filterFocusable.first().trigger("focus");
return true;
} else if (shiftKey && filterFocusable[0] === document.activeElement) {
filterFocusable.last().trigger("focus");
return true;
}
}
return false;
}
cell = $(activeElement()).closest(DOT + classNames.editCell);
if (that.options._tabCycleStop) {
return false;
}
if (cell[0] && cell[0] !== current[0]) {
current = cell;
}
cell = that._tabNext(current, currentTable, shiftKey);
if (cell.length) {
that._handleEditing(current, cell, cell.closest(TABLE));
return true;
} else {
that._preventPageSizeRestore = false;
}
return false;
},
_tabNext: function(current, currentTable, back) {
var that = this;
var switchRow = true;
var next = back ? current.prevAll(DATA_CELL).first() : current.nextAll(":visible").first();
if (!next.length) {
next = current.parent();
if (that.lockedTable) {
switchRow = back && currentTable == that.lockedTable[0] || !back && currentTable == that.table[0];
next = that._relatedRow(next);
}
if (switchRow) {
next = next[back ? "prevAll" : "nextAll"]("tr:not(.k-grouping-row):not(.k-detail-row):visible").first();
}
if (back) {
next = next.children(DATA_CELL).last();
} else {
next = next.children(DATA_CELL).first();
}
that.dataSource._restorePageSizeAfterAddChild();
}
return next;
},
_handleEditing: function(current, next, table) {
var that = this, active = $(kendo._activeElement()), isIE = browser.msie, editContainer, focusable, isEdited;
var editable = that.options.editable && that.options.editable.update !== false;
var incellEditing = that._isIncellEditable();
var nextFocusableCellRowIndex = $(next).parents("tr").index();
var nextFocusableCellIndex = $(next).index();
var currentFocusedCellRowIndex = $(current).parents("tr").index();
var currentFocusedCellIndex = current.index();
var editedCell;
table = $(table);
if (incellEditing) {
isEdited = current.hasClass(classNames.editCell);
} else {
isEdited = current.parent().hasClass("k-grid-edit-row");
}
if (that.editor) {
editContainer = that.editor.wrapper;
if (editContainer && $.contains(editContainer[0], active[0])) {
if (browser.opera) {
active.trigger("blur").change().triggerHandler("blur");
} else {
active.trigger("blur");
if (isIE) {
active.trigger("blur");
}
}
}
if (!that.editor) {
focusTable(that.table);
return;
}
if (that.editor.end()) {
if (incellEditing) {
that._preventPageSizeRestore = true;
that.closeCell();
that._preventPageSizeRestore = false;
if ($(that.table).add(that.lockedTable).find(DOT + classNames.editCell).length === 0) {
that._setCurrent(table.find("tbody").children().eq(currentFocusedCellRowIndex).children().eq(currentFocusedCellIndex));
}
} else {
that.saveRow();
isEdited = true;
}
} else {
if (incellEditing) {
that._setCurrent(editContainer);
} else {
that._setCurrent(editContainer.children().filter(NAVCELL).first());
}
focusable = editContainer.find(":kendoFocusable").first()[0];
if (focusable) {
focusable.focus();
}
return;
}
}
next = $(next).length && table.find(next).length === 0 ? table.find("tbody").children().eq(nextFocusableCellRowIndex).children().eq(nextFocusableCellIndex) : next;
if (next) {
that._setCurrent(next);
}
focusTable(that.table, true);
if (!editable) {
return;
}
if (!isEdited && !next || next) {
if (!that.current()) {
return;
}
var currentIndex = that.current().index();
if (incellEditing) {
that.editCell(that.current());
editedCell = $(that.table).add(that.lockedTable).find(DOT + classNames.editCell)[0];
if (editedCell) {
that._current = $(editedCell);
} else {
that._setCurrent(that._findCurrentCell());
}
} else {
that.editRow(that.current().parent());
that._setCurrent(that.editor.wrapper.children().eq(currentIndex));
that.current().removeClass("k-focus");
}
} else {
that.dataSource._restorePageSizeAfterAddChild();
}
},
_moveRight: function(current) {
var next = current.nextAll(NAVCELL).first();
var row = current.parent();
var rowIndex = row.index();
if (current.hasClass("k-header") || row.is(".k-filter-row")) {
next = current.nextAll(NAVHEADER).first();
if (!next[0] && this.lockedTable && current.closest("table")[0] === this.lockedHeader.find("table")[0]) {
next = this.thead.find("tr").eq(rowIndex).find(NAVHEADER).first();
}
}
if (!next[0] && this.lockedTable && current.closest("table")[0] === this.lockedTable[0]) {
next = this._relatedRow(row).children(NAVCELL).first();
}
if (next[0] && next[0] !== current[0]) {
focusTable(this.table, true);
}
this._setCurrent(next);
return true;
},
_moveLeft: function(current) {
var prev = current.prevAll(NAVCELL).first();
var row = current.parent();
var rowIndex = row.index();
if (current.hasClass("k-header") || row.is(".k-filter-row")) {
prev = current.prevAll(NAVHEADER).first();
if (!prev[0] && this.lockedTable && current.closest("table")[0] === this.thead.parent()[0]) {
prev = this.lockedHeader.find(">table>thead>tr").eq(rowIndex).children(NAVHEADER).last();
}
}
if (!prev[0] && this.lockedTable && current.closest("table")[0] === this.table[0]) {
prev = this._relatedRow(row).children(NAVCELL).last();
}
if (prev[0] && prev[0] !== current[0]) {
focusTable(this.table, true);
}
this._setCurrent(prev);
return true;
},
_moveUp: function(current, shiftKey) {
var container = current.parent().parent();
var prev;
if (shiftKey) {
prev = current.parent();
prev = prev.prevAll(ITEMROW).first();
prev = current.parent().is(ITEMROW) ? prev.children().eq(current.index()) : prev.children(DATA_CELL).last();
} else {
prev = this._prevVerticalCell(container, current);
if (!prev[0]) {
this._lastCellIndex = 0;
container = this._verticalContainer(container, true);
prev = this._prevVerticalCell(container, current);
if (prev[0]) {
focusTable(this.table, true);
}
}
}
var tmp = this._lastCellIndex || 0;
this._setCurrent(prev);
this._lastCellIndex = tmp;
return true;
},
_moveDown: function(current, shiftKey) {
var container = current.parent().parent();
var next;
if (shiftKey) {
next = current.parent();
next = next.nextAll(ITEMROW).first();
next = current.parent().is(ITEMROW) ? next.children().eq(current.index()) : next.children(DATA_CELL).first();
} else {
next = this._nextVerticalCell(container, current);
if (!next[0]) {
this._lastCellIndex = 0;
container = this._verticalContainer(container);
next = this._nextVerticalCell(container, current);
if (next[0]) {
focusTable(this.table, true);
}
}
}
var tmp = this._lastCellIndex || 0;
this._setCurrent(next);
this._lastCellIndex = tmp;
return true;
},
_tableClick: function(e) {
var that = this, currentTarget = $(e.currentTarget), isHeader = currentTarget.is("tr:not('.k-filter-row')>th"), target = $(e.target), table = this.table.add(this.lockedTable), headerTable = this.thead.parent().add($(">table", this.lockedHeader)), isInput = isInputElement(target.add(target.closest(".k-button-icon"))), currentTable = currentTarget.closest("table")[0];
if (kendo.support.touch) {
return;
}
if (currentTable !== table[0] && currentTable !== table[1] && currentTable !== headerTable[0] && currentTable !== headerTable[1]) {
return;
}
if (this.options.navigatable && !isInput) {
this._setCurrent(currentTarget);
}
if (isHeader || !isInput) {
setTimeout(function() {
if (!isInputElement(kendo._activeElement()) || !$.contains(currentTable, kendo._activeElement())) {
focusTable(that.table, true);
}
});
}
if (isHeader) {
e.preventDefault();
}
},
_tableFocus: function(e) {
var current = this.current();
var table = this.lockedTable ? this.lockedTable : this.table;
if (current && current.is(":visible")) {
current.addClass(classNames.focused);
} else {
this._setCurrent(table.find(NAVROW + " > td:visible").first());
}
this.table.attr(TABINDEX, 0);
},
_tableBlur: function() {
var current = this.current();
if (current) {
current.removeClass(classNames.focused);
}
},
_attachEvents: function() {
var that = this;
var retryButton = DOT + classNames.retry;
that._userEvents = new kendo.UserEvents(that.element, {
tap: that._onPress.bind(that),
allowSelection: true
});
this.element.on(CLICK + NS, retryButton, this._dataSourceFetchProxy).on(CLICK + NS, ".k-button[data-command]", this._commandClick.bind(this)).on(INPUT + NS, ".k-grid-search input", this._search.bind(this));
this._attachCellEditingEventHandlers();
},
_onPress: function(e) {
var that = this;
if (that._isToggleIcon(e.event.target)) {
that._toggleChildren.call(that, e.event);
}
},
_isToggleIcon: function(target) {
const icons = ICON_EXPAND_COLLAPSE_SELECTOR + "," + ICON_REFRESH_SELECTOR;
return $(target).closest(":not(path,svg)").is(icons);
},
_attachCellEditingEventHandlers: function() {
var that = this;
var editable = that.options.editable;
var selectable = that.selectable && that.selectable.options.multiple;
var closeCell = function(e) {
var target = activeElement();
var editor = that.editor || {};
var cell = editor.element;
if (cell && !$.contains(cell[0], target) && cell[0] !== target && !$(target).closest(".k-animation-container").length) {
if (editor.end()) {
if (!e.relatedTarget && that._isPageable() && !isUndefined(that.dataSource._addChildPageSize)) {
that._preventPageSizeRestore = false;
}
that.closeCell();
}
}
that._preventPageSizeRestore = false;
};
if (that._isIncellEditable() && editable.update !== false) {
that.wrapper.on(that.options._editCellEvent || CLICK + NS, "tr:not(.k-grouping-row) > td", function(e) {
var td = $(this), isLockedCell = that.lockedTable && td.closest("table")[0] === that.lockedTable[0];
if (that._isToggleIcon(e.target)) {
return;
}
if (td.hasClass(classNames.editCell) || td.has("a.k-grid-delete").length || td.has("button.k-grid-delete").length || td.closest("tbody")[0] !== that.tbody[0] && !isLockedCell || $(e.target).is(":input") || $(e.target).is(ICON_EXPAND_COLLAPSE_SELECTOR)) {
if (!that.editor) {
that.dataSource._restorePageSizeAfterAddChild();
}
that._preventPageSizeRestore = false;
return;
}
if (that.editor) {
if (td.is(":not(.k-command-cell)") && that.editor.end()) {
if (selectable) {
$(activeElement()).trigger("blur");
}
that.closeCell();
that.editCell(td);
}
} else {
that.editCell(td);
}
}).on("mousedown" + NS, "tr:not(.k-grouping-row) > td", function(e) {
if (that.editor && that._isPageable() && !isUndefined(that.dataSource._addChildPageSize)) {
that._preventPageSizeRestore = $(e.target).parents(DOT + classNames.editRow).length > 0;
} else {
that._preventPageSizeRestore = false;
}
}).on("focusin" + NS, function() {
if (!$.contains(this, activeElement())) {
clearTimeout(that._closeCellTimeout);
that._closeCellTimeout = null;
}
}).on("focusout" + NS, function(e) {
that._closeCellTimeout = setTimeout(function() {
closeCell(e);
}, 1);
});
}
},
_commandByName: function(name) {
var columns = this.columns;
var toolbar = Array.isArray(this.options.toolbar) ? this.options.toolbar : [];
var i, j, commands, currentName;
if (!name) {
return;
}
name = name.toLowerCase();
if (defaultCommands[name]) {
return defaultCommands[name];
}
for (i = 0; i < columns.length; i++) {
commands = columns[i].command;
if (commands) {
for (j = 0; j < commands.length; j++) {
currentName = commands[j].name;
if (!currentName) {
continue;
}
if (currentName.toLowerCase() == name) {
return commands[j];
}
}
}
}
for (i = 0; i < toolbar.length; i++) {
currentName = toolbar[i].name;
if (!currentName) {
continue;
}
if (currentName.toLowerCase() == name) {
return toolbar[i];
}
}
},
_commandClick: function(e) {
var button = $(e.currentTarget);
var commandName = button.attr("data-command") || button.parent().attr("data-command");
var command = this._commandByName(commandName);
var row = button.parentsUntil(this.wrapper, "tr");
row = row.length ? row : undefined;
if (command) {
if (command.methodName) {
this[command.methodName](row);
} else if (command.click) {
command.click.call(this, e);
}
if (e.preventDefault) {
e.preventDefault();
}
}
},
_search: function(e) {
var that = this;
var input = e.currentTarget;
clearTimeout(that._searchTimeOut);
that._searchTimeOut = setTimeout(function() {
that._searchTimeOut = null;
var options = that.options;
var searchFields = options.search ? options.search.fields : null;
var expression = {
filters: [],
logic: "or"
};
var value = input.value;
if (!searchFields) {
searchFields = getColumnsFields(options.columns);
}
if (value) {
for (var i = 0; i < searchFields.length; i++) {
expression.filters.push({
field: searchFields[i],
operator: "contains",
value
});
}
} else {
expression = {};
}
that.dataSource.filter(expression);
}, 300);
},
_ensureExpandableColumn: function() {
if (this._autoExpandable) {
delete this._autoExpandable.expandable;
}
var visibleColumns = grep(this.columns, not(is("hidden")));
visibleColumns = grep(visibleColumns, not(is("command")));
visibleColumns = grep(visibleColumns, not(is("selectable")));
visibleColumns = grep(visibleColumns, not(is("draggable")));
var expandableColumns = grep(visibleColumns, is("expandable"));
if (this.columns.length && !expandableColumns.length) {
this._autoExpandable = visibleColumns[0];
visibleColumns[0].expandable = true;
}
},
_columns: function() {
var that = this, columns = this.options.columns || [], draggableColumns;
this.columns = map(columns, function(column) {
column = typeof column === "string" ? { field: column } : column;
return extend({ encoded: true }, column);
});
var lockedCols = lockedColumns(columns);
if (lockedCols.length > 0) {
if (this.options.rowTemplate || this.options.altRowTemplate) {
throw new Error("Having both row template and locked columns is not supported");
}
this._hasLockedColumns = true;
this.columns = lockedCols.concat(nonLockedColumns(this.columns));
}
this.columns = normalizeColumns(this.columns);
this._ensureExpandableColumn();
this._columnTemplates();
this._columnAttributes();
if ($.grep(leafColumns(that.columns), function(col) {
if (col.selectable) {
that._includeChildren = col.includeChildren;
}
return col.selectable;
}).length) {
that._checkBoxSelection = true;
that.element.on(CLICK + NS, "tbody > tr " + CHECKBOXINPUT, that._checkboxClick.bind(that));
that.element.on(CLICK + NS, "thead > tr " + CHECKBOXINPUT, that._headerCheckboxClick.bind(that));
}
draggableColumns = $.grep(leafColumns(that.columns), function(col) {
return col.draggable;
});
if (draggableColumns.length) {
that._hasDragHandleColumn = true;
for (var i = 0; i < draggableColumns.length; i++) {
draggableColumns[i].headerAttributes = $.extend({ "aria-label": that.options.messages.dragHandleLabel }, draggableColumns[i].headerAttributes);
}
}
},
_columnTemplates: function() {
var idx, length, column;
var columns = leafColumns(this.columns);
for (idx = 0, length = columns.length; idx < length; idx++) {
column = columns[idx];
if (column.template) {
column.template = kendo.template(column.template);
}
if (this._isIncellEditable()) {
column.dirtyCellTemplate = this._createDirtyColumnTemplate(column);
column.dirtyIndicatorTemplate = this._createIndicatorTemplate(column);
}
if (column.headerTemplate) {
column.headerTemplate = kendo.template(column.headerTemplate);
}
if (column.footerTemplate) {
column.footerTemplate = kendo.template(column.footerTemplate);
}
}
},
_columnAttributes: function() {
var idx, length;
var columns = flatColumns(this.columns);
function convertStyle(attr) {
var properties, i, declaration;
if (attr && attr.style && attr.style.split) {
properties = attr.style.split(";");
attr.style = {};
for (i = 0; i < properties.length; i++) {
declaration = properties[i].split(":");
var name = kendo.trim(declaration[0]);
if (name) {
attr.style[toCamelCase(name)] = kendo.trim(declaration[1]);
}
}
}
}
for (idx = 0, length = columns.length; idx < length; idx++) {
convertStyle(columns[idx].attributes);
convertStyle(columns[idx].headerAttributes);
}
},
_clearSortClasses: function() {
var that = this;
if (that.content) {
that.content.find("col:not(.k-group-col):not(.k-hierarchy-col)").removeClass("k-sorted");
}
if (that.lockedContent) {
that.lockedContent.find("col:not(.k-group-col):not(.k-hierarchy-col)").removeClass("k-sorted");
}
},
_layout: function() {
var that = this;
var columns = this.columns;
var element = this.element;
this.wrapper = element.addClass(classNames.wrapper);
var layoutTemplateFunction = ({ gridHeader, gridHeaderWrap, gridContentWrap, toolbar, gridToolbar }) => {
var layout = this.options.hasHeader ? `<div class='${gridHeader}'>` : "";
if (this.options.hasHeader && this._hasLockedColumns) {
layout += "<div class='k-grid-header-locked'>" + "<table class='k-grid-header-table k-table'>" + "<colgroup></colgroup>" + "<thead class='k-table-thead' role='rowgroup'></thead>" + "</table>" + "</div>";
}
if (this.options.hasHeader) {
layout += `<div class='${gridHeaderWrap}'>` + "<table class='k-grid-header-table k-table'>" + "<colgroup></colgroup>" + "<thead class='k-table-thead' role='rowgroup'></thead>" + "</table>" + "</div>" + "</div>";
}
if (this._hasLockedColumns) {
layout += "<div class='k-grid-content-locked'>" + "<table class='k-grid-table k-table' role='treegrid'>" + "<colgroup></colgroup>" + "<tbody class='k-table-tbody' role='rowgroup'></tbody>" + "</table>" + "</div>";
}
layout += `<div class='${gridContentWrap} k-auto-scrollable'>` + "<table class='k-grid-table k-table' role='treegrid'>" + "<colgroup></colgroup>" + "<tbody class='k-table-tbody' role='rowgroup'></tbody>" + "</table>" + "</div>";
if (!this.options.scrollable) {
layout = `<table class='k-grid-table k-table' role='treegrid' >` + `<colgroup></colgroup>` + `${this.options.hasHeader ? `<thead class='k-table-thead ${gridHeader}' role='rowgroup'></thead>` : ""}` + `<tbody class='k-table-tbody' role='rowgroup'></tbody>` + `</table>`;
}
if (this.options.toolbar) {
layout = `<div class='${toolbar} ${gridToolbar}'></div>` + layout;
}
return layout;
};
layoutTemplateFunction = layoutTemplateFunction.bind(that);
element.append(kendo.template(layoutTemplateFunction)(classNames) + "<div class='k-status' role='alert' aria-live='polite'></div>");
this.toolbar = element.find(DOT + classNames.gridToolbar);
var header = element.find(DOT + classNames.gridHeader).find("thead").addBack().filter("thead");
this.thead = header.last();
if (this.options.scrollable) {
var rtl = kendo.support.isRtl(element);
element.find("div." + classNames.gridHeader).css(rtl ? "padding-left" : "padding-right", kendo.support.scrollbar());
}
var content = element.find(DOT + classNames.gridContentWrap);
if (!content.length) {
content = element;
} else {
this.content = content;
}
this.table = content.find(">table").addClass("k-grid-table");
this.tbody = this.table.find(">tbody");
if (this._hasLockedColumns) {
this.lockedHeader = header.first().closest(".k-grid-header-locked");
this.lockedContent = element.find(".k-grid-content-locked");
this.lockedTable = this.lockedContent.children().addClass("k-grid-table");
}
this._initVirtualTrees();
this._renderCols();
if (that.options.hasHeader) {
this._renderHeader();
}
},
_initVirtualTrees: function() {
this._headerColsTree = new kendoDom.Tree(this.thead.prev()[0]);
this._contentColsTree = new kendoDom.Tree(this.tbody.prev()[0]);
this._headerTree = new kendoDom.Tree(this.thead[0]);
this._contentTree = new kendoDom.Tree(this.tbody[0]);
this._statusTree = new kendoDom.Tree(this.element.children(".k-status")[0]);
if (this.lockedHeader) {
this._lockedHeaderColsTree = new kendoDom.Tree(this.lockedHeader.find("colgroup")[0]);
this._lockedContentColsTree = new kendoDom.Tree(this.lockedTable.find(">colgroup")[0]);
this._lockedHeaderTree = new kendoDom.Tree(this.lockedHeader.find("thead")[0]);
this._lockedContentTree = new kendoDom.Tree(this.lockedTable.find(">tbody")[0]);
}
},
_processToolbarItems: function(commands) {
var that = this, messages = that.options.messages.commands, items = [];
commands.map((command) => {
var name = (isPlainObject(command) ? command.name || "" : command).toLowerCase(), text = messages[name];
if (!name && !(isPlainObject(command) && command.template)) {
throw new Error("Commands should have name specified");
}
command = extend({}, defaultCommands[name], {
name,
text: (defaultCommands[name] || {}).text || text || capitalize(name),
type: command.template ? null : "button"
}, command);
if (name === "search") {
items.push({ type: "spacer" });
command.template = command.template({ message: command.text || messages.search });
}
if (command.imageClass) {
command.spriteCssClass = command.imageClass;
command.iconClass = command.imageClass;
}
if (that._commandByName(name)) {
if (!command.attributes) {
command.attributes = {};
}
command.attributes["data-command"] = name;
command.click = (e) => {
e.event.preventDefault();
e.event.stopPropagation();
that._commandClick({ currentTarget: e.target });
};
}
if (command.className) {
if (!command.attributes) {
command.attributes = {};
}
command.attributes["class"] = command.className;
}
items.push(command);
});
return items;
},
_toolbar: function() {
var options = this.options.toolbar;
var toolbar = this.toolbar;
if (!options) {
return;
}
if (Array.isArray(options)) {
toolbar.kendoToolBar({
navigateOnTab: !this.options.navigatable,
items: this._processToolbarItems(options)
});
} else if (isPlainObject(options)) {
toolbar.kendoToolBar({
navigateOnTab: !this.options.navigatable,
items: this._processToolbarItems(options.items || []),
overflow: options.overflow
});
} else {
toolbar.append(kendo.template(options)({}));
}
},
_initContextMenu: function() {
var that = this, options = that.options, tbodyContextMenu = isPlainObject(options.contextMenu) && isArray(options.contextMenu.body) ? { items: options.contextMenu.body } : { items: defaultBodyContextMenu }, theadContextMenu = isPlainObject(options.contextMenu) && isArray(options.contextMenu.head) ? { items: options.contextMenu.head } : { items: defaultHeadContextMenu };
var mainOptions = isPlainObject(options.contextMenu) ? options.contextMenu : {};
tbodyContextMenu = extend({}, {
messages: options.messages,
target: that.tbody,
filter: ".k-table-td",
action: that._action.bind(that),
states: that._buildStates()
}, mainOptions, tbodyContextMenu);
theadContextMenu = extend({}, {
messages: options.messages,
target: that.thead,
filter: ".k-table-th",
action: that._action.bind(that),
states: that._buildStates()
}, mainOptions, theadContextMenu);
that.tbodyContextMenu = new ui.treelist.ContextMenu("<ul></ul>", tbodyContextMenu);
that.theadContextMenu = new ui.treelist.ContextMenu("<ul></ul>", theadContextMenu);
},
_buildStates: function() {
var that = this;
return {
isEditable: that.options.editable,
isSelectable: that.options.selectable,
isMultiRowSelectionEnabled: that.options.selectable === "multiple, row",
isSortable: that.options.sortable && that.options.hasHeader,
alwaysDisabled: false,
hasSelection: () => this.select() ? this.select().length > 0 : false,
isSorted: () => !(this.dataSource.sort() ? this.dataSource.sort().length > 0 : false),
isExpandable: (target) => {
let dataItem = this.dataItem(target);
return dataItem && dataItem.hasChildren && !dataItem.expanded;
},
isCollapsible: (target) => {
let dataItem = this.dataItem(target);
return dataItem && dataItem.hasChildren && dataItem.expanded;
}
};
},
_action: function(args) {
var commandName = args.command, commandOptions = extend({ treelist: this }, args.options), command = new ui.treelist.commands[commandName](commandOptions);
return command.exec();
},
_lockedColumns: function() {
return grep(this.columns, is("locked"));
},
_nonLockedColumns: function() {
return grep(this.columns, not(is("locked")));
},
_templateColumns: function() {
return grep(this.columns, is("template"));
},
_render: function(options) {
var that = this;
options = options || {};
options = that._renderOptions(options);
var messages = this.options.messages;
var pageable = that._isPageable();
var dataSource = that.dataSource;
var maps = {
children: options.filteredChildrenMap || options.childrenMap,
ids: options.idsMap
};
var dataMaps = pageable ? maps && maps.children && maps.ids ? maps : dataSource._initDataMaps(dataSource._getData()) : {};
var childrenMap = dataMaps.children;
var idsMap = dataMaps.ids;
options.childrenMap = childrenMap;
options.idsMap = idsMap;
var data = that._dataToRender(options);
var level = that._renderedModelLevel(data[0], options);
var uidAttr = kendo.attr("uid");
var hasFooterTemplate;
var selected = this.select().removeClass("k-selected").map(function(_, row) {
return $(row).attr(uidAttr);
});
var viewChildrenMap;
this._absoluteIndex = 0;
that._clearRenderMap();
if (options.error) {
this._showStatus(kendo.template(({ messages, buttonClass }) => `${encode(messages.requestFailed)} ` + `<button class='${buttonClass}'><span class='k-button-text'>${encode(messages.retry)}</span></button>`)({
buttonClass: [classNames.button, classNames.retry].join(" "),
messages
}));
} else if (!data.length) {
this._hideStatus();
this._showNoRecordsTemplate();
} else {
if (pageable) {
viewChildrenMap = that._viewChildrenMap(options);
}
this._hideStatus();
hasFooterTemplate = this._hasFooterTemplate();
that._renderRows(options, data, leafColumns(nonLockedColumns(this.columns)), selected, childrenMap, viewChildrenMap, hasFooterTemplate);
if (this._hasLockedColumns) {
this._absoluteIndex = 0;
this._lockedContentTree.render(this._trs({
columns: leafColumns(lockedColumns(this.columns)),
editedColumn: options.editedColumn,
editedColumnIndex: options.editedColumnIndex,
aggregates: options.aggregates,
selected,
data,
childrenMap,
viewChildrenMap,
hasFooterTemplate,
visible: true,
level,
isLockedTable: true
}));
}
}
if (this._touchScroller) {
this._touchScroller.contentResized();
}
this.items().filter(function() {
return $.inArray($(this).attr(uidAttr), selected) >= 0;
}).addClass("k-selected");
this._syncLockedContentHeight();
that._togglePagerVisibility();
that._setExpanderElement();
},
_renderRows: function(options, data, columns, selected, childrenMap, viewChildrenMap, hasFooterTemplate) {
this._contentTree.render(this._trs({
columns,
editedColumn: options.editedColumn,
editedColumnIndex: options.editedColumnIndex,
aggregates: options.aggregates,
selected,
data,
childrenMap,
viewChildrenMap,
hasFooterTemplate,
visible: true,
level: 0
}));
},
_setExpanderElement: function() {
var that = this, hiddenDivClass = "k-grid-content-expander", hiddenDiv = "<div class=\"" + hiddenDivClass + "\"></div>", expander;
if (that.options.scrollable && that.wrapper.is(":visible")) {
expander = that.table.parent().children("." + hiddenDivClass);
if (!that.dataSource || !that.dataSource.view().length) {
if (!expander[0]) {
expander = $(hiddenDiv).appendTo(that.table.parent());
}
if (that.thead) {
expander.width(that.thead.width());
}
} else if (expander[0]) {
expander.remove();
}
}
},
_renderProgress: function(toggle) {
kendo.ui.progress(this.wrapper, toggle);
},
_renderOptions: function(options) {
options = options || {};
var that = this;
var dataMaps = that.dataSource._getDataMaps();
var filter = that.dataSource.filter();
if (that._isPageable()) {
options.childrenMap = dataMaps.children;
options.idsMap = dataMaps.ids;
if (filter) {
options.filteredChildrenMap = dataMaps.filteredChildren;
}
}
return options;
},
_renderedModelLevel: function(model, options) {
return !this._isPageable() ? 0 : this.dataSource._pageableModelLevel(model, options);
},
_viewChildrenMap: function(options) {
options = options || {};
var that = this;
var dataSource = that.dataSource;
var viewChildrenMap = dataSource.childrenMap(dataSource.view());
var idField = dataSource._modelIdField();
var parentsNotInView = dataSource._parentNodesNotInView();
var parentNotInView;
var parentNotInViewId;
var parents;
var parent;
var parentId;
var child;
var childId;
var parentsCopy;
that._clearRenderMap();
for (var i = 0; i < parentsNotInView.length; i++) {
parentNotInView = parentsNotInView[i];
parentNotInViewId = parentNotInView[idField];
that._markNodeAsNonRenderable(parentNotInViewId);
viewChildrenMap[parentNotInViewId] = viewChildrenMap[parentNotInViewId] || [];
parents = dataSource._parentNodes(parentNotInView);
parentsCopy = parents.slice();
parentsCopy.push(parentNotInView);
for (var parentIndex = 0; parentIndex < parentsCopy.length - 1; parentIndex++) {
parent = parentsCopy[parentIndex];
parentId = parent[idField];
that._markNodeAsNonRenderable(parentId);
viewChildrenMap[parentId] = viewChildrenMap[parentId] || [];
child = parentsCopy[parentIndex + 1];
childId = child[idField];
that._markNodeAsNonRenderable(childId);
viewChildrenMap[childId] = viewChildrenMap[childId] || [];
if (viewChildrenMap[parentId].indexOf(child) === -1) {
viewChildrenMap[parentId].unshift(child);
}
}
}
return viewChildrenMap;
},
_clearRenderMap: function() {
this._skipRenderingMap = {};
},
_dataToRender: function(options) {
var that = this;
if (that._isPageable()) {
return that.dataSource._pageableRootNodes(options);
}
return that.dataSource.rootNodes();
},
_markNodeAsNonRenderable: function(nodeId) {
this._skipRenderingMap[nodeId] = true;
},
_adjustRowsHeight: function(table1, table2) {
if (!this._hasLockedColumns) {
return;
}
var rows = table1[0].rows;
var length = rows.length;
var idx;
var rows2 = table2[0].rows;
var containers = table1.add(table2);
var containersLength = containers.length;
var heights = [];
for (idx = 0; idx < length; idx++) {
if (!rows2[idx]) {
break;
}
if (rows[idx].style.height) {
rows[idx].style.height = rows2[idx].style.height = "";
}
}
for (idx = 0; idx < length; idx++) {
if (!rows2[idx]) {
break;
}
var offsetHeight1 = rows[idx].offsetHeight;
var offsetHeight2 = rows2[idx].offsetHeight;
var height = 0;
if (offsetHeight1 > offsetHeight2) {
height = offsetHeight1;
} else if (offsetHeight1 < offsetHeight2) {
height = offsetHeight2;
}
heights.push(height);
}
for (idx = 0; idx < containersLength; idx++) {
containers[idx].style.display = "none";
}
for (idx = 0; idx < length; idx++) {
if (heights[idx]) {
rows[idx].style.height = rows2[idx].style.height = heights[idx] + 1 + "px";
}
}
for (idx = 0; idx < containersLength; idx++) {
containers[idx].style.display = "";
}
},
_ths: function(columns, rowSpan) {
var ths = [];
var column, title, children, cellClasses, attr, headerContent;
var index;
var leafs;
for (var i = 0, length = columns.length; i < length; i++) {
column = columns[i];
children = [];
cellClasses = [classNames.header];
if (column.selectable) {
leafs = leafColumns(columns);
index = inArray(column, leafs);
attr = {
scope: "col",
role: "columnheader",
className: cellClasses.join(" ")
};
if (column.headerTemplate) {
title = column.headerTemplate({});
}
title = column.headerTemplate ? title : kendo.template(() => SELECTCOLUMNHEADERTMPL)({});
if (rowSpan && !column.colSpan) {
attr.rowSpan = rowSpan;
}
if (index > -1) {
attr[kendo.attr("index")] = index;
}
children.push(kendoHtmlElement(title));
ths.push(kendoDomElement("th", $.extend(true, {}, attr, column.headerAttributes), children));
continue;
}
if (column.headerTemplate) {
title = column.headerTemplate({});
} else {
title = column.title || column.field || "";
}
if (column.headerTemplate) {
headerContent = kendoHtmlElement(title);
} else {
headerContent = kendoTextElement(title);
}
if (this.options.sortable) {
if (!column.draggable) {
children.push(kendoDomElement("span", { className: classNames.headerCellInner }, [kendoDomElement("span", { className: classNames.link }, [kendoDomElement("span", { className: classNames.columnTitle }, [headerContent])])]));
}
} else {
children.push(headerContent);
}
attr = {
"data-field": column.field,
"data-title": column.title,
"style": column.hidden === true ? { "display": "none" } : {},
className: cellClasses.join(" "),
"role": "columnheader"
};
if (this.options.sortable && column.sortable !== false) {
let sortableTitle = `${column.title || column.field}. ${this.options.messages.sortHeader}`;
attr["aria-label"] = sortableTitle;
attr["title"] = sortableTitle;
}
if (!column.columns) {
attr.rowSpan = rowSpan ? rowSpan : 1;
}
if (column.headerAttributes) {
if (column.headerAttributes.colSpan === 1) {
delete column.headerAttributes.colSpan;
}
if (column.headerAttributes["class"]) {
attr.className += " " + column.headerAttributes["class"];
}
}
if (column["data-index"] > -1) {
attr["data-index"] = column["data-index"];
}
let headerAttributesCopy = { ...column.headerAttributes };
delete headerAttributesCopy["class"];
attr = extend(true, {}, attr, headerAttributesCopy);
ths.push(kendoDomElement("th", attr, children));
}
return ths;
},
_cols: function(columns) {
var cols = [];
var width, attr;
for (var i = 0; i < columns.length; i++) {
if (columns[i].hidden === true) {
continue;
}
width = columns[i].width;
attr = {};
if (width && parseInt(width, 10) !== 0) {
attr.style = { width: typeof width === "string" ? width : width + "px" };
}
if (columns[i].draggable) {
attr.class = "k-drag-col";
}
cols.push(kendoDomElement("col", attr));
}
return cols;
},
_clearColsCache: function() {
this._headerColsTree.render([]);
if (this.options.scrollable) {
this._contentColsTree.render([]);
}
if (this._hasLockedColumns) {
this._lockedHeaderColsTree.render([]);
this._lockedContentColsTree.render([]);
}
},
_renderCols: function() {
var columns = nonLockedColumns(this.columns);
if (this.options.hasHeader) {
this._headerColsTree.render(this._cols(leafColumns(columns)));
}
if (this.options.scrollable) {
this._contentColsTree.render(this._cols(leafColumns(columns)));
}
if (this._hasLockedColumns) {
columns = lockedColumns(this.columns);
if (this.options.hasHeader) {
this._lockedHeaderColsTree.render(this._cols(leafColumns(columns)));
}
this._lockedContentColsTree.render(this._cols(leafColumns(columns)));
if (!this.options.hasHeader) {
this._applyLockedContainersWidth();
}
}
},
_retrieveFirstColumn: function(columns, rows) {
var result = $();
if (rows.length && columns[0]) {
var column = columns[0];
while (column.columns && column.columns.length) {
column = column.columns[0];
rows = rows.filter(":not(:first)");
}
result = result.add(rows);
}
return result;
},
_updateFirstColumnClass: function() {
var that = this;
var columns = that.columns || [];
var tr = that.thead.find(">tr:not(:first, .k-filter-row)");
var rows;
columns = nonLockedColumns(columns);
rows = that._retrieveFirstColumn(columns, tr);
if (that.lockedHeader) {
tr = that.lockedHeader.find("thead>tr:not(.k-filter-row):not(:first)");
columns = lockedColumns(that.columns);
rows = rows.add(that._retrieveFirstColumn(columns, tr));
}
rows.each(function() {
var ths = $(this).find("th");
ths.removeClass("k-first");
ths.eq(0).addClass("k-first");
});
},
_updateRowSpans: function(rows) {
for (var i = rows.length - 1; i >= 0; i--) {
var included = visibleChildColumns(rows[i].cells).length > 0;
if (included) {
rows[i].rowSpan = rows.length - i;
}
}
},
_setColumnDataIndexes: function(columns) {
for (var i = 0; i < columns.length; i++) {
columns[i]["data-index"] = i;
}
},
_updateColumnCellIndex: function() {
var header;
var offset = 0;
if (this.lockedHeader) {
header = this.lockedHeader.find("thead");
offset = updateCellIndex(header, lockedColumns(this.columns));
}
updateCellIndex(this.thead, nonLockedColumns(this.columns), offset);
},
_setParentsVisibility: function(column, visible) {
var columns = this.columns;
var idx;
var parents = [];
var parent;
var predicate = visible ? function(p) {
return visibleColumns(p.columns).length && p.hidden;
} : function(p) {
return !visibleColumns(p.columns).length && !p.hidden;
};
if (columnParents(column, columns, parents) && parents.length) {
for (idx = parents.length - 1; idx >= 0; idx--) {
parent = parents[idx];
if (predicate(parent)) {
parent.hidden = !visible;
}
}
}
},
_prepareColumns: function(rows, columns, parentCell, parentRow, parentColumn) {
var row = parentRow || rows[rows.length - 1];
var childRow = rows[row.index + 1];
var totalColSpan = 0;
for (var idx = 0; idx < columns.length; idx++) {
var cell = $.extend({}, columns[idx], { headerAttributes: columns[idx].headerAttributes || {} });
row.cells.push(cell);
if (columns[idx].columns && columns[idx].columns.length) {
if (!childRow) {
childRow = {
rowSpan: 0,
cells: [],
index: rows.length
};
rows.push(childRow);
}
if (columns[idx].columns.length) {
cell.headerAttributes.colSpan = visibleChildColumns(columns[idx].columns).length || 1;
cell.headerAttributes["data-colspan"] = leafColumns(columns[idx].columns).length;
}
this._prepareColumns(rows, columns[idx].columns, cell, childRow, columns[idx]);
if (!cell.hidden) {
totalColSpan += cell.headerAttributes.colSpan - 1;
}
row.rowSpan = rows.length - row.index;
}
columns[idx].rowIndex = row.index;
if (parentColumn) {
columns[idx].parentColumn = parentColumn;
}
columns[idx].cellIndex = row.cells.length - 1;
}
if (parentCell) {
parentCell.headerAttributes.colSpan += totalColSpan;
}
},
_renderHeaderTree: function(tree, columns, hasMultiColumnHeaders) {
var idx;
var rows = [];
var rowsToRender = [];
var filterThs = [];
if (hasMultiColumnHeaders) {
rows = [{
rowSpan: 1,
cells: [],
index: 0
}];
this._prepareColumns(rows, columns);
this._updateRowSpans(rows);
for (idx = 0; idx < rows.length; idx++) {
rowsToRender.push(kendoDomElement("tr", {
"role": "row",
"class": "k-table-row"
}, this._ths(rows[idx].cells, rows[idx].rowSpan)));
}
} else {
rowsToRender.push(kendoDomElement("tr", {
"role": "row",
"class": "k-table-row"
}, this._ths(columns)));
}
if (this._hasFilterRow()) {
this._filterThs(columns, filterThs);
rowsToRender.push(kendoDomElement("tr", { "class": "k-filter-row k-table-row" }, filterThs));
}
tree.render(rowsToRender);
},
_renderHeader: function() {
var columns = nonLockedColumns(this.columns);
var hasMultiColumnHeaders = grep(this.columns, function(item) {
return item.columns !== undefined;
}).length > 0;
this._setColumnDataIndexes(leafColumns(this.columns));
this._renderHeaderTree(this._headerTree, columns, hasMultiColumnHeaders);
if (this._hasLockedColumns) {
columns = lockedColumns(this.columns);
this._renderHeaderTree(this._lockedHeaderTree, columns, hasMultiColumnHeaders);
this._applyLockedContainersWidth();
this._syncLockedHeaderHeight();
}
this._updateFirstColumnClass();
},
_filterThs: function(columns, ths) {
var column;
var attr;
var uidAttr = kendo.attr("uid");
for (var i = 0, length = columns.length; i < length; i++) {
column = columns[i];
if (column.columns) {
this._filterThs(column.columns, ths);
}
if (column.columns && column.columns.length) {
continue;
}
attr = {
"style": column.hidden === true ? { "display": "none" } : {},
"className": "k-table-th k-header",
"title": this.options.messages.filterCellTitle,
"aria-label": this.options.messages.filterCellTitle
};
attr[uidAttr] = column.headerAttributes.id;
ths.push(kendoDomElement("th", attr));
}
},
_updateFilterThs: function(before, column, refColumn) {
var columns = leafColumns([column]);
var filterRowThs = $(this.lockedHeader).add(this.thead).find("tr.k-filter-row th");
var refIndex;
var currIndex;
var uidAttr = kendo.attr("uid");
function thIndex(ths, uid) {
for (var i = 0; i < ths.length; i++) {
if (ths.eq(i).attr(uidAttr) === uid) {
return i;
}
}
}
for (var i = columns.length - 1; i >= 0; i--) {
column = columns[i];
currIndex = thIndex(filterRowThs, column.headerAttributes.id);
refIndex = thIndex(filterRowThs, refColumn.headerAttributes.id);
filterRowThs.eq(currIndex)[before ? "insertBefore" : "insertAfter"](filterRowThs.eq(refIndex));
}
},
_applyLockedContainersWidth: function() {
if (!this._hasLockedColumns) {
return;
}
var lockedWidth = this.options.hasHeader ? columnsWidth(this.lockedHeader.find(">table>colgroup>col")) : columnsWidth(this.lockedTable.find(">colgroup>col"));
var headerTable = this.options.hasHeader ? this.thead.parent() : this.tbody.parent();
var nonLockedWidth = columnsWidth(headerTable.find(">colgroup>col"));
var wrapperWidth = this.wrapper[0].clientWidth;
var scrollbar = kendo.support.scrollbar();
if (lockedWidth >= wrapperWidth) {
lockedWidth = wrapperWidth - 3 * scrollbar;
}
this.lockedHeader.add(this.lockedContent).width(lockedWidth);
headerTable.add(this.table).width(nonLockedWidth);
var width = wrapperWidth - lockedWidth;
this.content.width(width - 1);
headerTable.parent().width(width - scrollbar - 2);
},
_generateRowOptions: function(model, attr, pageable, options, level, hasChildren) {
var that = this;
var rowOptions = {
model,
attr,
level: pageable ? that._renderedModelLevel(model, options) : level,
editedColumn: options.editedColumn,
editedColumnIndex: options.editedColumnIndex,
hasChildren,
visible: options.visible,
isAlt: this._absoluteIndex % 2 === 0
};
return rowOptions;
},
_renderRow: function(rowOptions, columns, renderer) {
return this._tds(rowOptions, columns, renderer);
},
_trs: function(options) {
var that = this;
var model, attr, className, hasChildren, childNodes, i, length;
var modelId;
var rows = [];
var level = options.level;
var data = options.data;
var dataSource = this.dataSource;
var aggregates = dataSource.aggregates() || {};
var idField = dataSource._modelIdField();
var parentIdField = dataSource._modelParentIdField();
var columns = options.columns;
var pageable = that._isPageable();
var isLockedTable = options.isLockedTable;
var childrenMap = options.childrenMap || dataSource.childrenMap(dataSource._getData());
for (i = 0, length = data.length; i < length; i++) {
className = ["k-table-row"];
model = data[i];
modelId = model[idField];
childNodes = pageable ? childrenMap[modelId] : model.loaded() ? dataSource.childNodes(model) : [];
hasChildren = childNodes && childNodes.length;
attr = { "role": "row" };
attr[kendo.attr("uid")] = model.uid;
if (!isLockedTable && hasChildren) {
attr[ARIA_EXPANDED] = !!model.expanded;
}
if (options.visible) {
if (!pageable || pageable && !that._skipRenderingMap[modelId]) {
if (this._absoluteIndex % 2 !== 0) {
className.push(classNames.alt);
}
this._absoluteIndex++;
}
} else {
attr.style = { display: "none" };
}
if ($.inArray(model.uid, options.selected) >= 0) {
className.push(classNames.selected);
}
if (model._edit) {
className.push("k-grid-edit-row");
}
attr.className = className.join(" ");
if (!that._skipRenderingMap[modelId]) {
var row;
var rowOptions = that._generateRowOptions(model, attr, pageable, options, level, hasChildren);
if (that.options.rowTemplate) {
row = this._trFromTemplate(rowOptions);
} else {
row = this._renderRow(rowOptions, columns, this._td.bind(this));
}
rows.push(row);
}
if (hasChildren && (that.options.renderAllRows || !!model.expanded)) {
if (pageable) {
childNodes = (options.viewChildrenMap || {})[modelId] || [];
}
if (childNodes.length === 0) {
continue;
}
rows = rows.concat(this._trs({
columns,
editedColumn: options.editedColumn,
editedColumnIndex: options.editedColumnIndex,
aggregates,
selected: options.selected,
visible: pageable ? options.visible : options.visible && !!model.expanded,
data: childNodes,
childrenMap: options.childrenMap || childrenMap,
hasFooterTemplate: options.hasFooterTemplate,
viewChildrenMap: options.viewChildrenMap,
level: level + 1,
isLockedTable: options.isLockedTable
}));
}
}
if (options.hasFooterTemplate && model) {
attr = {
className: classNames.footerTemplate + " k-table-row",
"data-parentId": model[parentIdField]
};
if (!options.visible) {
attr.style = { display: "none" };
}
rows.push(this._tds({
model: aggregates[model[parentIdField]],
attr,
level,
editedColumn: options.editedColumn,
editedColumnIndex: options.editedColumnIndex
}, columns, this._footerId));
}
return rows;
},
_trFromTemplate: function(options) {
var rowTemplate = this.options.rowTemplate;
var altRowTemplate = this.options.altRowTemplate;
var row;
var template;
altRowTemplate = altRowTemplate ? altRowTemplate : rowTemplate;
if (!kendo.isFunction(rowTemplate)) {
rowTemplate = kendo.template(rowTemplate);
}
if (!kendo.isFunction(altRowTemplate)) {
altRowTemplate = kendo.template(altRowTemplate);
}
if (this._absoluteIndex % 2 !== 0) {
template = rowTemplate(options);
} else {
template = altRowTemplate(options);
}
if (!$(template).length) {
return kendoTextElement(template);
}
row = this.parseRowTemplate($(template)[0], options);
return row;
},
parseRowTemplate: function(element, options) {
var nodeName = element.nodeName.toLocaleLowerCase();
var childNodes = element.childNodes;
var children = [];
var currElement;
var attributes;
attributes = this.parseAttributes(element);
for (var i = 0; i < childNodes.length; i++) {
if (!/\S/.test(childNodes[i].nodeValue)) {
continue;
}
if (childNodes[i].nodeName.toLocaleLowerCase() === "td") {
children.push(this._createCellElement(childNodes[i]));
}
}
if (options && !options.visible) {
attributes.style = attributes.style || {};
attributes.style = $.extend(true, attributes.style, { display: "none" });
}
if (this._isTextNode(nodeName)) {
currElement = kendoTextElement(element.nodeValue);
} else {
currElement = kendoDomElement(nodeName, attributes, children);
}
return currElement;
},
_createCellElement: function(element) {
var attributes = this.parseAttributes(element);
var spaceElements = $(element).find("." + classNames.iconHidden).remove();
var iconElement = $(element).find(ICON_EXPAND_COLLAPSE_SELECTOR).remove()[0];
var children = [];
for (var i = 0; i < spaceElements.length; i++) {
children.push(kendoDomElement("span", this.parseAttributes(spaceElements[i])));
}
if (iconElement) {
children.push(kendoHtmlElement(iconElement.outerHTML, true));
}
children.push(kendoHtmlElement($(element).html()));
return kendoDomElement("td", attributes, children);
},
parseAttributes: function(element) {
if (this._isTextNode(element.nodeName)) {
return null;
}
element = $(element)[0];
var attributes = element.attributes;
var length = attributes.length;
var result = {};
for (var i = 0; i < length; i++) {
result[attributes[i].name] = attributes[i].value;
}
return result;
},
_isTextNode: function(nodeName) {
return nodeName.indexOf("text") >= 0;
},
_footerId: function(options) {
var content = [];
var column = options.column;
var template = options.column.footerTemplate || $.noop;
var aggregates = options.model[column.field] || {};
var attr = {
"role": "gridcell",
"class": "k-table-td",
"style": column.hidden === true ? { "display": "none" } : {}
};
if (column.expandable) {
content = content.concat(createPlaceholders({
level: options.level + 1,
className: classNames.iconPlaceHolder
}));
}
if (column.attributes) {
extend(true, attr, column.attributes, { "style": column.hidden === true ? { "display": "none" } : {} });
}
content.push(kendoHtmlElement(template(aggregates) || ""));
return kendoDomElement("td", attr, content);
},
_hasFooterTemplate: function() {
return !!grep(leafColumns(this.columns), function(c) {
return c.footerTemplate;
}).length;
},
_tds: function(options, columns, renderer) {
var children = [];
var column;
var editedColumnField = (options.editedColumn || {}).field;
var incellEditing = this._isIncellEditable();
var length = columns.length;
for (var i = 0; i < length; i++) {
column = columns[i];
var col = renderer({
model: options.model,
column,
editColumn: !incellEditing || incellEditing && column.field === editedColumnField && options.editedColumnIndex === i,
level: options.level
});
children.push(col);
}
return kendoDomElement("tr", options.attr, children);
},
_td: function(options) {
var children = [];
var model = options.model;
var column = options.column;
var iconType = kendo.defaults.iconType;
var iconClass;
var attr = {
"role": "gridcell",
"class": "k-table-td",
"style": column.hidden === true ? { "display": "none" } : {}
};
var incellEditing = this._isIncellEditable();
var columnHasEditCommand = false;
if (column.attributes) {
extend(true, attr, column.attributes);
}
if (!!column.headerAttributes && !!column.headerAttributes.id) {
attr["aria-describedby"] = column.headerAttributes.id;
}
if (model._edit && column.field && options.editColumn && (incellEditing || !incellEditing && isColumnEditable(column, model))) {
attr[kendo.attr("container-for")] = column.field;
if (incellEditing) {
if (attr.className && attr.className.indexOf(classNames.editCell) !== -1) {
attr.className += " k-table-td" + classNames.editCell;
} else if (!attr.className) {
attr.className = "k-table-td " + classNames.editCell;
}
}
} else {
if (column.expandable) {
children = createPlaceholders({
level: options.level,
className: classNames.iconPlaceHolder
});
if (model.hasChildren) {
attr.ariaExpanded = model.expanded;
iconClass = model.expanded ? classNames.iconCollapse : classNames.iconExpand;
} else {
iconClass = classNames.iconPlaceHolder;
}
if (model._error) {
iconClass = classNames.refresh;
} else if (!model.loaded() && model.expanded) {
iconClass = "loading";
attr["aria-busy"] = true;
}
children.push(kendoHtmlElement(kendo.ui.icon($(`<span ref-treelist-expand-collapse-icon ${iconClass === classNames.iconPlaceHolder ? "ref-blank-icon" : ""} class="k-treelist-toggle ${iconClass === classNames.iconPlaceHolder ? "" : iconClass === "loading" ? "k-i-loading" : ""}"></span>`), {
icon: iconClass,
type: iconType
}), true));
attr.style["white-space"] = "nowrap";
}
if (isDirtyColumn(column, model)) {
if (attr.className) {
attr.className += classNames.dirtyCell;
} else if (!attr.className) {
attr.className = classNames.dirtyCell;
}
}
if (column.draggable) {
attr["class"] += " k-drag-cell k-touch-action-none";
attr["ref-treelist-drag-cell"] = true;
if (typeof attr[ARIA_LABEL] === "undefined") {
attr[ARIA_LABEL] = this.options.messages.dragHandleLabel;
}
attr.style.cursor = "move";
}
if (column.command) {
if (attr.className && attr.className.indexOf("k-command-cell") !== -1) {
attr.className += " k-command-cell";
} else if (!attr.className) {
attr.className = "k-command-cell";
}
columnHasEditCommand = grep(column.command, function(command) {
return command === EDIT || command.name === EDIT;
}).length > 0;
if (model._edit && !this._isIncellEditable() && columnHasEditCommand) {
children = this._buildCommands(["update", "canceledit"]);
} else {
children = this._buildCommands(column.command);
}
} else {
children.push(this._cellContent(column, model));
}
attr.className = [attr["class"], attr.className].join(" ").trim();
}
return kendoDomElement("td", attr, children);
},
_cellContent: function(column, model) {
var that = this;
var value;
var incellEditing = that._isIncellEditable();
var dirtyIndicator;
if (column.selectable) {
return kendoHtmlElement(SELECTCOLUMNTMPL);
}
if (column.draggable) {
return kendoHtmlElement(DRAGHANDLECOLUMNTMPL());
}
if (column.template) {
value = that._evalColumnTemplate(column, model);
} else if (column.field) {
value = model.get(column.field);
dirtyIndicator = incellEditing ? column.dirtyIndicatorTemplate(model) : "";
if (value !== null && !isUndefined(value)) {
if (column.format) {
value = kendo.format(column.format, value);
}
value = dirtyIndicator + value;
} else {
value = dirtyIndicator;
}
} else if (value === null || isUndefined(value)) {
value = "";
}
if (column.template || !column.encoded) {
return kendoHtmlElement(value);
} else {
if (incellEditing) {
return kendoHtmlElement(value);
} else {
return kendoTextElement(value);
}
}
},
_evalColumnTemplate: function(column, model) {
if (this._isIncellEditable()) {
return column.dirtyCellTemplate(model);
} else {
return column.template(model);
}
},
_createDirtyColumnTemplate: function(column) {
var that = this;
var templateSettings = that._customTemplateSettings();
var templateFunction = function(data) {
return that._dirtyIndicatorTemplate(column.field)(data) + this.columnTemplate(data);
};
return kendoTemplate(templateFunction, templateSettings).bind({ columnTemplate: column.template });
},
_createIndicatorTemplate: function(column) {
var dirtyIndicatorTemplate = this._dirtyIndicatorTemplate(column.field);
return kendoTemplate(dirtyIndicatorTemplate);
},
_dirtyIndicatorTemplate: function(field) {
var that = this;
var dirtyField;
var templateSettings = that._customTemplateSettings();
var paramName = templateSettings.paramName;
if (field && paramName) {
return ({ dirty, dirtyFields }) => dirty && dirtyFields && dirtyFields[field] ? "<span class=\"k-dirty\"></span>" : "";
}
return () => "";
},
_customTemplateSettings: function() {
return extend({}, kendo.Template, this.options.templateSettings);
},
_buildCommands: function(commands, skipCommandClass) {
var i, result = [];
for (i = 0; i < commands.length; i++) {
result.push(this._handleCommand(commands[i], skipCommandClass));
}
return result;
},
_handleCommand: function(command, skipCommandClass) {
var name = (command.name || command).toLowerCase();
var text = this.options.messages.commands[name];
command = extend({}, defaultCommands[name], { text }, command);
if (command.template) {
return kendoHtmlElement(kendo.template(command.template)({ message: command.text || this.options.messages.commands.search }));
} else {
return this._button(command, name, command.icon, skipCommandClass);
}
},
_button: function(command, name, icon, skipCommandClass) {
if (command.className && command.className.indexOf("k-primary") > -1) {
command.className = command.className.replace("k-primary", "k-button-primary");
}
if (!command.className || command.className.indexOf("k-button-primary") === -1) {
command.className = command.className || "";
}
if (skipCommandClass && command.className) {
let classes = command.className.split(" ");
command.className = classes.filter((c) => c.indexOf("command") === -1).join(" ");
}
let buttonHTML = "<button data-command=\"" + name + "\" class=\"" + command.className + "\">" + (command.text || (command.text === "" ? "" : command.name)) + "</button>";
let button = kendoHtmlElement(kendo.html.renderButton(buttonHTML, {
icon,
iconClass: command.imageClass
}));
return button;
},
_positionResizeHandle: function(e) {
var th = $(e.currentTarget);
var resizeHandle = this.resizeHandle;
var position = th.position();
var left;
var rtlCorrection = 0;
var headerWrap;
var ieCorrection;
var webkitCorrection;
var firefoxCorrection;
var leftMargin;
var invisibleSpace;
var leftBorderWidth;
var scrollLeft;
var cellWidth = outerWidth(th);
var container = th.closest("div");
var button = typeof e.buttons !== "undefined" ? e.buttons : e.which || e.button;
var indicatorWidth = this.options.columnResizeHandleWidth || 3;
var halfResizeHandle = indicatorWidth * 3 / 2;
left = cellWidth;
if (typeof button !== "undefined" && button !== 0) {
return;
}
if (!resizeHandle) {
resizeHandle = this.resizeHandle = $("<div class=\"k-resize-handle\"><div class=\"k-resize-handle-inner\"></div></div>");
}
var cells = leafDataCells(th.closest("thead")).filter(":visible");
if (isRtl) {
scrollLeft = kendo.scrollLeft(container);
if (browser.mozilla || browser.webkit && browser.version >= 85) {
scrollLeft = scrollLeft * -1;
}
leftBorderWidth = parseFloat(container.css("borderLeftWidth"));
left = th.offset().left + scrollLeft - parseFloat(th.css("marginLeft")) - (container.offset().left + leftBorderWidth);
rtlCorrection = left <= scrollLeft ? halfResizeHandle : 0;
headerWrap = th.closest(".k-grid-header-wrap, .k-grid-header-locked");
invisibleSpace = headerWrap[0].scrollWidth - headerWrap[0].offsetWidth;
leftMargin = parseFloat(headerWrap.css("marginLeft"));
ieCorrection = browser.msie ? 2 * kendo.scrollLeft(headerWrap) + leftBorderWidth - leftMargin - rtlCorrection : 0;
webkitCorrection = browser.webkit && browser.version < 85 ? invisibleSpace - rtlCorrection - leftMargin + leftBorderWidth : -rtlCorrection;
firefoxCorrection = browser.mozilla ? leftBorderWidth - leftMargin - rtlCorrection : 0;
left -= webkitCorrection + firefoxCorrection + ieCorrection;
} else {
for (var idx = 0; idx < cells.length; idx++) {
if (cells[idx] == th[0]) {
break;
}
left += cells[idx].offsetWidth;
}
}
container.append(resizeHandle);
resizeHandle.show().css({
top: position.top,
left: left - halfResizeHandle,
height: outerHeight(th),
width: indicatorWidth * 3
}).data("th", th);
var that = this;
resizeHandle.off("dblclick" + NS).on("dblclick" + NS, function() {
var index = th.index();
if ($.contains(that.thead[0], th[0])) {
index += grep(that.columns, function(val) {
return val.locked && !val.hidden;
}).length;
}
that.autoFitColumn(index);
});
},
autoFitColumn: function(column) {
var that = this, options = that.options, columns = that.columns, index, th, headerTable, isLocked, visibleLocked = that.lockedHeader ? leafDataCells(that.lockedHeader.find(">table>thead")).filter(isCellVisible).length : 0, col;
if (typeof column == "number") {
column = columns[column];
} else if (isPlainObject(column)) {
column = grep(columns, function(item) {
return item === column;
})[0];
} else {
column = grep(columns, function(item) {
return item.field === column;
})[0];
}
if (!column || column.hidden) {
return;
}
index = inArray(column, columns);
isLocked = column.locked;
if (isLocked) {
headerTable = that.lockedHeader.children("table");
} else {
headerTable = that.thead.parent();
}
th = headerTable.find("[data-index='" + index + "']");
var contentTable = isLocked ? that.lockedTable : that.table, footer = that.footer || $();
if (that.footer && that.lockedContent) {
footer = isLocked ? that.footer.children(".k-grid-footer-locked") : that.footer.children(".k-grid-footer-wrap");
}
var footerTable = footer.find("table").first();
if (that.lockedHeader && visibleLocked >= index && !isLocked) {
index -= visibleLocked;
}
for (var j = 0; j < columns.length; j++) {
if (columns[j] === column) {
break;
} else {
if (columns[j].hidden) {
index--;
}
}
}
if (options.scrollable) {
col = headerTable.find("col:not(.k-group-col):not(.k-hierarchy-col)").eq(index).add(contentTable.children("colgroup").find("col:not(.k-group-col):not(.k-hierarchy-col)").eq(index)).add(footerTable.find("colgroup").find("col:not(.k-group-col):not(.k-hierarchy-col)").eq(index));
} else {
col = contentTable.children("colgroup").find("col:not(.k-group-col):not(.k-hierarchy-col)").eq(index);
}
var tables = headerTable.add(contentTable).add(footerTable);
var oldColumnWidth = outerWidth(th);
col.width("");
tables.css("table-layout", "fixed");
col.width("auto");
tables.addClass("k-autofitting");
tables.css("table-layout", "");
var newColumnWidth = Math.ceil(Math.max(outerWidth(th), outerWidth(contentTable.find("tr").eq(0).children("td:visible").eq(index)), outerWidth(footerTable.find("tr").eq(0).children("td:visible").eq(index))));
col.width(newColumnWidth);
column.width = newColumnWidth;
if (options.scrollable) {
var cols = headerTable.find("col"), colWidth, totalWidth = 0;
for (var idx = 0, length = cols.length; idx < length; idx += 1) {
colWidth = cols[idx].style.width;
if (colWidth && colWidth.indexOf("%") == -1) {
totalWidth += parseInt(colWidth, 10);
} else {
totalWidth = 0;
break;
}
}
if (totalWidth) {
tables.each(function() {
this.style.width = totalWidth + "px";
});
}
}
tables.removeClass("k-autofitting");
that.trigger(COLUMNRESIZE, {
column,
oldWidth: oldColumnWidth,
newWidth: newColumnWidth
});
that._applyLockedContainersWidth();
that._syncLockedContentHeight();
that._syncLockedHeaderHeight();
},
_adjustLockedHorizontalScrollBar: function() {
var table = this.table, content = table.parent();
var scrollbar = table[0].offsetWidth > content[0].clientWidth ? kendo.support.scrollbar() : 0;
this.lockedContent.height(outerHeight(content) - scrollbar);
},
_syncLockedContentHeight: function() {
if (this.lockedTable) {
if (!this._touchScroller) {
this._adjustLockedHorizontalScrollBar();
}
this._adjustRowsHeight(this.table, this.lockedTable);
this._syncLockedScroll();
}
},
_syncLockedHeaderHeight: function() {
if (this.lockedHeader) {
var lockedTable = this.lockedHeader.children("table");
var table = this.thead.parent();
this._adjustRowsHeight(lockedTable, table);
syncTableHeight(lockedTable, table);
}
},
_syncLockedScroll: function() {
if (!this.options.scrollable) {
return;
}
this.lockedContent[0].scrollTop = this.content[0].scrollTop;
},
_resizable: function() {
if (!this.options.resizable) {
return;
}
if (this.resizable) {
this.resizable.destroy();
}
var treelist = this;
$(this.lockedHeader).find("thead").add(this.thead).on("mousemove" + NS, "tr:not(.k-filter-row) > th", this._positionResizeHandle.bind(this));
this.resizable = new kendo.ui.Resizable(this.wrapper, {
handle: ".k-resize-handle",
start: function(e) {
var th = $(e.currentTarget).data("th");
var index = $.inArray(th[0], leafDataCells(th.closest("thead")).filter(":visible"));
var header, contentTable;
treelist.wrapper.addClass("k-grid-column-resizing");
if (treelist.lockedHeader && $.contains(treelist.lockedHeader[0], th[0])) {
header = treelist.lockedHeader;
contentTable = treelist.lockedTable;
} else {
header = treelist.thead.parent();
contentTable = treelist.table;
}
this.col = contentTable.children("colgroup").find("col").eq(index).add(header.find("col").eq(index));
this.th = th;
this.startLocation = e.x.location;
this.columnWidth = outerWidth(th);
this.table = this.col.closest("table");
this.totalWidth = this.table.width();
},
resize: function(e) {
var rtlModifier = isRtl ? -1 : 1;
var minColumnWidth = 11;
var delta = e.x.location * rtlModifier - this.startLocation * rtlModifier;
if (this.columnWidth + delta < minColumnWidth) {
delta = minColumnWidth - this.columnWidth;
}
this.table.width(this.totalWidth + delta);
this.col.width(this.columnWidth + delta);
},
resizeend: function() {
treelist.wrapper.removeClass("k-grid-column-resizing");
var field = this.th.attr("data-field");
var column = grep(leafColumns(treelist.columns), function(c) {
return c.field == field;
});
var newWidth = Math.floor(outerWidth(this.th));
column[0].width = newWidth;
treelist._resize();
treelist._syncLockedContentHeight();
treelist._syncLockedHeaderHeight();
treelist.trigger(COLUMNRESIZE, {
column,
oldWidth: this.columnWidth,
newWidth
});
this.table = this.col = this.th = null;
}
});
},
_sortable: function() {
var columns;
var column;
var sortableInstance;
var cells;
var cell, idx, length;
var sortable = this.options.sortable;
var hasMultiColumnHeaders = grep(this.columns, function(item) {
return item.columns !== undefined;
}).length > 0;
var sortHandler = this._sort.bind(this);
if (!sortable) {
return;
}
if (hasMultiColumnHeaders) {
if (this.lockedHeader) {
cells = sortCells(leafDataCells(this.lockedHeader.find(">table>thead")).add(leafDataCells(this.thead)));
} else {
cells = leafDataCells(this.thead);
}
} else {
cells = $(this.lockedHeader).add(this.thead).find("tr:not(.k-filter-row) th");
}
columns = leafColumns(this.columns);
for (idx = 0, length = cells.length; idx < length; idx++) {
column = columns[idx];
if (column.sortable !== false && !column.command && !column.draggable && column.field && !column.selectable) {
cell = cells.eq(idx);
sortableInstance = cell.data("kendoColumnSorter");
if (sortableInstance) {
sortableInstance.destroy();
}
cell.kendoColumnSorter(extend({}, sortable, column.sortable, {
dataSource: this.dataSource,
change: sortHandler
}));
}
}
},
_filterable: function() {
var cells;
var filterable = this.options.filterable;
var idx;
var length;
var columns;
var column;
var cell;
var filterMenuInstance;
var hasMultiColumnHeaders = grep(this.columns, function(item) {
return item.columns !== undefined;
}).length > 0;
if (!filterable || this.options.columnMenu) {
return;
}
var filterInit = (function(e) {
this.trigger(FILTERMENUINIT, {
field: e.field,
container: e.container
});
}).bind(this);
var filterOpen = (function(e) {
this.trigger(FILTERMENUOPEN, {
field: e.field,
container: e.container
});
}).bind(this);
var filterHandler = this._filter.bind(this);
if (hasMultiColumnHeaders) {
if (this.lockedHeader) {
cells = leafDataCells(this.lockedHeader.find(">table>thead").add(this.thead));
} else {
cells = leafDataCells(this.thead);
}
} else {
cells = $(this.lockedHeader).add(this.thead).find("tr:not(.k-filter-row) th");
}
columns = leafColumns(this.columns);
if (filterable && typeof filterable.mode == STRING && filterable.mode.indexOf("menu") == -1) {
filterable = false;
}
if (!filterable) {
return;
}
for (idx = 0, length = cells.length; idx < length; idx++) {
column = columns[idx];
cell = cells.eq(idx);
filterMenuInstance = cell.data("kendoFilterMenu");
if (filterMenuInstance) {
filterMenuInstance.destroy();
}
if (column.draggable || column.command || column.filterable === false || column.selectable) {
continue;
}
cell.kendoFilterMenu(extend(true, {}, filterable, column.filterable, {
dataSource: this.dataSource,
init: filterInit,
open: filterOpen,
change: filterHandler,
appendTo: DOT + classNames.headerCellInner
}));
}
},
_filterRow: function() {
var that = this;
if (!that._hasFilterRow()) {
return;
}
var settings;
var uidAttr = kendo.attr("uid");
var columns = leafColumns(that.columns), filterable = that.options.filterable, filterHandler = this._filter.bind(this), existingInstance;
for (var i = 0; i < columns.length; i++) {
var suggestDataSource, col = columns[i], operators = that.options.filterable.operators, customDataSource = false, th = this.wrapper.find(".k-grid-header .k-filter-row th[" + uidAttr + "=\"" + col.headerAttributes.id + "\"]"), field = col.field, parentColumn = col.parentColumn;
delete col.parentColumn;
if (field && col.filterable !== false) {
var cellOptions = col.filterable && col.filterable.cell || {};
existingInstance = th.find(".k-filtercell").data("kendoFilterCell");
if (existingInstance) {
existingInstance.destroy();
th.empty();
}
suggestDataSource = that.options.dataSource;
if (suggestDataSource instanceof DataSource) {
suggestDataSource = that.options.dataSource.options;
}
var messages = extend(true, {}, filterable.messages);
if (col.filterable) {
extend(true, messages, col.filterable.messages);
}
if (cellOptions.enabled === false) {
th.html(" ");
continue;
}
if (cellOptions.dataSource) {
suggestDataSource = cellOptions.dataSource;
customDataSource = true;
}
if (col.filterable && col.filterable.operators) {
operators = col.filterable.operators;
}
settings = {
column: col,
dataSource: that.dataSource,
suggestDataSource,
customDataSource,
field,
messages,
values: col.values,
template: cellOptions.template,
delay: cellOptions.delay,
inputWidth: cellOptions.inputWidth,
suggestionOperator: cellOptions.suggestionOperator,
minLength: cellOptions.minLength,
dataTextField: cellOptions.dataTextField,
operator: cellOptions.operator,
operators,
showOperators: cellOptions.showOperators,
change: filterHandler
};
$("<span/>").attr(kendo.attr("field"), field).appendTo(th).kendoFilterCell(settings);
col.parentColumn = parentColumn;
} else {
th.html(" ");
}
}
this._filterFocusable().attr(TABINDEX, -1);
},
_hasFilterRow: function() {
var filterable = this.options.filterable;
var hasFiltering = filterable && typeof filterable.mode == STRING && filterable.mode.indexOf("row") != -1;
var columns = this.columns;
var columnsWithoutFiltering = $.grep(columns, function(col) {
return col.filterable === false;
});
if (columns.length && columnsWithoutFiltering.length == columns.length) {
hasFiltering = false;
}
return hasFiltering;
},
_change: function() {
var that = this;
var selectedValues;
if (that._checkBoxSelection) {
selectedValues = that.selectable.value();
that._uncheckCheckBoxes();
that._checkRows(selectedValues);
if (selectedValues.length && selectedValues.length === that.items().length) {
that._toggleHeaderCheckState(true);
} else {
that._toggleHeaderCheckState(false);
}
}
this.trigger(CHANGE);
},
_isLocked: function() {
return this.lockedHeader !== null;
},
_selectable: function() {
var that = this;
var selectable = this.options.selectable;
var filter;
var element = this.table;
var useAllItems;
var isLocked = that._isLocked();
var multi;
var cell;
if (selectable) {
selectable = kendo.ui.Selectable.parseOptions(selectable);
if (this._hasLockedColumns) {
element = element.add(this.lockedTable);
useAllItems = selectable.multiple && selectable.cell;
}
filter = ">tbody>tr:not(.k-footer-template)";
if (selectable.cell) {
filter = filter + ">td";
}
this.selectable = new kendo.ui.Selectable(element, {
filter,
aria: true,
multiple: selectable.multiple,
change: this._change.bind(this),
useAllItems,
continuousItems: this._continuousItems.bind(this, filter, selectable.cell),
relatedTarget: !selectable.cell && this._hasLockedColumns ? this._selectableTarget.bind(this) : undefined
});
if (that.options.navigatable) {
multi = selectable.multiple;
cell = selectable.cell;
element.on("keydown" + NS, function(e) {
var current = that.current();
if (!current) {
return;
}
var target = e.target;
if (e.keyCode === keys.SPACEBAR && !e.shiftKey && $.inArray(target, element) > -1 && !current.is(".k-header")) {
e.preventDefault();
e.stopPropagation();
current = cell ? current : current.parent();
if (isLocked && !cell) {
current = current.add(that._relatedRow(current));
}
if (multi) {
if (!e.ctrlKey) {
that.selectable.clear();
} else {
if (current.hasClass(classNames.selected)) {
current.removeClass(classNames.selected);
that.trigger(CHANGE);
return;
}
}
} else {
that.selectable.clear();
}
if (!cell) {
that.selectable._lastActive = current;
}
that.selectable.value(current);
that.trigger(CHANGE);
} else if (!cell && (e.shiftKey && e.keyCode == keys.LEFT || e.shiftKey && e.keyCode == keys.RIGHT || e.shiftKey && e.keyCode == keys.UP || e.shiftKey && e.keyCode == keys.DOWN || e.keyCode === keys.SPACEBAR && e.shiftKey)) {
e.preventDefault();
e.stopPropagation();
current = current.parent();
if (isLocked) {
current = current.add(that._relatedRow(current));
}
if (multi) {
if (!that.selectable._lastActive) {
that.selectable._lastActive = current;
}
that.selectable.selectRange(that.selectable._firstSelectee(), current);
} else {
that.selectable.clear();
that.selectable.value(current);
}
that.trigger(CHANGE);
}
});
}
}
},
_continuousItems: function(filter, cell) {
if (!this.lockedContent) {
return;
}
var lockedItems = $(filter, this.lockedTable);
var nonLockedItems = $(filter, this.table);
var columns = cell ? lockedColumns(this.columns).length : 1;
var nonLockedColumns = cell ? this.columns.length - columns : 1;
var result = [];
for (var idx = 0; idx < lockedItems.length; idx += columns) {
push.apply(result, lockedItems.slice(idx, idx + columns));
push.apply(result, nonLockedItems.splice(0, nonLockedColumns));
}
return result;
},
_selectableTarget: function(items) {
var related;
var result = $();
for (var idx = 0, length = items.length; idx < length; idx++) {
related = this._relatedRow(items[idx]);
if (inArray(related[0], items) < 0) {
result = result.add(related);
}
}
return result;
},
_relatedRow: function(row) {
var lockedTable = this.lockedTable;
row = $(row);
if (!lockedTable) {
return row;
}
var table = row.closest(this.table.add(this.lockedTable));
var index = table.find(">tbody>tr").index(row);
table = table[0] === this.table[0] ? lockedTable : this.table;
return table.find(">tbody>tr").eq(index);
},
select: function(value) {
var that = this;
var selectable = this.selectable;
if (that._checkBoxSelection) {
if (value) {
that._checkRows(value);
if (that.select().length === that.items().length) {
that._toggleHeaderCheckState(true);
}
}
return that.items().filter("." + SELECTED);
}
if (!selectable) {
return $();
}
if (typeof value !== "undefined") {
if (!selectable.options.multiple) {
selectable.clear();
value = value.first();
}
if (this._hasLockedColumns) {
value = value.add($.map(value, this._relatedRow.bind(this)));
}
}
return selectable.value(value);
},
clearSelection: function() {
var that = this;
if (that.selectable && !that._checkBoxSelection) {
that.selectable.clear();
}
if (that._checkBoxSelection) {
that._deselectCheckRows(that.select(), true);
return;
}
},
_uncheckCheckBoxes: function() {
var that = this;
var tables = that.table.add(that.lockedTable);
tables.find("tbody " + CHECKBOXINPUT).attr("aria-checked", false).prop("checked", false).attr("aria-label", "Select row");
},
_deselectCheckRows: function(items, preventChange) {
var that = this;
items = that.table.add(that.lockedTable).find(items);
if (that._isLocked()) {
items = items.add(items.map(function() {
return that._relatedRow(this);
}));
}
items.each(function() {
$(this).removeClass(SELECTED).find(CHECKBOXINPUT).attr("aria-checked", false).prop("checked", false).attr("aria-label", "Select row");
});
that._toggleHeaderCheckState(false);
if (!preventChange) {
that.trigger(CHANGE);
}
},
_headerCheckboxClick: function(e) {
var that = this, checkBox = $(e.target), checked = checkBox.prop("checked"), parentGrid = checkBox.closest(".k-grid").getKendoTreeList();
if (that !== parentGrid) {
return;
}
if (checked) {
that.select(parentGrid.items());
} else {
that.clearSelection();
}
that.trigger(CHANGE);
},
_checkboxClick: function(e) {
var that = this, row = $(e.target).closest("tr"), isSelecting = !row.hasClass(SELECTED), dataItem = that.dataItem(row), children = [], selector = "";
if (that !== row.closest(".k-grid").getKendoTreeList()) {
return;
}
if (that._includeChildren) {
that.dataSource.allChildNodes(dataItem, children);
for (var i = 0; i < children.length; i++) {
selector += "tr[data-uid='" + children[i].uid + "'],";
}
}
selector += "tr[data-uid='" + dataItem.uid + "']";
row = $(selector);
if (isSelecting) {
that.select(row);
that.trigger(CHANGE);
} else {
that._deselectCheckRows(row);
}
},
_checkRows: function(items) {
items.each(function() {
$(this).addClass(SELECTED).find(CHECKBOXINPUT).prop("checked", true).attr("aria-label", "Deselect row").attr("aria-checked", true);
});
},
_toggleHeaderCheckState: function(checked) {
var that = this;
if (checked) {
that.thead.add(that.lockedHeader).find("tr " + CHECKBOXINPUT).prop("checked", true).attr("aria-checked", true).attr("aria-label", "Deselect all rows");
} else {
that.thead.add(that.lockedHeader).find("tr " + CHECKBOXINPUT).prop("checked", false).attr("aria-checked", false).attr("aria-label", "Select all rows");
}
},
_dataSource: function(dataSource) {
var that = this;
var ds = this.dataSource;
var pageable = that.options.pageable;
if (ds) {
ds.unbind(CHANGE, this._refreshHandler);
ds.unbind(ERROR, this._errorHandler);
ds.unbind(SORT, this._sortHandler);
ds.unbind(PROGRESS, this._progressHandler);
}
this._refreshHandler = this.refresh.bind(this);
this._errorHandler = this._error.bind(this);
this._sortHandler = this._clearSortClasses.bind(this);
this._progressHandler = this._progress.bind(this);
if (isPlainObject(dataSource)) {
extend(dataSource, {
table: that.table,
fields: that.columns
});
if (isPlainObject(pageable) && pageable.pageSize !== undefined) {
dataSource.pageSize = pageable.pageSize;
}
}
ds = this.dataSource = TreeListDataSource.create(dataSource);
if (pageable) {
ds._collapsedTotal = undefined;
}
ds.bind(CHANGE, this._refreshHandler);
ds.bind(ERROR, this._errorHandler);
ds.bind(SORT, this._sortHandler);
ds.bind(PROGRESS, this._progressHandler);
this._dataSourceFetchProxy = (function() {
this.dataSource.fetch();
}).bind(this);
},
setDataSource: function(dataSource) {
this._dataSource(dataSource);
this._sortable();
this._filterable();
this._filterRow();
this._columnMenu();
this._pageable();
this._contentTree.render([]);
if (this.options.autoBind) {
this.dataSource.fetch();
}
},
dataItem: function(element) {
if (element instanceof TreeListModel) {
return element;
}
var row = $(element).closest("tr");
var uid = row.attr(kendo.attr("uid"));
var model = isUndefined(uid) ? null : this.dataSource.getByUid(uid);
return model;
},
editRow: function(row) {
var that = this;
var model;
if (this._isIncellEditable() || !this.options.editable) {
return;
}
if (typeof row === STRING) {
row = this.tbody.find(row);
}
if (that._isPageable() && that._isPopupEditable() && row instanceof TreeListModel) {
model = row;
} else {
model = this.dataItem(row);
}
if (!model) {
return;
}
if (that.editor) {
model._edit = true;
this._render();
this._cancelEditor();
} else {
that._preventPageSizeRestore = false;
}
if (this._editMode() != "popup") {
model._edit = true;
}
if (this.trigger(BEFORE_EDIT, { model })) {
that.dataSource._restorePageSizeAfterAddChild();
return;
}
this._render();
this._createEditor(model);
this.trigger(EDIT, {
container: this.editor.wrapper,
model
});
},
_cancelEdit: function(e) {
if (!this.editor) {
return;
}
var currentIndex;
e = extend(e, {
container: this.editor.wrapper,
model: this.editor.model
});
if (this.trigger(CANCEL, e)) {
return;
}
if (this.options.navigatable) {
currentIndex = this.items().index($(this.current()).parent());
}
this.cancelRow();
if (this.options.navigatable) {
this._setCurrent(this.items().eq(currentIndex).children().filter(NAVCELL).first());
focusTable(this.table, true);
}
},
cancelRow: function() {
if (this._isIncellEditable()) {
return;
}
this._cancelEditor();
this._render();
},
saveRow: function() {
var editor = this.editor;
var args;
if (this._isIncellEditable()) {
return;
}
if (!editor) {
return;
}
args = {
model: editor.model,
container: editor.wrapper
};
if (editor.end() && !this.trigger(SAVE, args)) {
this.dataSource.sync();
}
},
addRow: function(parent) {
var that = this;
var dataSource = that.dataSource;
var pageable = that._isPageable();
var incellEditing = that._isIncellEditable();
var inlineEditing = that._isInlineEditable();
var editor = this.editor;
var index = 0;
var model = {};
if (editor && !editor.end() || !this.options.editable) {
return;
}
if (parent) {
if (!(parent instanceof TreeListModel)) {
parent = this.dataItem(parent);
}
model[parent.parentIdField] = parent.id;
index = this.dataSource.indexOf(parent) + 1;
this.expand(parent).then(function() {
var showNewModelInView = pageable && dataSource._isLastItemInView(parent) && (incellEditing || inlineEditing);
that._insertAt(model, index, showNewModelInView);
});
return;
}
this._insertAt(model, index);
},
_insertAt: function(model, index, showNewModelInView) {
var that = this;
var dataSource = that.dataSource;
model = that.dataSource.insert(index, model);
if (showNewModelInView) {
dataSource._setAddChildPageSize();
}
var row = this._itemFor(model);
var cell;
if (that._isIncellEditable()) {
cell = row.children("td").eq(that._firstEditableColumnIndex(row));
that.editCell(cell);
} else if (row && row[0]) {
that.editRow(row);
} else if ((that._isPageable() || that.dataSource.filter()) && (that._isPopupEditable() || that._isInlineEditable())) {
that.editRow(model);
}
},
_firstEditableColumnIndex: function(container) {
var that = this;
var model = that.dataItem(container);
var columns = leafColumns(that.columns);
var length = columns.length;
var column;
var idx;
for (idx = 0; idx < length; idx++) {
column = columns[idx];
if (model && (!model.editable || model.editable(column.field)) && !column.command && !column.draggable && column.field && column.hidden !== true) {
return idx;
}
}
return -1;
},
removeRow: function(row) {
var model = this.dataItem(row);
var args = {
model,
row
};
if (this.options.editable && model && !this.trigger(REMOVE, args)) {
if (document.activeElement === $(row).find(".k-grid-delete")[0]) {
$(row).find(".k-grid-delete").trigger("blur");
}
this.dataSource.remove(model);
if (!this._isIncellEditable()) {
this.dataSource.sync();
}
}
},
_cancelEditor: function() {
var that = this;
var model;
var editor = that.editor;
if (editor) {
model = editor.model;
that._destroyEditor();
if (!that._isIncellEditable()) {
that.dataSource.cancelChanges(model);
} else if (that._shouldRestorePageSize()) {
that.dataSource._restorePageSizeAfterAddChild();
}
model._edit = false;
}
that._preventPageSizeRestore = false;
},
_shouldRestorePageSize: function() {
var that = this;
return that._isPageable() && that._isIncellEditable() && !that._preventPageSizeRestore;
},
_destroyEditor: function() {
if (!this.editor) {
return;
}
this.editor.close();
this.editor = null;
},
_createEditor: function(model) {
let row = this.itemFor(model);
let columns = leafColumns(this.columns);
let leafCols = [];
let that = this;
for (var idx = 0; idx < columns.length; idx++) {
leafCols.push(extend({}, columns[idx]));
delete leafCols[idx].parentColumn;
}
row = row.add(this._relatedRow(row));
let mode = this._editMode();
let options = {
columns: leafCols,
model,
target: this,
clearContainer: false,
template: this.options.editable.template
};
if (mode == "inline") {
this.editor = new Editor(row, options);
} else {
let windowOptions = extend({}, that.options.editable.window, { _footerTemplate: () => `<div class="k-actions k-actions-start k-actions-horizontal k-window-actions">` + that._buildCommands(["update"], true)[0].html + that._buildCommands(["canceledit"], true)[0].html + `</div>` });
extend(options, {
window: windowOptions,
fieldRenderer: this._cellContent.bind(this),
skipFocus: true,
save: this.saveRow.bind(this),
cancel: this._cancelEdit.bind(this),
appendTo: this.wrapper
});
this.editor = new PopupEditor(row, options);
}
},
_createIncellEditor: function(cell, options) {
var that = this;
var column = extend({}, options.columns[0]);
delete column.parentColumn;
return new IncellEditor(cell, extend({}, {
fieldRenderer: that._cellContent.bind(that),
appendTo: that.wrapper,
clearContainer: false,
target: that,
columns: [column],
model: options.model,
change: options.change
}));
},
editCell: function(cell) {
var that = this;
cell = $(cell);
var column = leafColumns(that.columns)[that.cellIndex(cell)];
var model = that.dataItem(cell);
if (that._isIncellEditable() && model && isColumnEditable(column, model)) {
that._editCell(cell, column, model, cell.index());
}
},
_editCell: function(cell, column, model, cellIndex) {
var that = this;
var editedCell;
if (that.trigger(BEFORE_EDIT, { model })) {
that.dataSource._restorePageSizeAfterAddChild();
return;
}
that.closeCell();
model._edit = true;
that._cancelEditor();
that._render({
editedColumn: column,
editedColumnIndex: cellIndex
});
editedCell = that.table.add(that.lockedTable).find(DOT + classNames.editCell).first();
that.editor = that._createIncellEditor(editedCell, {
columns: [column],
model,
change: function(e) {
if (that.trigger(SAVE, {
values: e.values,
container: cell,
model
})) {
e.preventDefault();
}
}
});
if (that.lockedTable) {
that._syncLockedContentHeight();
}
that.current() && that.current().removeClass("k-focus");
that._current = editedCell;
that.trigger(EDIT, {
container: cell,
model
});
},
closeCell: function(isCancel) {
var that = this;
var cell = (that.editor || {}).element;
var tr;
var model;
if (!cell || !cell[0] || !that._isIncellEditable()) {
return;
}
model = that.dataItem(cell);
if (isCancel && that.trigger(CANCEL, {
container: cell,
model
})) {
return;
}
that.trigger(CELL_CLOSE, {
type: isCancel ? CANCEL : SAVE,
model,
container: cell
});
that._cancelEditor();
cell.removeClass(classNames.editCell);
tr = cell.parent().removeClass(classNames.editRow);
if (that.lockedContent) {
that._relatedRow(tr).removeClass(classNames.editRow);
}
that._render();
that.trigger(ITEM_CHANGE, {
item: tr,
data: model,
ns: ui
});
if (that.lockedContent) {
adjustRowHeight(tr.css("height", "")[0], that._relatedRow(tr).css("height", "")[0]);
}
},
cancelChanges: function() {
this.dataSource.cancelChanges();
},
saveChanges: function() {
var that = this;
var editable = (that.editor || {}).editable;
var valid = editable && editable.end();
if ((valid || !editable) && !that.trigger(SAVE_CHANGES)) {
that.dataSource.sync();
}
},
_editMode: function() {
var mode = "inline", editable = this.options.editable;
if (editable !== true) {
if (typeof editable == "string") {
mode = editable;
} else {
mode = editable.mode || mode;
}
}
return mode.toLowerCase();
},
_isIncellEditable: function() {
return this._editMode() === INCELL;
},
_isInlineEditable: function() {
return this._editMode() === INLINE;
},
_isPopupEditable: function() {
return this._editMode() === POPUP;
},
hideColumn: function(column) {
this._toggleColumnVisibility(column, true);
},
showColumn: function(column) {
this._toggleColumnVisibility(column, false);
},
_toggleColumnVisibility: function(column, hidden) {
column = this._findColumn(column);
if (!column || column.hidden === hidden) {
return;
}
column.hidden = hidden;
this._setParentsVisibility(column, !hidden);
this._ensureExpandableColumn();
this._clearColsCache();
this._renderCols();
this._renderHeader();
this._render();
this._adjustTablesWidth();
if (hidden) {
this._ariaAddHiddenColIndex();
} else {
this._ariaRemoveHiddenColIndex();
}
this.trigger(hidden ? COLUMNHIDE : COLUMNSHOW, { column });
if (!hidden && !column.width) {
this.table.add(this.thead.closest("table")).width("");
}
this._updateFirstColumnClass();
},
_findColumn: function(column) {
if (typeof column == "number") {
column = this.columns[column];
} else if (isPlainObject(column)) {
column = grep(leafColumns(this.columns), function(item) {
return item === column;
})[0];
} else {
column = grep(leafColumns(this.columns), function(item) {
return item.field === column;
})[0];
}
return column;
},
_adjustTablesWidth: function() {
var idx, length;
var cols = this.thead.prev().children();
var colWidth, width = 0;
for (idx = 0, length = cols.length; idx < length; idx++) {
colWidth = cols[idx].style.width;
if (colWidth && colWidth.indexOf("%") == -1) {
width += parseInt(colWidth, 10);
} else {
width = 0;
break;
}
}
if (width) {
this.table.add(this.thead.closest("table")).width(width);
}
},
_reorderable: function() {
if (!this.options.reorderable) {
return;
}
var scrollable = this.options.scrollable === true;
var selector = (scrollable ? ".k-grid-header " : "table>.k-grid-header ") + HEADERCELLS;
var that = this;
this._draggableInstance = new ui.Draggable(this.wrapper, {
group: kendo.guid(),
filter: selector,
ignore: ".k-filter-row *",
hint: function(target) {
return $("<div class=\"k-reorder-clue k-drag-clue\" />").html(target.attr(kendo.attr("title")) || target.attr(kendo.attr("field")) || target.text()).prepend(kendo.ui.icon({
icon: "cancel",
iconClass: "k-drag-status"
}));
}
});
this.reorderable = new ui.Reorderable(this.wrapper, {
draggable: this._draggableInstance,
dragOverContainers: this._allowDragOverContainers.bind(this),
inSameContainer: function(e) {
return $(e.source).parent()[0] === $(e.target).parent()[0] && targetParentContainerIndex(flatColumnsInDomOrder(that.columns), that.columns, e.sourceIndex, e.targetIndex) > -1;
},
change: function(e) {
var columns = flatColumnsInDomOrder(that.columns);
var column = columns[e.oldIndex];
var newIndex = targetParentContainerIndex(columns, that.columns, e.oldIndex, e.newIndex);
that.trigger(COLUMNREORDER, {
newIndex,
oldIndex: inArray(column, columns),
column
});
that.reorderColumn(newIndex, column, e.position === "before");
}
});
},
_allowDragOverContainers: function(sourceIndex, targetIndex) {
var columns = flatColumnsInDomOrder(this.columns);
return columns[sourceIndex].lockable !== false && targetParentContainerIndex(columns, this.columns, sourceIndex, targetIndex) > -1;
},
_reorderTrees: function(destSources, destContainer, destDomTree, sources, sourcesContainer, sourcesDomTree, before, depth) {
var ths = $();
var source = sourcesContainer.find("tr").eq(sources[0].rowIndex);
var sourceDOM = sourcesDomTree.children[sources[0].rowIndex];
var sourceChildren = source.children();
var destDomChildren;
var currentIndex;
var destColumn = before ? destSources[0] : destSources[destSources.length - 1];
var destRow;
var sourcesLeafs;
var destLeafs;
var reorderTaget;
var destThs;
for (var idx = 0; idx < sources.length; idx++) {
currentIndex = sources[idx].cellIndex;
ths = ths.add(sourceChildren.eq(currentIndex));
destDomChildren = destDomTree.children[destColumn.rowIndex].children;
if (destDomTree === sourcesDomTree && before) {
currentIndex += idx;
}
destDomChildren.splice(before ? destColumn.cellIndex + idx : destColumn.cellIndex + 1 + idx, 0, sourceDOM.children[currentIndex]);
}
if (destDomTree === sourcesDomTree && before) {
sourceDOM.children.splice(sources[0].cellIndex + sources.length, sources.length);
} else {
sourceDOM.children.splice(sources[0].cellIndex, sources.length);
}
destRow = destContainer.find("tr").eq(destColumn.rowIndex);
destThs = destRow.find(">th.k-header").eq(destColumn.cellIndex);
if (destThs.length && ths[0] !== destThs[0]) {
ths[before ? "insertBefore" : "insertAfter"](destThs);
}
if (depth >= sources[0].rowIndex + 1 && depth != 1) {
sourcesLeafs = [];
for (idx = 0; idx < sources.length; idx++) {
if (sources[idx].columns) {
sourcesLeafs = sourcesLeafs.concat(sources[idx].columns);
}
}
if (!sourcesLeafs.length) {
return;
}
destLeafs = [];
for (idx = 0; idx < destSources.length; idx++) {
if (destSources[idx].columns) {
destLeafs = destLeafs.concat(destSources[idx].columns);
}
}
if (!destLeafs.length && (destContainer !== sourcesContainer || destColumn.cellIndex - sources[0].cellIndex > 1 || sources[0].cellIndex - destColumn.cellIndex > 1)) {
reorderTaget = findReorderTarget(this.columns, destColumn, sources[0], before, this.columns);
destLeafs = [reorderTaget];
if (!reorderTaget && sourcesLeafs.length && destContainer.find("tr").length > sources[0].rowIndex + 1) {
this._insertTree(sourcesLeafs, sourcesContainer, sourcesDomTree, destContainer, destDomTree);
return;
}
}
if (!destLeafs.length) {
return;
}
this._reorderTrees(destLeafs, destContainer, destDomTree, sourcesLeafs, sourcesContainer, sourcesDomTree, before, depth);
}
},
_insertTree: function(columns, sourcesContainer, sourcesDomTree, destContainer, destDomTree) {
var leafs = [];
var row;
var ths = $();
var domTr;
row = sourcesContainer.find("tr").eq(columns[0].rowIndex);
domTr = sourcesDomTree.children[columns[0].rowIndex];
for (var idx = 0; idx < columns.length; idx++) {
if (columns[idx].columns) {
leafs = leafs.concat(columns[idx].columns);
}
destDomTree.children[columns[0].rowIndex].children.splice(idx, 0, domTr.children[columns[idx].rowIndex]);
ths = ths.add(row.find(">th.k-header").eq(columns[idx].cellIndex));
}
sourcesDomTree.children[columns[0].rowIndex].children.splice(columns[0].cellIndex, columns.length);
destContainer.find("tr").eq(columns[0].rowIndex).append(ths);
if (leafs.length) {
this._insertTree(leafs, sourcesContainer, sourcesDomTree, destContainer, destDomTree);
}
},
_reorderHeader: function(destColumn, column, before) {
var sourcesDepth = column.columns ? depth([column]) : 1;
var targetDepth = destColumn.columns ? depth([destColumn]) : 1;
var sourceLocked = isLocked(column);
var destLocked = isLocked(destColumn);
var destContainer = destLocked ? this.lockedHeader : this.thead;
var sourcesContainer = sourceLocked ? this.lockedHeader : this.thead;
var destDomTree = destLocked ? this._lockedHeaderTree : this._headerTree;
var sourcesDomTree = sourceLocked ? this._lockedHeaderTree : this._headerTree;
var rowsToAdd;
var destRows = destContainer.find("tr:not(.k-filter-row)");
var destTarget;
if (sourcesDepth === targetDepth || sourcesDepth < destRows.length) {
this._reorderTrees([destColumn], destContainer, destDomTree, [column], sourcesContainer, sourcesDomTree, before, sourcesDepth);
updateRowSpans(destContainer, destDomTree);
removeEmptyRows(sourcesContainer, sourcesDomTree);
} else {
if (destContainer !== sourcesContainer) {
rowsToAdd = sourcesDepth - destRows.length;
destRows.each(function(idx) {
var cells = this.cells;
for (var i = 0; i < cells.length; i++) {
if (cells[i].colSpan <= 1 && cells[i].attributes.rowspan) {
destDomTree.children[idx].children[i].attr.rowSpan += rowsToAdd;
cells[i].rowSpan += rowsToAdd;
}
}
});
for (var j = 0; j < rowsToAdd; j++) {
destDomTree.children.push(kendoDomElement("tr", { "role": "row" }));
if (destContainer.is("thead")) {
destTarget = destContainer;
} else {
destTarget = destContainer.find("thead");
}
if (this._hasFilterRow()) {
$("<tr class='k-table-row' role='row'></tr>").insertBefore(destTarget.find("tr.k-filter-row"));
} else {
destTarget.append("<tr class='k-table-row' role='row'></tr>");
}
}
}
this._reorderTrees([destColumn], destContainer, destDomTree, [column], sourcesContainer, sourcesDomTree, before, sourcesDepth);
removeEmptyRows(sourcesContainer, sourcesDomTree);
}
},
reorderColumn: function(destIndex, column, before) {
var lockChanged;
var parent = column.parentColumn;
var columns = parent ? parent.columns : this.columns;
var sourceIndex = inArray(column, columns);
var destColumn = columns[destIndex];
var isLocked = !!destColumn.locked;
var hasMultiColumnHeaders = grep(this.columns, function(item) {
return item.columns !== undefined;
}).length > 0;
var nonLockedColumnsLength = nonLockedColumns(columns).length;
if (sourceIndex === destIndex) {
return;
}
if (isLocked && !column.locked && nonLockedColumnsLength == 1) {
return;
}
if (!isLocked && column.locked && columns.length - nonLockedColumnsLength == 1) {
return;
}
if (before === undefined) {
before = destIndex < sourceIndex;
}
if (hasMultiColumnHeaders) {
this._reorderHeader(destColumn, column, before);
}
lockChanged = !!column.locked;
lockChanged = lockChanged != isLocked;
column.locked = isLocked;
columns.splice(before ? destIndex : destIndex + 1, 0, column);
columns.splice(sourceIndex < destIndex ? sourceIndex : sourceIndex + 1, 1);
this._setColumnDataIndexes(leafColumns(this.columns));
this._clearColsCache();
this._renderCols();
if (!hasMultiColumnHeaders) {
var ths = $(this.lockedHeader).add(this.thead).find("tr:not(.k-filter-row) th");
ths.eq(sourceIndex)[before ? "insertBefore" : "insertAfter"](ths.eq(destIndex));
var dom = this._headerTree.children[0].children;
if (this._hasLockedColumns) {
dom = this._lockedHeaderTree.children[0].children.concat(dom);
}
dom.splice(before ? destIndex : destIndex + 1, 0, dom[sourceIndex]);
dom.splice(sourceIndex < destIndex ? sourceIndex : sourceIndex + 1, 1);
if (this._hasLockedColumns) {
this._lockedHeaderTree.children[0].children = dom.splice(0, lockedColumns(columns).length);
this._headerTree.children[0].children = dom;
}
} else {
if (this.lockedHeader) {
columns = nonLockedColumns(this.columns);
this._prepareColumns([{
rowSpan: 1,
cells: [],
index: 0
}], columns);
columns = lockedColumns(this.columns);
this._prepareColumns([{
rowSpan: 1,
cells: [],
index: 0
}], columns);
} else {
this._prepareColumns([{
rowSpan: 1,
cells: [],
index: 0
}], this.columns);
}
}
this._updateColumnCellIndex();
this._applyLockedContainersWidth();
this._syncLockedHeaderHeight();
this._updateFirstColumnClass();
if (this._hasFilterRow()) {
this._updateFilterThs(before, column, destColumn);
}
this.refresh();
if (!lockChanged) {
return;
}
if (isLocked) {
this.trigger(COLUMNLOCK, { column });
} else {
this.trigger(COLUMNUNLOCK, { column });
}
},
lockColumn: function(column) {
var columns = this.columns;
if (typeof column == "number") {
column = columns[column];
} else {
column = grep(columns, function(item) {
return item.field === column;
})[0];
}
if (!column || column.hidden) {
return;
}
var index = lockedColumns(columns).length - 1;
this.reorderColumn(index, column, false);
},
unlockColumn: function(column) {
var columns = this.columns;
if (typeof column == "number") {
column = columns[column];
} else {
column = grep(columns, function(item) {
return item.field === column;
})[0];
}
if (!column || column.hidden) {
return;
}
var index = lockedColumns(columns).length;
this.reorderColumn(index, column, true);
},
_columnMenu: function() {
var ths = $(this.lockedHeader).add(this.thead).find("th");
var columns = this.columns;
var options = this.options;
var columnMenu = options.columnMenu;
var column, menu, menuOptions, sortable, filterable;
var initHandler = this._columnMenuInit.bind(this);
var openHandler = this._columnMenuOpen.bind(this);
var sortHandler = this._sort.bind(this);
var filterHandler = this._filter.bind(this);
var hasLockableColumns = grep(this.columns, function(item) {
return item.lockable !== false;
}).length > 0;
var hasMultiColumnHeaders = grep(this.columns, function(item) {
return item.columns !== undefined;
}).length > 0;
if (hasMultiColumnHeaders) {
columns = leafColumns(columns);
if (this.lockedHeader) {
ths = sortCells(leafDataCells(this.lockedHeader.find(">table>thead")).add(leafDataCells(this.thead)));
} else {
ths = leafDataCells(this.thead);
}
} else {
ths = $(this.lockedHeader).add(this.thead).find("tr:not(.k-filter-row) th");
}
if (!columnMenu) {
return;
}
if (typeof columnMenu == "boolean") {
columnMenu = {};
}
for (var i = 0; i < ths.length; i++) {
column = columns[i];
if (!column.field) {
continue;
}
menu = ths.eq(i).data("kendoColumnMenu");
if (menu) {
menu.destroy();
}
sortable = false;
if (column.sortable !== false && columnMenu.sortable !== false && options.sortable !== false) {
sortable = extend({}, options.sortable, { compare: (column.sortable || {}).compare });
}
filterable = false;
if (options.filterable && column.filterable !== false && columnMenu.filterable !== false) {
filterable = extend({ pane: this.pane }, column.filterable, options.filterable);
}
menuOptions = {
dataSource: this.dataSource,
values: column.values,
columns: columnMenu.columns,
sortable,
filterable,
messages: columnMenu.messages,
owner: this,
closeCallback,
init: initHandler,
open: openHandler,
sort: sortHandler,
filtering: filterHandler,
pane: this.pane,
hasLockableColumns: lockedColumns(columns).length > 0 && hasLockableColumns && !hasMultiColumnHeaders,
appendTo: DOT + classNames.headerCellInner,
reorderable: !!options.reorderable
};
ths.eq(i).kendoColumnMenu(menuOptions);
}
},
_columnMenuInit: function(e) {
this.trigger(COLUMNMENUINIT, {
field: e.field,
container: e.container
});
},
_columnMenuOpen: function(e) {
this.trigger(COLUMNMENUOPEN, {
field: e.field,
container: e.container
});
},
_filter: function(e) {
if (this.trigger(FILTER, {
filter: e.filter,
field: e.field
})) {
e.preventDefault();
}
},
_sort: function(e) {
if (this.trigger(SORT, { sort: e.sort })) {
e.preventDefault();
}
},
_pageable: function() {
var that = this, wrapper, pageable = that.options.pageable;
if (pageable) {
wrapper = that.wrapper.children("div.k-grid-pager");
if (!wrapper.length) {
wrapper = $("<div class=\"k-pager k-grid-pager\"/>").appendTo(that.wrapper);
}
that._destroyPager();
if (typeof pageable === "object" && pageable instanceof kendo.ui.TreeListPager) {
that.pager = pageable;
} else if (that.dataSource && !that.dataSource.options.serverPaging) {
that._createPager(wrapper);
}
if (that.pager) {
that.pager.bind(PAGE_CHANGE, function(e) {
if (that.trigger(PAGE, { page: e.index })) {
e.preventDefault();
}
});
}
}
},
_createPager: function(element, options) {
var that = this;
that.pager = new TreeListPager(element, extend({}, that.options.pageable, {
dataSource: that.dataSource,
navigatable: that.options.navigatable
}, options));
},
_destroyPager: function() {
if (this.pager) {
this.pager.destroy();
this.pager = null;
}
},
_isPageable: function() {
var that = this;
return that.options.pageable && (!that.dataSource || that.dataSource && that.dataSource._isPageable());
},
_togglePagerVisibility: function() {
var that = this;
var pageable = that.options.pageable;
if (pageable && (isPlainObject(pageable) || pageable instanceof TreeListPager) && pageable.alwaysVisible === false) {
that.wrapper.find(".k-grid-pager").toggle((that.dataSource.collapsedTotal() || 0) >= that.dataSource.pageSize());
}
}
});
function closeCallback(element) {
focusTable(element.closest(".k-treelist").find("[role=treegrid]"), true);
}
function isInputElement(element) {
return $(element).is(":button,a,:input,a>.k-icon,a>.k-svg-icon,textarea,span.k-select,span.k-icon:not(.k-treelist-toggle),span.k-svg-icon:not(.k-treelist-toggle),span.k-link,.k-input,.k-multiselect-wrap,.k-tool-icon,.k-input-value-text,.k-input-inner,.k-button-icon,.k-switch-thumb,.k-switch-track,.k-switch-label-off,.k-switch-label-on");
}
function isLocked(column) {
if (!column.parentColumn) {
return !!column.locked;
}
return !!isLocked(column.parentColumn);
}
function findParentColumnWithChildren(columns, index, source, rtl) {
var target;
var locked = !!source.locked;
var targetLocked;
do {
target = columns[index];
index += rtl ? 1 : -1;
targetLocked = !!target.locked;
} while (target && index > -1 && index < columns.length && target != source && !target.columns && targetLocked === locked);
return target;
}
function findReorderTarget(columns, target, source, before, masterColumns) {
if (target.columns) {
target = target.columns;
return target[before ? 0 : target.length - 1];
} else {
var parent = columnParent(target, columns);
var parentColumns;
if (parent) {
parentColumns = parent.columns;
} else {
parentColumns = columns;
}
var index = inArray(target, parentColumns);
if (index === 0 && before && parentColumns.length !== 1) {
index++;
} else if (index == parentColumns.length - 1 && !before && index !== 0) {
index--;
} else if (index > 0 || index === 0 && !before && index !== 0) {
index += before ? -1 : 1;
}
var sourceIndex = inArray(source, parentColumns);
target = findParentColumnWithChildren(parentColumns, index, source, sourceIndex > index);
var targetIndex = inArray(target, masterColumns);
if (target.columns && (!targetIndex || targetIndex === parentColumns.length - 1)) {
return null;
}
if (target && target != source && target.columns) {
return findReorderTarget(columns, target, source, before, masterColumns);
}
}
return null;
}
function leafColumns(columns) {
var result = [];
for (var idx = 0; idx < columns.length; idx++) {
if (!columns[idx].columns) {
result.push(columns[idx]);
continue;
}
result = result.concat(leafColumns(columns[idx].columns));
}
return result;
}
function getColumnsFields(columns) {
var result = [];
columns = leafColumns(columns);
for (var idx = 0; idx < columns.length; idx++) {
if (typeof columns[idx] === "string") {
result.push(columns[idx]);
} else if (columns[idx].field) {
result.push(columns[idx].field);
}
}
return result;
}
function visibleChildColumns(columns) {
return grep(columns, function(column) {
return !column.hidden;
});
}
function isVisible(column) {
return visibleColumns([column]).length > 0;
}
function visibleColumns(columns) {
return grep(columns, function(column) {
var result = !column.hidden;
if (result && column.columns) {
result = visibleColumns(column.columns).length > 0;
}
return result;
});
}
function normalizeColumns(columns, hide, parentIds) {
return map(columns, function(column) {
var hidden;
column.parentIds = parentIds;
if (!isVisible(column) || hide) {
hidden = true;
}
var uid = kendo.guid();
column.headerAttributes = extend({ headers: parentIds }, column.headerAttributes);
if (!column.headerAttributes || !column.headerAttributes.id) {
column.headerAttributes = extend({ id: uid }, column.headerAttributes);
} else {
uid = column.headerAttributes.id;
}
if (column.columns) {
column.columns = normalizeColumns(column.columns, hidden, parentIds ? parentIds + " " + uid : uid);
}
return extend({ hidden }, column);
});
}
function flatColumnsInDomOrder(columns) {
var result = flatColumns(lockedColumns(columns));
return result.concat(flatColumns(nonLockedColumns(columns)));
}
function targetParentContainerIndex(flatColumns, columns, sourceIndex, targetIndex) {
var column = flatColumns[sourceIndex];
var target = flatColumns[targetIndex];
var parent = columnParent(column, columns);
columns = parent ? parent.columns : columns;
return inArray(target, columns);
}
function parentColumnsCells(cell) {
var container = cell.closest("table");
var result = $().add(cell);
var row = cell.closest("tr");
var headerRows = container.find("tr");
var level = headerRows.index(row);
if (level > 0) {
var parent = headerRows.eq(level - 1);
var parentCellsWithChildren = parent.find("th").filter(function() {
return !$(this).attr("rowspan");
});
var offset = 0;
var index = row.find("th").index(cell);
var prevCells = cell.prevAll().filter(function() {
return this.colSpan > 1;
});
for (var idx = 0; idx < prevCells.length; idx++) {
offset += prevCells[idx].colSpan || 1;
}
index += Math.max(offset - 1, 0);
offset = 0;
for (idx = 0; idx < parentCellsWithChildren.length; idx++) {
var parentCell = parentCellsWithChildren.eq(idx);
if (parentCell.attr("data-colspan")) {
offset += parentCell[0].getAttribute("data-colspan");
} else {
offset += 1;
}
if (index >= idx && index < offset) {
result = parentColumnsCells(parentCell).add(result);
break;
}
}
}
return result;
}
function childColumnsCells(cell) {
var container = cell.closest("thead");
var result = $().add(cell);
var row = cell.closest("tr");
var headerRows = container.find("tr");
var level = headerRows.index(row) + cell[0].rowSpan;
var colSpanAttr = kendo.attr("colspan");
if (level <= headerRows.length - 1) {
var child = row.next();
var prevCells = cell.prevAll();
var idx;
prevCells = prevCells.filter(function() {
return !this.rowSpan || this.rowSpan === 1;
});
var offset = 0;
for (idx = 0; idx < prevCells.length; idx++) {
offset += parseInt(prevCells.eq(idx).attr(colSpanAttr), 10) || 1;
}
var cells = child.find("th");
var colSpan = parseInt(cell.attr(colSpanAttr), 10) || 1;
idx = 0;
while (idx < colSpan) {
child = cells.eq(idx + offset);
result = result.add(childColumnsCells(child));
var value = parseInt(child.attr(colSpanAttr), 10);
if (value > 1) {
colSpan -= value - 1;
}
idx++;
}
}
return result;
}
function columnParent(column, columns) {
var parents = [];
columnParents(column, columns, parents);
return parents[parents.length - 1];
}
function columnParents(column, columns, parents) {
parents = parents || [];
for (var idx = 0; idx < columns.length; idx++) {
if (column === columns[idx]) {
return true;
} else if (columns[idx].columns) {
var inserted = parents.length;
parents.push(columns[idx]);
if (!columnParents(column, columns[idx].columns, parents)) {
parents.splice(inserted, parents.length - inserted);
} else {
return true;
}
}
}
return false;
}
function flatColumns(columns) {
var result = [];
var children = [];
for (var idx = 0; idx < columns.length; idx++) {
result.push(columns[idx]);
if (columns[idx].columns) {
children = children.concat(columns[idx].columns);
}
}
if (children.length) {
result = result.concat(flatColumns(children));
}
return result;
}
function columnPosition(column, columns, row, cellCounts) {
var result;
var idx;
row = row || 0;
cellCounts = cellCounts || {};
cellCounts[row] = cellCounts[row] || 0;
for (idx = 0; idx < columns.length; idx++) {
if (columns[idx] == column) {
result = {
cell: cellCounts[row],
row
};
break;
} else if (columns[idx].columns) {
result = columnPosition(column, columns[idx].columns, row + 1, cellCounts);
if (result) {
break;
}
}
cellCounts[row]++;
}
return result;
}
function updateCellIndex(thead, columns, offset) {
offset = offset || 0;
var position;
var cell;
var allColumns = columns;
columns = leafColumns(columns);
var cells = {};
var rows = thead.find(">tr:not(.k-filter-row)");
var filter = function() {
var el = $(this);
return !el.hasClass("k-group-cell") && !el.hasClass("k-hierarchy-cell");
};
for (var idx = 0, length = columns.length; idx < length; idx++) {
position = columnPosition(columns[idx], allColumns);
if (!cells[position.row]) {
cells[position.row] = rows.eq(position.row).find(".k-header").filter(filter);
}
cell = cells[position.row].eq(position.cell);
cell.attr(kendo.attr("index"), offset + idx);
}
return columns.length;
}
function depth(columns) {
var result = 1;
var max = 0;
for (var idx = 0; idx < columns.length; idx++) {
if (columns[idx].columns) {
var temp = depth(columns[idx].columns);
if (temp > max) {
max = temp;
}
}
}
return result + max;
}
function lockedColumns(columns) {
return grep(columns, is("locked"));
}
function nonLockedColumns(columns) {
return grep(columns, not(is("locked")));
}
function updateRowSpans(container, containerDOMtree) {
var rows = container.find("tr:not(.k-filter-row)");
var length = rows.length;
rows.each(function(idx) {
var cells = this.cells;
for (var i = 0; i < cells.length; i++) {
if (cells[i].colSpan <= 1 && cells[i].attributes.rowspan) {
containerDOMtree.children[idx].children[i].attr.rowSpan = length - idx;
cells[i].rowSpan = length - idx;
}
}
});
}
function removeEmptyRows(container, containerDOMtree) {
var rows = container.find("tr");
var emptyRows = [];
rows.filter(function(idx) {
var shouldRemove = !$(this).children().length;
if (shouldRemove) {
emptyRows.push(idx);
}
return shouldRemove;
}).remove();
for (var i = emptyRows.length - 1; i >= 0; i--) {
containerDOMtree.children.splice(emptyRows[i], 1);
}
updateRowSpans(container, containerDOMtree);
}
function focusTable(table, direct) {
if (direct === true) {
table = $(table);
var scrollTop, scrollLeft;
scrollTop = table.parent().scrollTop();
scrollLeft = kendo.scrollLeft(table.parent());
kendo.focusElement(table);
kendo.scrollLeft(table.parent().scrollTop(scrollTop), scrollLeft);
} else {
$(table).one("focusin", function(e) {
e.preventDefault();
}).trigger("focus");
}
}
function adjustRowHeight(row1, row2) {
var height;
var offsetHeight1 = row1.offsetHeight;
var offsetHeight2 = row2.offsetHeight;
if (offsetHeight1 > offsetHeight2) {
height = offsetHeight1 + "px";
} else if (offsetHeight1 < offsetHeight2) {
height = offsetHeight2 + "px";
}
if (height) {
row1.style.height = row2.style.height = height;
}
}
function isColumnEditable(column, model) {
if (!column || !model || !column.field || column.selectable || column.command || column.draggable || column.editable && !column.editable(model)) {
return false;
}
return column.field && model.editable && model.editable(column.field);
}
function capitalize(word) {
return word.charAt(0).toUpperCase() + word.slice(1);
}
function isDirtyColumn(column, model) {
var field = (column || {}).field || "";
return model.dirty && model.dirtyFields && model.dirtyFields[field] && isColumnEditable(column, model);
}
function isUndefined(value) {
return typeof value === "undefined";
}
function isNumber(value) {
return typeof value === "number" && !isNaN(value);
}
if (kendo.ExcelMixin) {
kendo.ExcelMixin.extend(TreeList.prototype);
}
if (kendo.PDFMixin) {
kendo.PDFMixin.extend(TreeList.prototype);
TreeList.prototype._drawPDF = function(progress) {
var treeList = this;
if (treeList.options.pdf.paperSize && treeList.options.pdf.paperSize != "auto") {
return treeList._drawPDF_autoPageBreak(progress);
}
var result = new $.Deferred();
var dataSource = treeList.dataSource;
var allPages = treeList.options.pdf.allPages;
this._initPDFProgress(progress);
var doc = new kendo.drawing.Group();
var startingPage = dataSource.page();
function resolve() {
if (allPages && startingPage !== undefined) {
dataSource.unbind("change", exportPage);
dataSource.one("change", function() {
result.resolve(doc);
});
dataSource.page(startingPage);
} else {
result.resolve(doc);
}
}
function exportPage() {
treeList._drawPDFShadow({ width: treeList.wrapper.width() }, { avoidLinks: treeList.options.pdf.avoidLinks }).done(function(group) {
var pageNum = dataSource.page();
var totalPages = allPages ? dataSource.totalPages() : 1;
var args = {
page: group,
pageNumber: pageNum,
progress: pageNum / totalPages,
totalPages
};
progress.notify(args);
doc.append(args.page);
if (pageNum < totalPages) {
dataSource.page(pageNum + 1);
} else {
resolve();
}
}).fail(function(err) {
result.reject(err);
});
}
if (allPages) {
dataSource.bind("change", exportPage);
dataSource.page(1);
} else {
exportPage();
}
return result.promise();
};
TreeList.prototype._initPDFProgress = function(deferred) {
var loading = $("<div class='k-loading-pdf-mask'><div class='k-loading-color'></div></div>");
loading.prepend(this.wrapper.clone().css({
position: "absolute",
top: 0,
left: 0
}));
this.wrapper.append(loading);
var progressBar = $("<div class='k-loading-pdf-progress'>").appendTo(loading).kendoProgressBar({
type: "chunk",
chunkCount: 10,
min: 0,
max: 1,
value: 0
}).data("kendoProgressBar");
deferred.progress(function(e) {
progressBar.value(e.progress);
}).always(function() {
kendo.destroy(loading);
loading.remove();
});
};
TreeList.prototype._drawPDF_autoPageBreak = function(progress) {
var treeList = this;
var result = new $.Deferred();
var dataSource = treeList.dataSource;
var allPages = treeList.options.pdf.allPages;
var origBody = treeList.wrapper.find("table[role=\"treeList\"] > tbody");
var cont = $("<div>").css({
position: "absolute",
left: -1e4,
top: -1e4
});
var clone = treeList.wrapper.clone().css({
height: "auto",
width: "auto"
}).appendTo(cont);
clone.find(".k-grid-content").css({
height: "auto",
width: "auto",
overflow: "visible"
});
clone.find("table[role=\"treeList\"], .k-grid-footer table").css({
height: "auto",
width: "100%",
overflow: "visible"
});
clone.find(".k-grid-pager, .k-grid-toolbar, .k-grouping-header").remove();
clone.find(".k-grid-header, .k-grid-footer").css({ paddingRight: 0 });
this._initPDFProgress(progress);
var body = clone.find("table[role=\"treeList\"] > tbody").empty();
var startingPage = dataSource.page();
function resolve() {
if (allPages && startingPage !== undefined) {
dataSource.one("change", draw);
dataSource.page(startingPage);
} else {
treeList.refresh();
draw();
}
}
function draw() {
cont.appendTo(document.body);
var options = $.extend({}, treeList.options.pdf, {
_destructive: true,
progress: function(p) {
progress.notify({
page: p.page,
pageNumber: p.pageNum,
progress: .5 + p.pageNum / p.totalPages / 2,
totalPages: p.totalPages
});
}
});
kendo.drawing.drawDOM(clone, options).always(function() {
cont.remove();
}).then(function(group) {
result.resolve(group);
}).fail(function(err) {
result.reject(err);
});
}
function renderPage() {
var pageNum = dataSource.page();
var totalPages = allPages ? dataSource.totalPages() : 1;
body.append(origBody.find("tr"));
if (pageNum < totalPages) {
dataSource.page(pageNum + 1);
} else {
dataSource.unbind("change", renderPage);
resolve();
}
}
if (allPages) {
dataSource.bind("change", renderPage);
dataSource.page(1);
} else {
renderPage();
}
return result.promise();
};
}
extend(true, kendo.data, {
TreeListDataSource,
TreeListModel
});
extend(kendo.ui.treelist, {
editor: Editor,
defaultBodyContextMenu,
defaultHeadContextMenu
});
ui.plugin(TreeList);
ui.plugin(TreeListPager);
})(window.kendo.jQuery);
var kendo_treelist_default = kendo;
//#endregion
export { kendo_treelist_default as n, __meta__ as t };