@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,355 lines (1,173 loc) • 64.2 kB
JavaScript
import './kendo.menu.js';
import './mixins-C63N9J7p.js';
import './kendo.ooxml.js';
import './kendo.progressbar.js';
import './kendo.treelist.js';
import './kendo.dialog.js';
import { ExcelExporter } from '@progress/kendo-ooxml';
import './kendo.popup.js';
import './kendo.core.js';
import './kendo.licensing.js';
import '@progress/kendo-licensing';
import './kendo.data.js';
import './kendo.data.odata.js';
import './kendo.data.xml.js';
import './kendo.icons.js';
import './kendo.html.icon.js';
import './kendo.html.base.js';
import '@progress/kendo-svg-icons';
import './kendo.dom.js';
import './kendo.columnsorter.js';
import './kendo.editable.js';
import './kendo.checkbox.js';
import './kendo.toggleinputbase.js';
import './kendo.html.input.js';
import './kendo.dropdownlist.js';
import './kendo.list.js';
import './kendo.label.js';
import './kendo.floatinglabel.js';
import './kendo.actionsheet.js';
import './kendo.html.button.js';
import './kendo.actionsheet.view.js';
import './kendo.button.js';
import './kendo.badge.js';
import './dropdowns-loader-00xUvouJ.js';
import './kendo.mobile.scroller.js';
import './kendo.fx.js';
import './kendo.draganddrop.js';
import './kendo.userevents.js';
import './kendo.virtuallist.js';
import './valueMapper-CXgI6HWc.js';
import './kendo.datepicker.js';
import './kendo.calendar.js';
import './kendo.selectable.js';
import './kendo.dateinput.js';
import '@progress/kendo-dateinputs-common';
import './kendo.numerictextbox.js';
import './prefix-suffix-containers-Cid0cOEy.js';
import './kendo.textbox.js';
import './kendo.combobox.js';
import './kendo.multiselect.js';
import './kendo.html.chip.js';
import './kendo.html.chiplist.js';
import './kendo.validator.js';
import './kendo.binder.js';
import './kendo.otpinput.js';
import './kendo.upload.js';
import './kendo.window.js';
import './kendo.filtermenu.js';
import './kendo.buttongroup.js';
import './kendo.togglebutton.js';
import './kendo.pane.js';
import './kendo.view.js';
import './kendo.columnmenu.js';
import './kendo.tabstrip.js';
import './kendo.sortable.js';
import './kendo.expansionpanel.js';
import './kendo.resizable.js';
import './kendo.treeview.draganddrop.js';
import './kendo.pager.js';
import './kendo.filtercell.js';
import './kendo.autocomplete.js';
import './kendo.form.js';
import './kendo.toolbar.js';
import './kendo.splitbutton.js';
import './kendo.button.menu.js';
import './kendo.dropdownbutton.js';
import './kendo.reorderable.js';
import './html-DIrOxn6k.js';
import '@progress/kendo-drawing';
import './kendo.color.js';
import './mixins-pM1BXjp5.js';
(function($, undefined$1) {
const kendo = window.kendo,
ui = kendo.ui,
TreeListContextMenu = ui.treelist.ContextMenu,
extend = $.extend;
let PropertyGridContextMenu = TreeListContextMenu.extend({
init: function(element, options) {
const that = this;
TreeListContextMenu.fn.init.call(that, element, options);
},
defaultItems: {
"separator": { name: "separator", separator: true },
"copy": { name: "copy", text: "Copy", icon: "copy", command: "CopyCommand", softRules: "windowHasSelection",options: "copy:selection" },
"copyName": { name: "copyName", text: "Copy Name", icon: "file-txt", command: "CopyCommand", options: "copy:name" },
"copyDeclaration": { name: "copyDeclatarion", text: "Copy Declaration", icon: "file-data", command: "CopyCommand", options: "copy:declaration" },
"resize": { name: "resize", text: "Resize Column", icon: "arrows-left-right", rules: "isResizable", command: "ResizeColumnCommand",softRules: "isNotGroupColumn" },
"reset": { name: "reset", text: "Reset", icon: "arrow-rotate-ccw", command: "ResetCommand", rules: "isEditable", softRules: "isDirty;isNotInEditMode" },
"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" }
}
});
kendo.ui.propertygrid = kendo.ui.propertygrid || {};
extend(kendo.ui.propertygrid, {
ContextMenu: PropertyGridContextMenu
});
})(window.kendo.jQuery);
(function($, undefined$1) {
let kendo = window.kendo,
extend = $.extend,
Class = kendo.Class,
keys = kendo.keys,
COLUMNSIZE = "#columnsize";
let Command = Class.extend({
init: function(options) {
this.options = options;
this.propertyGrid = options.propertyGrid;
}
});
let CopyCommand = Command.extend({
exec: function() {
const that = this,
options = that.options,
propertyGrid = that.propertyGrid,
target = that.options.target.closest("tr"),
dataItem = propertyGrid.dataItem(target);
if (options.copy == "selection") {
let sel = window.getSelection();
let range = sel.getRangeAt(0);
let selectedText = range.toString();
navigator.clipboard.writeText(selectedText);
} else if (options.copy == "name") {
navigator.clipboard.writeText(dataItem.field);
} else if (options.copy == "declaration") {
let value = that.propertyGrid._objectFromNodes(dataItem);
let tabDelimitedValue = [dataItem.field, JSON.stringify(value[dataItem.field]), dataItem.description].filter(item => item !== undefined$1).join("\t");
navigator.clipboard.writeText(tabDelimitedValue);
}
}
});
let ResetCommand = Command.extend({
exec: function() {
let that = this,
propertyGrid = that.propertyGrid,
target = that.options.target.closest("tr"),
dataItem = propertyGrid.dataItem(target);
propertyGrid.dataSource.cancelChanges(dataItem);
propertyGrid.trigger("cancel", { type: "cancel", model: dataItem, container: that.options.target });
propertyGrid._render();
}
});
let ResizeColumnCommand = Command.extend({
_actionButtonsTemplate: function({ apply, cancel, insertButtonIcon, cancelButtonIcon }) {
return '<div class="k-actions k-actions-start k-actions-horizontal k-window-buttons">' +
kendo.html.renderButton(`<button class="k-dialog-apply">${apply}</button>`, { themeColor: "primary", icon: insertButtonIcon }) +
kendo.html.renderButton(`<button class="k-dialog-close">${cancel}</button>`, { icon: cancelButtonIcon }) +
'</div>';
},
exec: function() {
let that = this, dialog, form,
propertyGrid = that.propertyGrid,
tableColumnIndex = that.options.target.index(),
columnIndex = propertyGrid.grouped ? tableColumnIndex - 1 : tableColumnIndex,
columnSelector = `tr:not(.k-table-group-row):first > td:nth-child(${tableColumnIndex + 1})`,
oldColumnWidth = propertyGrid.table.find(columnSelector).outerWidth(),
dialogOptions = {
title: "Resize Column",
visible: false,
resizable: true,
minWidth: 350
},
totalWidth = propertyGrid.table.width();
adjustColWidths(that.propertyGrid);
propertyGrid.table.width(totalWidth);
function apply(e) {
let delta;
let oldColumnWidth = dialog.wrapper.find(".k-form").data("kendoForm").options.formData.columnsize;
let newColumnWidth = dialog.wrapper.find(COLUMNSIZE).data("kendoNumericTextBox").value();
if (oldColumnWidth == newColumnWidth) {
close(e);
return;
} else if (oldColumnWidth > newColumnWidth) {
delta = oldColumnWidth - newColumnWidth;
propertyGrid.table.width(totalWidth - delta);
} else {
delta = newColumnWidth - oldColumnWidth;
propertyGrid.table.width(totalWidth + delta);
}
propertyGrid.columns[columnIndex].width = newColumnWidth;
propertyGrid.table.children("colgroup").find("col").eq(tableColumnIndex).width(newColumnWidth);
propertyGrid.trigger("columnResize", {
column: propertyGrid.columns[columnIndex],
oldWidth: oldColumnWidth,
newWidth: newColumnWidth
});
close(e);
}
function close(e) {
e.preventDefault();
form.destroy();
dialog.destroy();
}
function keyDown(e) {
if (e.keyCode == keys.ENTER) {
apply(e);
} else if (e.keyCode == keys.ESC) {
close(e);
}
}
function adjustColWidths(component) {
const columnSelector = (columnIndex) => `tr:not(.k-table-group-row):first > td:nth-child(${columnIndex + 1})`,
colCount = component.table.children("colgroup").find("col").length;
let widths = [];
for (let idx = 0; idx < colCount; idx++) {
widths.push(component.table.find(columnSelector(idx)).outerWidth());
}
component.table.children("colgroup").find("col").each((idx,col) => {
$(col).width(widths[idx]);
});
}
dialogOptions.close = close;
dialog = $("<div/>").appendTo(document.body).kendoWindow(dialogOptions).data("kendoWindow");
form = that._createForm(dialog, oldColumnWidth);
dialog.element.after($(that._actionButtonsTemplate({ apply: "Apply", cancel: "Cancel" , insertButtonIcon: "check", cancelButtonIcon: "cancel-outline" })));
dialog.wrapper
.find(".k-dialog-apply").on("click", apply).end()
.find(".k-dialog-close").on("click", close).end()
.find(".k-form-field input").on("keydown", keyDown).end();
dialog.center().open();
},
_createForm: function(dialog, currentColumnWidth) {
let formElement = $("<div/>").appendTo(dialog.element);
return formElement.kendoForm({
formData: {
columnsize: currentColumnWidth
},
validation: {
validateOnBlur: false,
validaitonSummary: false
},
renderButtons: false,
items: [
{
field: "columnsize",
label: "Set column Size",
editor: "NumericTextBox",
editorOptions: {
min: 0
}
}
]
}).data("kendoForm");
}
});
let ToggleItemCommand = Command.extend({
exec: function() {
let that = this,
propertyGrid = that.propertyGrid,
target = that.options.target,
options = that.options,
expand = options.expand === 'true';
if (expand) {
propertyGrid.expand(target);
} else {
propertyGrid.collapse(target);
}
}
});
let ToggleGroupLayout = Command.extend({
exec: function() {
let that = this,
propertyGrid = that.propertyGrid,
grouped = propertyGrid.grouped;
propertyGrid.grouped = !grouped;
if ( !propertyGrid.grouped) {
propertyGrid.wrapper.find("tr:not(.k-details-box)").removeClass("k-hidden");
}
propertyGrid._refreshLayout();
propertyGrid._updateDetails();
}
});
let ToggleDetails = Command.extend({
exec: function() {
let that = this,
propertyGrid = that.propertyGrid,
visible = propertyGrid.visibleDetails;
propertyGrid.visibleDetails = !visible;
if ( !propertyGrid.visible) {
propertyGrid.table.find("tr.k-details-box").toggleClass("k-hidden");
}
}
});
let ExcelExport = Command.extend({
exec: function() {
let that = this,
propertyGrid = that.propertyGrid;
propertyGrid.saveAsExcel();
}
});
let PDFExport = Command.extend({
exec: function() {
let that = this,
propertyGrid = that.propertyGrid;
propertyGrid.saveAsPDF();
}
});
kendo.ui.propertygrid = kendo.ui.propertygrid || {};
extend(kendo.ui.propertygrid, {
PropertyGridCommand: Command,
commands: {
ResetCommand: ResetCommand,
CopyCommand: CopyCommand,
ResizeColumnCommand: ResizeColumnCommand,
ToggleItemCommand: ToggleItemCommand,
ToggleGroupLayout: ToggleGroupLayout,
ToggleDetails: ToggleDetails,
ExcelExport: ExcelExport,
PDFExport: PDFExport,
}
});
})(window.kendo.jQuery);
const __meta__ = {
id: "propertygrid",
name: "PropertyGrid",
category: "web",
description: "The PropertyGrid widget displays objects as hierarchical structure and provides means to edit the properties and attributes of objects.",
depends: [ "excel", "menu", "treelist" ]
};
(function($, undefined$1) {
const kendo = window.kendo,
ui = kendo.ui,
NS = ".kendoPropertyGrid",
extend = $.extend,
kendoDom = kendo.dom,
kendoDomElement = kendoDom.element,
kendoHtmlElement = kendoDom.html,
kendoTextElement = kendoDom.text,
keys = $.extend({ F10: 121 }, kendo.keys),
Editable = ui.Editable,
TreeList = ui.TreeList,
isArray = Array.isArray,
isPlainObject = $.isPlainObject,
CHANGE = "change",
CLICK = "click",
EDIT = "edit",
EXPAND = "expand",
COLLAPSE = "collapse",
GROUP_EXPAND = "groupExpand",
GROUP_COLLAPSE = "groupCollapse",
COLUMNRESIZE = "columnResize",
CELL_CLOSE = "cellClose",
SAVE = "save",
CANCEL = "cancel",
BEFORE_EDIT = "beforeEdit",
PDF_EXPORT = "pdfExport",
CARET_ALT_DOWN = "a[class*='-i-caret-alt-down']",
CARET_ALT_RIGHT = "a[class*='-i-caret-alt-right']",
DOT = ".",
GROUPING_ROW = "k-grouping-row",
TR = "tr",
TD = "td",
ARIA_LABEL = "aria-label",
COLLAPSE_ICON = "caret-alt-down",
EXPAND_ICON = "caret-alt-right";
const defaultBodyContextMenu = [
"copy",
"copyName",
"copyDeclaration",
"separator",
"reset",
"separator",
"resize",
"separator",
"expandItem",
"collapseItem",
"separator"
];
const defaultCommands = {
group: {
name: "group",
type: "button",
text: 'Group Items',
togglable: true,
showText: "overflow",
icon: "categorize",
commandName: "ToggleGroupLayout",
attributes: {
title: "Group Items"
},
overflow: "never"
},
details: {
name: "details",
type: "button",
text: 'Toggle Info box',
togglable: true,
icon: "info-circle",
commandName: "ToggleDetails",
showText: "overflow",
attributes: {
title: "Toggle Info box"
},
overflow: "never"
},
sort: {
name: "sort",
component: "DropDownList",
componentOptions: {
commandOn: CHANGE,
dataTextField: "text",
dataValueField: "value",
dataSource: [
{ text: "Default Sort", value: "none" },
{ text: "Sort A-Z", value: "asc" },
{ text: "Sort Z-A", value: "desc" }
],
},
attributes: {
class: "k-property-grid-sort",
title: "Sort"
},
overflow: "never"
},
search: {
name: "search",
component: "TextBox",
componentOptions: {
prefixOptions: {
icon: "search"
},
placeholder: "Search...",
},
attributes: {
class: "k-grid-search"
},
overflow: "never"
},
separator: {
name: "separator",
type: "separator",
},
spacer: {
name: "spacer",
type: "spacer",
},
excel: {
name: "excel",
type: "button",
text: "Export to Excel",
showText: false,
icon: "file-excel",
commandName: "ExcelExport",
overflow: "auto"
},
pdf: {
name: "excel",
type: "button",
text: "Export to PDF",
showText: false,
icon: "file-pdf",
commandName: "PDFExport",
overflow: "auto"
},
};
function isNullorUndefined(value) {
return value === undefined$1 || value === null;
}
function isCollection(value) {
return typeof value === 'object' && isArray(value);
}
function isComplexObject(value) {
return typeof value === 'object' && !kendo.isDate(value);
}
function isEditable(value) {
return (kendo.type(value) != 'object' && kendo.type(value) != 'function');
}
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 asArray(obj) {
return Object.entries(obj).map(x=>x[1]);
}
let PropertyGridDataSource = kendo.data.TreeListDataSource.extend({
groupedItemsTree: function(field) {
let map = this._childrenMap(this.view()),
defaultParentId = this._defaultParentId(),
currentChildren = map[defaultParentId] || [],
grouped = new kendo.data.Query(currentChildren).group({ field: field }).toArray();
return grouped;
},
filterGroupedItemsTree: function(expression, field) {
let dataSource = this;
let sort = this.sort() || {};
let filterExpression = expression || { filters: [], logic: "or" };
let map = this._childrenMap(this.data()),
defaultParentId = this._defaultParentId(),
currentChildren = map[defaultParentId] || [],
groups = new kendo.data.Query(currentChildren).sort(sort).group({ field: field }).toArray();
let filterItems = function(filterExpression, items) {
let filtered = [];
for (let i = 0; i < items.length; i++) {
if (items[i].hasChildren && filterItems(filterExpression, dataSource.childNodes(items[i])).length > 0) {
filtered.push(items[i]);
}
}
return filtered.length != 0 ? filtered : new kendo.data.Query(items).sort(sort).filter(filterExpression).toArray();
};
let filteredGroups = [];
groups.forEach(function(itm) {
if (itm.items) {
itm.items = filterItems(filterExpression,itm.items);
}
filteredGroups.push(itm);
});
return filteredGroups;
}
});
const DynamicInCellEditor = kendo.ui.treelist.editor.extend({
createEditable: function() {
let options = this.options;
this.fields[0].editor = options.model.editor;
this.fields[0].editorOptions = { ...options.model.editorOptions };
this.editable = new Editable(this.wrapper, {
fields: this.fields,
target: options.target,
clearContainer: options.clearContainer,
model: this.model,
change: options.change,
});
},
destroy: function() {
let 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;
}
});
const PropertyGrid = TreeList.extend({
init: function(element, options) {
const that = this;
that._processOptions(options);
that.options = extend(true, {}, that.options, options);
that._processedModel = that._processModel();
that._createDataSource();
TreeList.fn.init.call(that, element, that.options);
that._wrapper();
that._detailsBox();
that._groupable();
kendo.notify(that);
},
options: {
name: 'PropertyGrid',
model: {},
items: [],
columns: [{ field: "field" },{ field: "value", editable: function(e) { return isEditable(e.value); } }],
hasHeader: false,
groupable: true,
resizable: true,
contextMenu: false,
sortable: true,
selectable: true,
scrollable: true,
showDetails: true,
editable: "incell",
size: "medium",
defaultTools: [defaultCommands.search, defaultCommands.sort, defaultCommands.group, defaultCommands.details],
messages: {
defaultGroupName: "Other"
}
},
events: [
BEFORE_EDIT,
EDIT,
CHANGE,
EXPAND,
COLLAPSE,
COLUMNRESIZE,
GROUP_EXPAND,
GROUP_COLLAPSE,
CELL_CLOSE,
SAVE,
CANCEL,
PDF_EXPORT
],
defaultEditors: {
string: "TextBox",
date: "DatePicker",
number: "NumericTextBox",
boolean: "CheckBox"
},
_groupContentTemplate: ({ groupName, action, icon }) => `<p class="k-reset">${kendo.ui.icon($('<a href="#" tabindex="-1" ' + ARIA_LABEL + '=' + action + '></a>'), icon)}${groupName}</p>`,
_detailsTemplate: ({ description }) => `<span>${description || ' '}</span>`,
_setEditable: function(value) {
const that = this;
that.options.editable = value;
},
_processOptions: function(options) {
const that = this;
kendo.type(options.editMode) === "boolean" && !options.editMode ? that._setEditable(false) : that._setEditable("incell");
if (isNullorUndefined(options.toolbar)) {
options.toolbar = that.options.defaultTools;
} else if (isPlainObject(options.toolbar)) {
options.toolbar.items = options.toolbar.items || that.options.defaultTools;
}
that._extendColumnOptions(options);
},
_extendColumnOptions: function(options) {
const that = this;
if (!options.columns) {
return;
}
that.options.columns[0] = extend(true, options.columns.fieldColumn, that.options.columns[0]);
that.options.columns[1] = extend(true, options.columns.valueColumn, that.options.columns[1]);
delete options.columns;
},
_processSettings: function(obj, settings) {
const that = this;
settings.forEach((item) => {
if (obj[item.field]) {
extend(obj[item.field], item);
if (obj[item.field].items) {
that._processSettings(obj[item.field].value, obj[item.field].items);
}
}
});
},
_processModel: function() {
const that = this,
model = that.options.model,
options = that.options;
let flatData = that._flatten(model);
that._setDefaults(flatData);
that._processSettings(flatData, options.items );
return asArray(flatData);
},
_createDataSource: function() {
const that = this,
dataSource = new PropertyGridDataSource({
data: that._processedModel,
serverGrouping: false,
schema: {
model: {
id: "id",
parentId: "parentId",
expanded: true,
fields: {
field: { editable: false },
value: { editable: true }
}
},
}
});
that.options.dataSource = dataSource;
},
_flatten: function(model) {
let id = 1;
function appendNested(result, key, nestedKeys, nestedObject, collectionIdx) {
if (!isNullorUndefined(collectionIdx)) {
nestedKeys.forEach (nestedKey => {
result[`${key}.${collectionIdx}.${nestedKey}`] = nestedObject[nestedKey];
result[`${key}.${collectionIdx}.${nestedKey}`].parentId = result[`${key}.${collectionIdx}`].id;
});
} else {
nestedKeys.forEach (nestedKey => {
result[`${key}.${nestedKey}`] = nestedObject[nestedKey];
});
}
}
function flattenCollection(result, obj, key, parentId) {
const collection = obj[key];
result[key] = {
id: id++,
parentId: parentId,
propType: "Array",
field: key,
value: collection,
};
for (let i = 0; i < collection.length; i++) {
const nested = typeof collection[i] === "object" ?
flattenObject(collection[i], result[key].id) :
collection[i];
result[`${key}.${i}`] = {
id: id++,
parentId: result[key].id,
propType: typeof obj[key],
field: `${key}[${i}]`,
value: nested
};
if (typeof collection[i] === "object") {
const nestedKeys = Object.keys(nested);
appendNested(result, key, nestedKeys, nested, i);
}
}
}
function flattenObject(obj, parentId) {
const result = {},
keys = Object.keys(obj || { } );
keys.forEach ((key) => {
if (isNullorUndefined(obj[key])) {
result[key] = {
id: id++,
parentId: parentId,
propType: typeof obj[key],
field: key,
value: obj[key]
};
} else if (isCollection(obj[key])) {
flattenCollection(result, obj, key, parentId);
} else if (isComplexObject(obj[key])) {
let tempId = id++;
const nestedObject = flattenObject(obj[key], tempId);
const nestedKeys = Object.keys(nestedObject);
result[key] = {
id: tempId,
parentId: parentId,
propType: typeof obj[key],
field: key,
value: nestedObject,
};
appendNested(result, key, nestedKeys, nestedObject);
} else {
let parsed = kendo.parseDate(obj[key].toString());
result[key] = {
id: id++,
parentId: parentId,
propType: parsed != null ? typeof parsed : typeof obj[key],
field: key,
value: parsed != null ? parsed : obj[key]
};
}
});
return result;
}
return flattenObject(model, null);
},
_setDefaults: function(obj) {
const that = this;
Object.keys(obj).forEach(key => {
if (that.options.groupable && !obj[key].group) {
obj[key].group = that.options.messages.defaultGroupName;
}
that._setDefaultEditor(obj[key]);
});
},
_setDefaultEditor: function(obj) {
const that = this,
type = kendo.type(obj.value);
switch (type) {
case "date":
obj.editor = that.defaultEditors.date;
break;
case "boolean":
obj.editor = that.defaultEditors.boolean;
break;
case "number":
obj.editor = that.defaultEditors.number;
break;
default:
obj.editor = that.defaultEditors.string;
break;
}
},
_createIncellEditor: function(cell, options) {
const that = this;
let column = extend({}, options.columns[0]);
options.model.fields.value.validation = options.model.validation ? options.model.validation.toJSON() : {};
delete column.parentColumn;
return new DynamicInCellEditor(cell, extend({}, {
fieldRenderer: that._cellContent.bind(that),
appendTo: that.wrapper,
clearContainer: false,
target: that,
columns: [column],
model: options.model,
change: options.change
}));
},
_createDirtyTemplate: function(model) {
const that = this;
let templateSettings = that._customTemplateSettings();
let dirtyIndicator = function(data) {
return '<span class="k-dirty"></span>';
};
let templateFunction = function(data) {
return (dirtyIndicator() + kendo.template(model.template)(model));
};
return kendo.template(templateFunction, templateSettings).bind({ columnTemplate: model.template });
},
_cellContent: function(column, model) {
const that = this,
incellEditing = that._isIncellEditable(),
isValueColumn = column.field == "value";
let value, dirtyIndicator, template;
if (isValueColumn && model.template) {
template = model.dirty ? that._createDirtyTemplate(model) : kendo.template(model.template);
value = template(model);
} else if (column.field) {
value = model.get(column.field);
dirtyIndicator = incellEditing ? column.dirtyIndicatorTemplate(model) : "";
if (!isNullorUndefined(value)) {
if (model.format) {
value = kendo.format(model.format, value);
}
value = dirtyIndicator + value;
} else {
value = dirtyIndicator;
}
} else if (isNullorUndefined(value)) {
value = "";
}
if (model.template) {
return kendoHtmlElement(value);
} else {
if (incellEditing) {
return isEditable(model.value) && isValueColumn ? that._editableCellContent(value) : kendoHtmlElement(value);
} else {
return kendoTextElement(value);
}
}
},
_editableCellContent: function(value) {
let bTag = kendoDomElement("b");
let content = kendoHtmlElement(value);
bTag.children.push(content);
return bTag;
},
_generateGroupRow: function(item) {
const that = this;
let groupRowContent = (kendo.template(that._groupContentTemplate)({
groupName: item.value,
action: item.visible ? COLLAPSE : EXPAND,
icon: item.visible ? COLLAPSE_ICON : EXPAND_ICON
}));
let tdElement = kendoDomElement(TD, { className: "k-table-td", class: "k-table-td", colSpan: "3" , role: "gridcell", "aria-expanded": item.visible, visible: true }, [kendo.dom.html(groupRowContent)] );
let trElement = kendoDomElement(TR, { className: "k-table-group-row k-grouping-row k-table-row", role: "row" , "data-uid": item.uid }, [tdElement] );
return trElement;
},
_generateDetailsBox: function() {
const that = this;
let tdElement = kendoDomElement(TD, { className: "k-table-td", class: "k-table-td", colSpan: that.grouped ? 3 : 2 , role: "gridcell", visible: true }, [kendo.dom.html("<span> </span>")] );
let trElement = kendoDomElement(TR, {
className: `k-details-box k-bottom k-sticky k-footer-template k-table-row ${!that.visibleDetails ? 'k-hidden' : ''}`,
role: "row"
}, [tdElement] );
return trElement;
},
_renderRows: function(options, data, columns, selected, childrenMap, viewChildrenMap, hasFooterTemplate) {
const that = this;
let selectedRow = selected.length ? selected : that._selectedRowUid;
let rows = [];
if (that.grouped) {
if (that.table.find(">colgroup>col.k-group-col").length === 0) {
that.table.find(">colgroup").prepend('<col class="k-group-col">');
}
that._groupedData.forEach(item => {
let groupTr = that._generateGroupRow(item);
rows.push(groupTr);
rows = rows.concat(that._trs({
columns: columns,
editedColumn: options.editedColumn,
editedColumnIndex: options.editedColumnIndex,
aggregates: options.aggregates,
selected: selectedRow,
data: item.items,
childrenMap: childrenMap,
viewChildrenMap: viewChildrenMap,
hasFooterTemplate: hasFooterTemplate,
visible: item.visible,
level: 0
}));
});
} else {
that.table.find(">colgroup>col.k-group-col").remove();
rows = rows.concat(this._trs({
columns: columns,
editedColumn: options.editedColumn,
editedColumnIndex: options.editedColumnIndex,
aggregates: options.aggregates,
selected: selectedRow,
data: data,
childrenMap: childrenMap,
viewChildrenMap: viewChildrenMap,
hasFooterTemplate: hasFooterTemplate,
visible: true,
level: 0
}));
}
if (that.options.showDetails) {
rows.push(that._generateDetailsBox());
}
that._contentTree.render(rows);
},
_generateRowOptions: function(model, attr, pageable, options, level, hasChildren) {
const that = this;
let rowOptions = {
model: model,
attr: attr,
level: pageable ? that._renderedModelLevel(model, options) : level,
editedColumn: options.editedColumn,
editedColumnIndex: options.editedColumnIndex,
hasChildren: hasChildren,
visible: options.visible,
isAlt: this._absoluteIndex % 2 === 0,
grouped: that.options.groupable && that.grouped
};
return rowOptions;
},
_renderRow: function(rowOptions, columns, renderer) {
let row = this._tds(rowOptions, columns, renderer);
if (rowOptions.grouped) {
let groupTdElement = kendoDomElement(TD, { class: "k-table-td k-group-cell", className: "k-table-td k-group-cell" });
row.children.splice(0,0,groupTdElement);
}
return row;
},
editCell: function(cell) {
const that = this;
let cellIndex;
cell = $(cell);
cellIndex = that.grouped ? that.cellIndex(cell) - 1 : that.cellIndex(cell);
let column = that.columns[cellIndex];
let model = that.dataItem(cell);
if (that._isIncellEditable() && model && isColumnEditable(column, model)) {
that._editCell(cell, column, model, cellIndex);
}
},
_wrapper: function() {
const that = this;
that.element.css("width", this.options.width);
that.wrapper.addClass("k-property-grid");
},
_toolbar: function() {
const that = this,
options = that.options;
let toolbarOptions = options.toolbar;
let toolbar = this.toolbar;
if (!toolbarOptions) {
return;
}
if (Array.isArray(toolbarOptions) || isPlainObject(toolbarOptions)) {
toolbarOptions = isPlainObject(toolbarOptions) ? toolbarOptions : { items: toolbarOptions };
let items = that._processToolbarItems(toolbarOptions.items);
items = that._verifyItems(items);
toolbar.kendoToolBar({
size: "medium",
resizable: true,
navigateOnTab: !options.navigatable,
items: items,
overflow: toolbarOptions.overflow
});
toolbar.find(".k-grid-search .k-input-inner").attr({
placeholder: options.messages.commands.search,
title: options.messages.commands.search
});
that._attachToolbarHandlers();
} else {
toolbar.append(kendo.template(toolbarOptions)({}));
}
},
_attachToolbarHandlers: function() {
const that = this;
let toolbarWidget = that.toolbar.getKendoToolBar();
let sortElement = toolbarWidget.element.find('[data-command="sort"] input');
toolbarWidget.bind("toggle", that._toolbarClick.bind(that));
toolbarWidget.bind("click", that._toolbarClick.bind(that));
if (sortElement.length > 0) {
sortElement.getKendoDropDownList().bind("change", that._sortItems.bind(that));
}
},
_verifyItems: function(items) {
const that = this;
if ((!that.options.groupable || !that.options.items.some(x=>x.hasOwnProperty("group")) )) {
items = items.filter(x=>x.name != "group");
}
if (!(that.options.showDetails && that.options.selectable) && items.findIndex(x=>x.name == "details") > 0) {
items = items.filter(x=>x.name != "details");
}
return items;
},
_getCommandType: function(command) {
if (command.type) {
return command.type;
}
if (command.template) {
return null;
}
return "button";
},
_processToolbarItems: function(commands) {
const that = this,
messages = that.options.messages.commands;
let items = [];
commands.map(command => {
let name = (isPlainObject(command) ? command.name || "" : command).toLowerCase();
let text = messages[name];
if (!name && !(isPlainObject(command) && command.template)) {
throw new Error("Commands should have name specified");
}
command = extend({}, defaultCommands[name], {
name: name,
text: text || (defaultCommands[name] || {}).text,
type: that._getCommandType(defaultCommands[name] || {})
}, command);
if (command.imageClass) {
command.spriteCssClass = command.imageClass;
command.iconClass = command.imageClass;
}
if (!command.attributes) {
command.attributes = {};
}
command.attributes["data-command"] = command.commandName || name;
if (command.menuButtons || command.buttons) {
delete command.name;
}
command.click = (e) => {
let origEvent = e.event || e.originalEvent;
if (origEvent) {
origEvent.preventDefault();
origEvent.stopPropagation();
}
that._commandClick({
currentTarget: e.target
});
};
if (command.className) {
if (!command.attributes) {
command.attributes = {};
}
command.attributes["class"] = command.className;
}
command.attributes["title"] = text || command.attributes["title"];
items.push(command);
});
return items;
},
_toolbarClick: function(ev) {
let command = $(ev.target).data("command"),
options = $(ev.target).data("options");
if (!!$(ev.target).val()) {
options = extend({}, options, { value: $(ev.target).val() });
}
if (!command || !ui.propertygrid.commands[command] ) {
return;
}
this._action({
command: command,
options: options
});
},
_sortItems: function(e) {
const that = this,
dataSource = that.dataSource,
dir = e.sender.value();
let sort = dir === "none" ? {} : { field: "field", dir: dir };
dataSource.sort(sort);
that._groupedData = dataSource.filterGroupedItemsTree(dataSource.filter(),"group").map(itm => ({
...itm,
visible: that._groupedData.filter(x=>x.value == itm.value)[0].visible,
uid: that._groupedData.filter(x=>x.value == itm.value)[0].uid
}));
if (that.grouped) {
that.refresh();
}
},
_initContextMenu: function() {
const that = this,
options = that.options;
if (!options.contextMenu) {
return;
}
let tbodyContextMenu = isPlainObject(options.contextMenu) && isArray(options.contextMenu.body) ? { items: options.contextMenu.body } : { items: defaultBodyContextMenu };
let mainOptions = isPlainObject(options.contextMenu) ? options.contextMenu : {};
tbodyContextMenu = extend({}, {
messages: options.messages,
target: that.tbody,
filter: ".k-table-row:not(.k-grouping-row,.k-details-box) > .k-table-td",
action: that._action.bind(that),
states: that._buildStates()
}, mainOptions, tbodyContextMenu);
that.tbodyContextMenu = new ui.propertygrid.ContextMenu("<ul></ul>", tbodyContextMenu);
},
_buildStates: function() {
const that = this;
return {
isResizable: that.options.resizable,
isEditable: that.options.editable,
windowHasSelection: () => (typeof window.getSelection != 'undefined' && window.getSelection().rangeCount != 0 && window.getSelection().getRangeAt(0).toString() != ''),
isDirty: (target)=> {
let dataItem = this.dataItem(target);
return dataItem.dirty;
},
isNotInEditMode: (target) => !target.closest("td").hasClass("k-edit-cell"),
isNotGroupColumn: (target) => !target.closest("td").hasClass("k-group-cell"),
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) {
let commandName = args.command,
commandOptions = extend({ propertyGrid: this }, args.options),
command = new ui.propertygrid.commands[commandName](commandOptions);
return command.exec();
},
_objectFromNodes: function(rootNodes) {
const that = this,
hashTable = Object.create(null),
dataSource = that.dataSource;
rootNodes = isArray(rootNodes) ? rootNodes : [rootNodes];
rootNodes.forEach((node) => {
if (node.propType == "Array") {
hashTable[node.field] = [];
dataSource.childNodes(node).forEach((childNode) => {
hashTable[node.field].push(childNode.hasChildren ? that._objectFromNodes(dataSource.childNodes(childNode)) : childNode.value);
});
} else {
hashTable[node.field] = node.hasChildren ? that._objectFromNodes(dataSource.childNodes(node)) : node.value;
}
});
return hashTable;
},
_groupable: function() {
const that = this;
that._groupedData = that.dataSource.groupedItemsTree("group").map(itm => ({ ...itm, visible: true, uid: kendo.guid() }));
that._groupableClickHandler = function(e) {
let element = $(this),
groupRow = element.closest(TR);
let group = that._groupedData.filter(x=>x.value === groupRow.text())[0];
group.visible = !group.visible;
if (element.is(CARET_ALT_DOWN)) {
if (!that.trigger(GROUP_COLLAPSE, { group: group.items, element: groupRow })) {
that.refresh();
}
} else {
if (!that.trigger(GROUP_EXPAND, { group: group.items, element: groupRow })) {
that.refresh();
}
}
e.preventDefault();
e.stopPropagation();
};
that.table.on(CLICK + NS, ".k-grouping-row " + CARET_ALT_RIGHT + ", .k-grouping-row " + CARET_ALT_DOWN, that._groupableClickHandler)
.on("keydown" + NS, that._groupRowKeyDown.bind(that));
},
_groupRowKeyDown: function(e) {
const that = this,
current = that.current();
let handled = false;
if (!that.options.navigatable) {
return;
}
if (e.keyCode == keys.ENTER) {
kendo.focusElement(that.table);
that._setCurrent(that._findCurrentCell());
handled = true;
}
if ((e.keyCode == keys.LEFT || e.keyCode == keys.RIGHT) && e.altKey) {
handled = this._handleGroupRowExpandCollapse(current, e.keyCode);
}
if (handled) {
e.preventDefault();
e.stopPropagation();