/** * Kendo UI v2016.1.112 (http://www.telerik.com/kendo-ui) * Copyright 2016 Telerik AD. All rights reserved. * * Kendo UI commercial licenses may be obtained at * http://www.telerik.com/purchase/license-agreement/kendo-ui-complete * If you do not own a commercial license, this file shall be governed by the trial license terms. */ (function (f, define) { define('kendo.treelist', [ 'kendo.dom', 'kendo.data', 'kendo.columnsorter', 'kendo.editable', 'kendo.window', 'kendo.filtermenu', 'kendo.selectable', 'kendo.resizable', 'kendo.treeview.draganddrop' ], f); }(function () { var __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' ], 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-editing', name: 'Editing', description: 'Support for record editing', depends: [ 'editable', 'window' ] }, { 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' ] } ] }; (function ($, undefined) { var data = kendo.data; var extend = $.extend; var kendoDom = kendo.dom; var kendoDomElement = kendoDom.element; var kendoTextElement = kendoDom.text; var kendoHtmlElement = kendoDom.html; 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 proxy = $.proxy; var map = $.map; var grep = $.grep; var inArray = $.inArray; var isPlainObject = $.isPlainObject; var push = Array.prototype.push; var STRING = 'string'; var CHANGE = 'change'; var ERROR = 'error'; var PROGRESS = 'progress'; var DOT = '.'; var NS = '.kendoTreeList'; var CLICK = 'click'; var MOUSEDOWN = 'mousedown'; var EDIT = 'edit'; var SAVE = 'save'; var EXPAND = 'expand'; var COLLAPSE = 'collapse'; var REMOVE = 'remove'; var DATABINDING = 'dataBinding'; var DATABOUND = 'dataBound'; var CANCEL = 'cancel'; var FILTERMENUINIT = 'filterMenuInit'; var COLUMNHIDE = 'columnHide'; var COLUMNSHOW = 'columnShow'; var HEADERCELLS = 'th.k-header'; var COLUMNREORDER = 'columnReorder'; var COLUMNRESIZE = 'columnResize'; var COLUMNMENUINIT = 'columnMenuInit'; var COLUMNLOCK = 'columnLock'; var COLUMNUNLOCK = 'columnUnlock'; var PARENTIDFIELD = 'parentId'; var DRAGSTART = 'dragstart'; var DRAG = 'drag'; var DROP = 'drop'; var DRAGEND = 'dragend'; var classNames = { wrapper: 'k-treelist k-grid k-widget', header: 'k-header', button: 'k-button', alt: 'k-alt', editCell: 'k-edit-cell', group: 'k-treelist-group', 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', footerTemplate: 'k-footer-template', loading: 'k-loading', refresh: 'k-i-refresh', retry: 'k-request-retry', selected: 'k-state-selected', status: 'k-status', link: 'k-link', withIcon: 'k-with-icon', filterable: 'k-filterable', icon: 'k-icon', iconFilter: 'k-filter', iconCollapse: 'k-i-collapse', iconExpand: 'k-i-expand', iconHidden: 'k-i-none', iconPlaceHolder: 'k-icon k-i-none', input: 'k-input', dropPositions: 'k-insert-top k-insert-bottom k-add k-insert-middle', dropTop: 'k-insert-top', dropBottom: 'k-insert-bottom', dropAdd: 'k-add', dropMiddle: 'k-insert-middle', dropDenied: 'k-denied', dragStatus: 'k-drag-status', dragClue: 'k-drag-clue', dragClueText: 'k-clue-text' }; var defaultCommands = { create: { imageClass: 'k-add', className: 'k-grid-add', methodName: 'addRow' }, createchild: { imageClass: 'k-add', className: 'k-grid-add', methodName: 'addRow' }, destroy: { imageClass: 'k-delete', className: 'k-grid-delete', methodName: 'removeRow' }, edit: { imageClass: 'k-edit', className: 'k-grid-edit', methodName: 'editRow' }, update: { imageClass: 'k-update', className: 'k-primary k-grid-update', methodName: 'saveRow' }, canceledit: { imageClass: 'k-cancel', className: 'k-grid-cancel', methodName: '_cancelEdit' }, excel: { imageClass: 'k-i-excel', className: 'k-grid-excel', methodName: 'saveAsExcel' }, pdf: { imageClass: 'k-i-pdf', className: 'k-grid-pdf', methodName: 'saveAsPDF' } }; 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) { DataSource.fn.init.call(this, extend(true, {}, { schema: { modelBase: TreeListModel, model: TreeListModel } }, options)); }, _createNewModel: function (data) { var model = {}; var fromModel = data instanceof Model; if (fromModel) { model = data; } model = DataSource.fn._createNewModel.call(this, model); if (!fromModel) { if (data.parentId) { data[model.parentIdField] = data.parentId; } model.accept(data); } return model; }, _shouldWrap: function () { return true; }, _readData: function (newData) { var data = this.data(); newData = DataSource.fn._readData.call(this, newData); this._concat(newData, data); if (newData instanceof ObservableArray) { return newData; } return data; }, _concat: function (source, target) { var targetLength = target.length; for (var i = 0; i < source.length; i++) { target[targetLength++] = source[i]; } target.length = targetLength; }, _readAggregates: function (data) { var result = extend(this._aggregateResult, this.reader.aggregates(data)); if ('' in result) { result[this._defaultParentId()] = result['']; delete result['']; } return result; }, remove: function (root) { var items = this._subtree(this._childrenMap(this.data()), root.id); this._removeItems(items); DataSource.fn.remove.call(this, root); }, _filterCallback: function (query) { var i, item; var map = {}; var result = []; var data = query.toArray(); for (i = 0; i < data.length; i++) { item = data[i]; while (item) { if (!map[item.id]) { map[item.id] = true; result.push(item); } if (!map[item.parentId]) { map[item.parentId] = true; item = this.parentNode(item); if (item) { result.push(item); } } else { break; } } } return new Query(result); }, _subtree: function (map, id) { var result = map[id] || []; var defaultParentId = this._defaultParentId(); for (var i = 0, len = result.length; i < len; i++) { if (result[i].id !== defaultParentId) { result = result.concat(this._subtree(map, result[i].id)); } } 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; }, _calculateAggregates: function (data, options) { options = options || {}; var result = {}; var item, subtree, i; var filter = options.filter; if (filter) { data = Query.process(data, { filter: filter, filterCallback: proxy(this._filterCallback, this) }).data; } var map = this._childrenMap(data); result[this._defaultParentId()] = new Query(this._subtree(map, this._defaultParentId())).aggregate(options.aggregate); for (i = 0; i < data.length; i++) { item = data[i]; subtree = this._subtree(map, item.id); result[item.id] = new Query(subtree).aggregate(options.aggregate); } return result; }, _queryProcess: function (data, options) { options = options || {}; options.filterCallback = proxy(this._filterCallback, this); var defaultParentId = this._defaultParentId(); var 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; }, _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 || !requestParams.id) { this._data = this._observe([]); } return DataSource.fn.success.call(this, data, requestParams); }, 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'; } return this[method]({ id: model.id }).then(proxy(this._modelLoaded, this, model.id), proxy(this._modelError, this, model.id)); }, contains: function (root, child) { var rootId = root.id; while (child) { if (child.parentId === rootId) { return true; } child = this.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]; }, childNodes: function (model) { return this._byParentId(model.id, this._defaultParentId()); }, rootNodes: function () { return this._byParentId(this._defaultParentId()); }, parentNode: function (model) { return this.get(model.parentId); }, level: function (model) { var result = -1; if (!(model instanceof TreeListModel)) { model = this.get(model); } do { model = this.parentNode(model); result++; } while (model); return result; }, filter: function (value) { var baseFilter = DataSource.fn.filter; if (value === undefined) { return baseFilter.call(this, value); } baseFilter.call(this, value); } }); TreeListDataSource.create = function (options) { if ($.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 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').filter(filter).filter(function () { return this.rowSpan > 1; }); } cells = cells.add(rows.last().find('th').filter(filter)); var indexAttr = kendo.attr('index'); cells.sort(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; }); return cells; } function createPlaceholders(options) { var spans = []; var className = options.className; for (var i = 0, level = options.level; i < level; i++) { spans.push(kendoDomElement('span', { className: className })); } 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) { var lockedHeigth = table1.offsetHeight; var tableHeigth = table2.offsetHeight; var row; var diff; if (lockedHeigth > tableHeigth) { row = table2.rows[table2.rows.length - 1]; diff = lockedHeigth - tableHeigth; } else { row = table1.rows[table1.rows.length - 1]; diff = tableHeigth - lockedHeigth; } row.style.height = row.offsetHeight + diff + 'px'; } } 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(); }, events: [], _initContainer: function () { this.wrapper = this.element; }, createEditable: function () { var options = this.options; this.editable = new ui.Editable(this.wrapper, { fields: this.fields, target: options.target, clearContainer: options.clearContainer, model: this.model }); }, _isEditable: function (column) { return column.field && this.model.editable(column.field); }, _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 }); } } 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 = $('
').attr(kendo.attr('uid'), this.model.uid).append('
'); if (options.template) { this._appendTemplate(formContent); this.fields = []; } else { this._appendFields(formContent); } this._appendButtons(formContent); 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 = window.unescape(template); } template = kendo.template(template)(this.model); form.push(kendoHtmlElement(template)); }, _appendFields: function (form) { var idx, length, column; var columns = this.options.columns; for (idx = 0, length = columns.length; idx < length; idx++) { column = columns[idx]; if (column.command) { continue; } form.push(kendoHtmlElement('
')); if (this._isEditable(column)) { form.push(kendoHtmlElement('
')); } else { form.push(kendoDomElement('div', { 'class': 'k-edit-field' }, [this.options.fieldRenderer(column, this.model)])); } } }, _appendButtons: function (form) { form.push(kendoDomElement('div', { 'class': 'k-edit-buttons k-state-default' }, this.options.commandRenderer())); }, _attachHandlers: function () { var closeHandler = this._cancelProxy = proxy(this._cancel, this); this.wrapper.on(CLICK + NS, '.k-grid-cancel', this._cancelProxy); this._saveProxy = proxy(this._save, this); this.wrapper.on(CLICK + NS, '.k-grid-update', this._saveProxy); this.window.bind('close', function (e) { if (e.userTriggered) { closeHandler(e); } }); }, _dettachHandlers: function () { this._cancelProxy = null; this._saveProxy = null; this.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', proxy(this.destroy, this)).close(); }, destroy: function () { this.window.destroy(); this.window = null; this._dettachHandlers(); Editor.fn.destroy.call(this); } }); var TreeList = DataBoundWidget.extend({ init: function (element, options) { DataBoundWidget.fn.init.call(this, element, options); this._dataSource(this.options.dataSource); this._columns(); this._layout(); this._selectable(); this._sortable(); this._resizable(); this._filterable(); this._attachEvents(); this._toolbar(); this._scrollable(); this._reorderable(); this._columnMenu(); this._minScreenSupport(); this._draggable(); 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); } kendo.notify(this); }, _draggable: function () { var editable = this.options.editable; if (!editable || !editable.move) { return; } this._dragging = new kendo.ui.HierarchicalDragAndDrop(this.wrapper, { $angular: this.$angular, autoScroll: true, filter: 'tbody>tr', itemSelector: 'tr', allowedContainers: this.wrapper, hintText: function (row) { var text = function () { return $(this).text(); }; var separator = ''; return row.children('td').map(text).toArray().join(separator); }, contains: proxy(function (source, destination) { var dest = this.dataItem(destination); var src = this.dataItem(source); return src == dest || this.dataSource.contains(src, dest); }, this), itemFromTarget: function (target) { var tr = target.closest('tr'); return { item: tr, content: tr }; }, dragstart: proxy(function (source) { this.wrapper.addClass('k-treelist-dragging'); var model = this.dataItem(source); return this.trigger(DRAGSTART, { source: model }); }, this), drag: proxy(function (e) { e.source = this.dataItem(e.source); this.trigger(DRAG, e); }, this), drop: proxy(function (e) { e.source = this.dataItem(e.source); e.destination = this.dataItem(e.destination); this.wrapper.removeClass('k-treelist-dragging'); return this.trigger(DROP, e); }, this), dragend: proxy(function (e) { var dest = this.dataItem(e.destination); var src = this.dataItem(e.source); src.set('parentId', dest ? dest.id : null); e.source = src; e.destination = dest; this.trigger(DRAGEND, e); }, this), reorderable: false, dropHintContainer: function (item) { return item.children('td:eq(1)'); }, dropPositionFrom: function (dropHint) { return dropHint.prevAll('.k-i-none').length > 0 ? 'after' : 'before'; } }); }, itemFor: function (model) { if (typeof model == 'number') { model = this.dataSource.get(model); } return this.tbody.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).bind('DOMMouseScroll' + NS + ' mousewheel' + NS, proxy(this._wheelScroll, this)); this.content.bind('scroll' + NS, function () { scrollables.scrollLeft(this.scrollLeft); lockedContent.scrollTop(this.scrollTop); }); var touchScroller = kendo.touchScroller(this.content); if (touchScroller && touchScroller.movable) { this._touchScroller = touchScroller; touchScroller.movable.bind('change', function (e) { scrollables.scrollLeft(-e.sender.x); if (lockedContent) { lockedContent.scrollTop(-e.sender.y); } }); } } }, _wheelScroll: function (e) { if (e.ctrlKey) { return; } var delta = kendo.wheelDeltaY(e); if (delta) { e.preventDefault(); $(e.currentTarget).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(' #: messages.loading #')({ className: classNames.icon + ' ' + classNames.loading, messages: messages })); } }, _error: function (e) { if (!this.dataSource.rootNodes().length) { this._render({ error: e }); } }, refresh: function (e) { e = e || {}; if (e.action == 'itemchange' && this.editor) { return; } if (this.trigger(DATABINDING)) { return; } this._cancelEditor(); this._render(); this._adjustHeight(); this.trigger(DATABOUND); }, _angularFooters: function (command) { var i, footer, aggregates; var allAggregates = this.dataSource.aggregates(); var footerRows = this._footerItems(); for (i = 0; i < footerRows.length; i++) { footer = footerRows.eq(i); aggregates = allAggregates[footer.attr('data-parentId')]; this._angularFooter(command, footer.find('td').get(), aggregates); } }, _angularFooter: function (command, cells, aggregates) { var columns = this.columns; this.angular(command, function () { return { elements: cells, data: map(columns, function (col) { return { column: col, aggregate: aggregates && aggregates[col.field] }; }) }; }); }, 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').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; }, _showStatus: function (message) { var status = this.element.find('.k-status'); var content = $(this.content).add(this.lockedContent); if (!status.length) { status = $('
').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.content).add(this.lockedContent).show(); }, _adjustHeight: function () { 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 height; var scrollbar = kendo.support.scrollbar(); element.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 = element.height() - header.outerHeight() - toolbar.outerHeight(); 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 () { this._applyLockedContainersWidth(); this._adjustHeight(); }, _minScreenSupport: function () { var any = this.hideMinScreenCols(); if (any) { this.minScreenResizeHandler = proxy(this.hideMinScreenCols, this); $(window).on('resize', this.minScreenResizeHandler); } }, hideMinScreenCols: function () { var cols = this.columns, any = false, screenWidth = window.innerWidth > 0 ? window.innerWidth : screen.width; 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); } } } return any; }, destroy: function () { 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._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.minScreenResizeHandler) { $(window).off('resize', this.minScreenResizeHandler); } this._destroyEditor(); this.element.off(NS); if (this._touchScroller) { this._touchScroller.destroy(); } this._autoExpandable = null; this._refreshHandler = this._errorHandler = this._progressHandler = 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; }, 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', commands: { edit: 'Edit', update: 'Update', canceledit: 'Cancel', create: 'Add new record', createchild: 'Add child record', destroy: 'Delete', excel: 'Export to Excel', pdf: 'Export to PDF' } }, excel: { hierarchy: true }, resizable: false, filterable: false, editable: false, reorderable: false }, events: [ CHANGE, EDIT, SAVE, REMOVE, EXPAND, COLLAPSE, DATABINDING, DATABOUND, CANCEL, DRAGSTART, DRAG, DROP, DRAGEND, FILTERMENUINIT, COLUMNHIDE, COLUMNSHOW, COLUMNREORDER, COLUMNRESIZE, COLUMNMENUINIT, COLUMNLOCK, COLUMNUNLOCK ], _toggle: function (model, expand) { var loaded = model.loaded(); if (model._error) { model.expanded = false; model._error = undefined; } if (!loaded && model.expanded) { return; } if (typeof expand == 'undefined') { expand = !model.expanded; } model.expanded = expand; if (!loaded) { this.dataSource.load(model).always(proxy(function () { this._render(); this._syncLockedContentHeight(); }, this)); } this._render(); this._syncLockedContentHeight(); }, expand: function (row) { this._toggle(this.dataItem(row), true); }, collapse: function (row) { this._toggle(this.dataItem(row), false); }, _toggleChildren: function (e) { var icon = $(e.currentTarget); var model = this.dataItem(icon); var event = !model.expanded ? EXPAND : COLLAPSE; if (!this.trigger(event, { model: model })) { this._toggle(model); } e.preventDefault(); }, _attachEvents: function () { var icons = DOT + classNames.iconCollapse + ', .' + classNames.iconExpand + ', .' + classNames.refresh; var retryButton = DOT + classNames.retry; var dataSource = this.dataSource; this.element.on(MOUSEDOWN + NS, icons, proxy(this._toggleChildren, this)).on(CLICK + NS, retryButton, proxy(dataSource.fetch, dataSource)).on(CLICK + NS, '.k-button[data-command]', proxy(this._commandClick, this)); }, _commandByName: function (name) { var columns = this.columns; var toolbar = $.isArray(this.options.toolbar) ? this.options.toolbar : []; var i, j, commands, currentName; 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'); 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); } e.preventDefault(); } }, _ensureExpandableColumn: function () { if (this._autoExpandable) { delete this._autoExpandable.expandable; } var visibleColumns = grep(this.columns, not(is('hidden'))); var expandableColumns = grep(visibleColumns, is('expandable')); if (this.columns.length && !expandableColumns.length) { this._autoExpandable = visibleColumns[0]; visibleColumns[0].expandable = true; } }, _columns: function () { var columns = this.options.columns || []; this.columns = map(columns, function (column) { column = typeof column === 'string' ? { field: column } : column; return extend({ encoded: true }, column); }); var lockedColumns = this._lockedColumns(); if (lockedColumns.length > 0) { this._hasLockedColumns = true; this.columns = lockedColumns.concat(this._nonLockedColumns()); } this._ensureExpandableColumn(); this._columnTemplates(); this._columnAttributes(); }, _columnTemplates: function () { var idx, length, column; var columns = this.columns; for (idx = 0, length = columns.length; idx < length; idx++) { column = columns[idx]; if (column.template) { column.template = kendo.template(column.template); } 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 = this.columns; function convertStyle(attr) { var properties, i, declaration; if (attr && attr.style) { properties = attr.style.split(';'); attr.style = {}; for (i = 0; i < properties.length; i++) { declaration = properties[i].split(':'); var name = $.trim(declaration[0]); if (name) { attr.style[$.camelCase(name)] = $.trim(declaration[1]); } } } } for (idx = 0, length = columns.length; idx < length; idx++) { convertStyle(columns[idx].attributes); convertStyle(columns[idx].headerAttributes); } }, _layout: function () { var columns = this.columns; var element = this.element; var layout = ''; this.wrapper = element.addClass(classNames.wrapper); layout = '
'; if (this._hasLockedColumns) { layout += '
' + '' + '' + '' + '
' + '
'; } layout += '
' + '' + '' + '' + '
' + '
' + '
'; if (this._hasLockedColumns) { layout += '
' + '' + '' + '' + '
' + '
'; } layout += '
' + '' + '' + '' + '
' + '
'; if (!this.options.scrollable) { layout = '' + '' + '' + '' + '
'; } if (this.options.toolbar) { layout = '
' + layout; } element.append(kendo.template(layout)(classNames) + '
'); 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'); 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(); } this._initVirtualTrees(); this._renderCols(); this._renderHeader(); this.angular('compile', function () { return { elements: header.find('th.k-header').get(), data: map(columns, function (col) { return { column: col }; }) }; }); }, _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]); } }, _toolbar: function () { var options = this.options.toolbar; var toolbar = this.toolbar; if (!options) { return; } if ($.isArray(options)) { var buttons = this._buildCommands(options); new kendoDom.Tree(toolbar[0]).render(buttons); } else { toolbar.append(kendo.template(options)({})); } this.angular('compile', function () { return { elements: toolbar.get() }; }); }, _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')); }, _flushCache: function () { if (this.options.$angular && this._templateColumns().length) { this._contentTree.render([]); if (this._hasLockedColumns) { this._lockedContentTree.render([]); } } }, _render: function (options) { options = options || {}; var messages = this.options.messages; var data = this.dataSource.rootNodes(); var selected = this.select().map(function (_, row) { return $(row).attr(kendo.attr('uid')); }); this._absoluteIndex = 0; this._angularItems('cleanup'); this._angularFooters('cleanup'); this._flushCache(); if (options.error) { this._showStatus(kendo.template('#: messages.requestFailed # ' + '')({ buttonClass: [ classNames.button, classNames.retry ].join(' '), messages: messages })); } else if (!data.length) { this._showStatus(kendo.htmlEncode(messages.noRows)); } else { this._hideStatus(); this._contentTree.render(this._trs({ columns: this._nonLockedColumns(), aggregates: options.aggregates, selected: selected, data: data, visible: true, level: 0 })); if (this._hasLockedColumns) { this._absoluteIndex = 0; this._lockedContentTree.render(this._trs({ columns: this._lockedColumns(), aggregates: options.aggregates, selected: selected, data: data, visible: true, level: 0 })); } } if (this._touchScroller) { this._touchScroller.contentResized(); } this._muteAngularRebind(function () { this._angularItems('compile'); this._angularFooters('compile'); }); this._adjustRowsHeight(); }, _adjustRowsHeight: function () { if (!this._hasLockedColumns) { return; } var table = this.table; var lockedTable = this.lockedTable; var rows = table[0].rows; var length = rows.length; var idx; var lockedRows = lockedTable[0].rows; var containers = table.add(lockedTable); var containersLength = containers.length; var heights = []; var lockedHeaderRows = this.lockedHeader.find('tr'); var headerRows = this.thead.find('tr'); lockedHeaderRows.add(headerRows).height('auto').height(Math.max(lockedHeaderRows.height(), headerRows.height())); for (idx = 0; idx < length; idx++) { if (!lockedRows[idx]) { break; } if (rows[idx].style.height) { rows[idx].style.height = lockedRows[idx].style.height = ''; } var offsetHeight1 = rows[idx].offsetHeight; var offsetHeight2 = lockedRows[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 = lockedRows[idx].style.height = heights[idx] + 1 + 'px'; } } for (idx = 0; idx < containersLength; idx++) { containers[idx].style.display = ''; } }, _ths: function (columns) { var ths = []; var column, title, children, cellClasses, attr, headerContent; for (var i = 0, length = columns.length; i < length; i++) { column = columns[i]; children = []; cellClasses = [classNames.header]; if (column.headerTemplate) { title = column.headerTemplate({}); } else { title = column.title || column.field || ''; } if (column.headerTemplate) { headerContent = kendoHtmlElement(title); } else { headerContent = kendoTextElement(title); } if (column.sortable) { children.push(kendoDomElement('a', { href: '#', className: classNames.link }, [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' }; attr = extend(true, {}, attr, column.headerAttributes); 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' }; } cols.push(kendoDomElement('col', attr)); } return cols; }, _renderCols: function () { var columns = this._nonLockedColumns(); this._headerColsTree.render(this._cols(columns)); if (this.options.scrollable) { this._contentColsTree.render(this._cols(columns)); } if (this._hasLockedColumns) { columns = this._lockedColumns(); this._lockedHeaderColsTree.render(this._cols(columns)); this._lockedContentColsTree.render(this._cols(columns)); } }, _renderHeader: function () { var columns = this._nonLockedColumns(); this._headerTree.render([kendoDomElement('tr', { 'role': 'row' }, this._ths(columns))]); if (this._hasLockedColumns) { columns = this._lockedColumns(); this._lockedHeaderTree.render([kendoDomElement('tr', { 'role': 'row' }, this._ths(columns))]); this._applyLockedContainersWidth(); } }, _applyLockedContainersWidth: function () { if (!this._hasLockedColumns) { return; } var lockedWidth = columnsWidth(this.lockedHeader.find('>table>colgroup>col')); var headerTable = this.thead.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 - 2; this.content.width(width); headerTable.parent().width(width - scrollbar); }, _trs: function (options) { var model, attr, className, hasChildren, childNodes, i, length; var rows = []; var level = options.level; var data = options.data; var dataSource = this.dataSource; var aggregates = dataSource.aggregates() || {}; var columns = options.columns; for (i = 0, length = data.length; i < length; i++) { className = []; model = data[i]; childNodes = model.loaded() && dataSource.childNodes(model); hasChildren = childNodes && childNodes.length; attr = { 'role': 'row' }; attr[kendo.attr('uid')] = model.uid; if (hasChildren) { attr['aria-expanded'] = !!model.expanded; } if (options.visible) { 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 (hasChildren) { className.push(classNames.group); } if (model._edit) { className.push('k-grid-edit-row'); } attr.className = className.join(' '); rows.push(this._tds({ model: model, attr: attr, level: level }, columns, proxy(this._td, this))); if (hasChildren) { rows = rows.concat(this._trs({ columns: columns, aggregates: aggregates, selected: options.selected, visible: options.visible && !!model.expanded, data: childNodes, level: level + 1 })); } } if (this._hasFooterTemplate()) { attr = { className: classNames.footerTemplate, 'data-parentId': model.parentId }; if (!options.visible) { attr.style = { display: 'none' }; } rows.push(this._tds({ model: aggregates[model.parentId], attr: attr, level: level }, columns, this._footerTd)); } return rows; }, _footerTd: function (options) { var content = []; var column = options.column; var template = options.column.footerTemplate || $.noop; var aggregates = options.model[column.field] || {}; var attr = { 'role': 'gridcell', 'style': column.hidden === true ? { 'display': 'none' } : {} }; if (column.expandable) { content = content.concat(createPlaceholders({ level: options.level + 1, className: classNames.iconPlaceHolder })); } if (column.attributes) { extend(attr, column.attributes); } content.push(kendoHtmlElement(template(aggregates) || '')); return kendoDomElement('td', attr, content); }, _hasFooterTemplate: function () { return !!grep(this.columns, function (c) { return c.footerTemplate; }).length; }, _tds: function (options, columns, renderer) { var children = []; var column; for (var i = 0, l = columns.length; i < l; i++) { column = columns[i]; children.push(renderer({ model: options.model, column: column, level: options.level })); } return kendoDomElement('tr', options.attr, children); }, _td: function (options) { var children = []; var model = options.model; var column = options.column; var iconClass; var attr = { 'role': 'gridcell', 'style': column.hidden === true ? { 'display': 'none' } : {} }; if (model._edit && column.field && model.editable(column.field)) { attr[kendo.attr('container-for')] = column.field; } else { if (column.expandable) { children = createPlaceholders({ level: options.level, className: classNames.iconPlaceHolder }); iconClass = [classNames.icon]; if (model.hasChildren) { iconClass.push(model.expanded ? classNames.iconCollapse : classNames.iconExpand); } else { iconClass.push(classNames.iconHidden); } if (model._error) { iconClass.push(classNames.refresh); } else if (!model.loaded() && model.expanded) { iconClass.push(classNames.loading); } children.push(kendoDomElement('span', { className: iconClass.join(' ') })); attr.style['white-space'] = 'nowrap'; } if (column.attributes) { extend(true, attr, column.attributes); } if (column.command) { if (model._edit) { children = this._buildCommands([ 'update', 'canceledit' ]); } else { children = this._buildCommands(column.command); } } else { children.push(this._cellContent(column, model)); } } return kendoDomElement('td', attr, children); }, _cellContent: function (column, model) { var value; if (column.template) { value = column.template(model); } else if (column.field) { value = model.get(column.field); if (value !== null && column.format) { value = kendo.format(column.format, value); } } if (value === null || typeof value == 'undefined') { value = ''; } if (column.template || !column.encoded) { return kendoHtmlElement(value); } else { return kendoTextElement(value); } }, _buildCommands: function (commands) { var i, result = []; for (i = 0; i < commands.length; i++) { result.push(this._button(commands[i])); } return result; }, _button: function (command) { var name = (command.name || command).toLowerCase(); var text = this.options.messages.commands[name]; var icon = []; command = extend({}, defaultCommands[name], { text: text }, command); if (command.imageClass) { icon.push(kendoDomElement('span', { className: [ 'k-icon', command.imageClass ].join(' ') })); } return kendoDomElement('button', { 'type': 'button', 'data-command': name, className: [ 'k-button', 'k-button-icontext', command.className ].join(' ') }, icon.concat([kendoTextElement(command.text || command.name)])); }, _positionResizeHandle: function (e) { var th = $(e.currentTarget); var resizeHandle = this.resizeHandle; var position = th.position(); var left = position.left; var cellWidth = th.outerWidth(); var container = th.closest('div'); var clientX = e.clientX + $(window).scrollLeft(); var indicatorWidth = this.options.columnResizeHandleWidth || 3; left += container.scrollLeft(); if (!resizeHandle) { resizeHandle = this.resizeHandle = $('
'); } var cellOffset = th.offset().left + cellWidth; var show = clientX > cellOffset - indicatorWidth && clientX < cellOffset + indicatorWidth; if (!show) { resizeHandle.hide(); return; } container.append(resizeHandle); resizeHandle.show().css({ top: position.top, left: left + cellWidth - indicatorWidth - 1, height: th.outerHeight(), 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, browser = kendo.support.browser, 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 = th.outerWidth(); col.width(''); tables.css('table-layout', 'fixed'); col.width('auto'); tables.addClass('k-autofitting'); tables.css('table-layout', ''); var newColumnWidth = Math.ceil(Math.max(th.outerWidth(), contentTable.find('tr').eq(0).children('td:visible').eq(index).outerWidth(), footerTable.find('tr').eq(0).children('td:visible').eq(index).outerWidth())); 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'; }); } } if (browser.msie && browser.version == 8) { tables.css('display', 'inline-table'); setTimeout(function () { tables.css('display', 'table'); }, 1); } tables.removeClass('k-autofitting'); that.trigger(COLUMNRESIZE, { column: 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(content.height() - scrollbar); }, _syncLockedContentHeight: function () { if (this.lockedTable) { if (!this._touchScroller) { this._adjustLockedHorizontalScrollBar(); } this._adjustRowsHeight(this.table, this.lockedTable); } }, _syncLockedHeaderHeight: function () { if (this.lockedHeader) { var lockedTable = this.lockedHeader.children('table'); var table = this.thead.parent(); this._adjustRowsHeight(lockedTable, table); syncTableHeight(lockedTable, table); } }, _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, 'th', $.proxy(this._positionResizeHandle, this)); this.resizable = new kendo.ui.Resizable(this.wrapper, { handle: '.k-resize-handle', start: function (e) { var th = $(e.currentTarget).data('th'); var colSelector = 'col:eq(' + $.inArray(th[0], th.parent().children().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(colSelector).add(header.find(colSelector)); this.th = th; this.startLocation = e.x.location; this.columnWidth = th.outerWidth(); this.table = this.col.closest('table'); this.totalWidth = this.table.width(); }, resize: function (e) { var minColumnWidth = 11; var delta = e.x.location - this.startLocation; 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(treelist.columns, function (c) { return c.field == field; }); var newWidth = Math.floor(this.th.outerWidth()); column[0].width = newWidth; treelist._resize(); treelist._adjustRowsHeight(); treelist.trigger(COLUMNRESIZE, { column: column, oldWidth: this.columnWidth, newWidth: newWidth }); this.table = this.col = this.th = null; } }); }, _sortable: function () { var columns = this.columns; var column; var sortableInstance; var cells = $(this.lockedHeader).add(this.thead).find('th'); var cell, idx, length; var fieldAttr = kendo.attr('field'); var sortable = this.options.sortable; if (!sortable) { return; } for (idx = 0, length = cells.length; idx < length; idx++) { column = columns[idx]; if (column.sortable !== false && !column.command && column.field) { cell = cells.eq(idx); sortableInstance = cell.data('kendoColumnSorter'); if (sortableInstance) { sortableInstance.destroy(); } cell.attr(fieldAttr, column.field).kendoColumnSorter(extend({}, sortable, column.sortable, { dataSource: this.dataSource })); } } }, _filterable: function () { var cells = $(this.lockedHeader).add(this.thead).find('th'); var filterable = this.options.filterable; var idx, length, column, cell, filterMenuInstance; if (!filterable || this.options.columnMenu) { return; } var filterInit = proxy(function (e) { this.trigger(FILTERMENUINIT, { field: e.field, container: e.container }); }, this); for (idx = 0, length = cells.length; idx < length; idx++) { column = this.columns[idx]; cell = cells.eq(idx); filterMenuInstance = cell.data('kendoFilterMenu'); if (filterMenuInstance) { filterMenuInstance.destroy(); } if (column.command || column.filterable === false) { continue; } cell.kendoFilterMenu(extend(true, {}, filterable, column.filterable, { dataSource: this.dataSource, init: filterInit })); } }, _change: function () { this.trigger(CHANGE); }, _selectable: function () { var selectable = this.options.selectable; var filter; var element = this.table; var useAllItems; 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: filter, aria: true, multiple: selectable.multiple, change: proxy(this._change, this), useAllItems: useAllItems, continuousItems: proxy(this._continuousItems, this, filter, selectable.cell), relatedTarget: !selectable.cell && this._hasLockedColumns ? proxy(this._selectableTarget, this) : undefined }); } }, _continuousItems: function (filter, cell) { if (!this.lockedContent) { return; } var lockedItems = $(filter, this.lockedTable); var nonLockedItems = $(filter, this.table); var columns = cell ? this._lockedColumns().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 selectable = this.selectable; if (!selectable) { return $(); } if (typeof value !== 'undefined') { if (!selectable.options.multiple) { selectable.clear(); value = value.first(); } if (this._hasLockedColumns) { value = value.add($.map(value, proxy(this._relatedRow, this))); } } return selectable.value(value); }, clearSelection: function () { var selected = this.select(); if (selected.length) { this.selectable.clear(); this.trigger(CHANGE); } }, _dataSource: function (dataSource) { var ds = this.dataSource; if (ds) { ds.unbind(CHANGE, this._refreshHandler); ds.unbind(ERROR, this._errorHandler); ds.unbind(PROGRESS, this._progressHandler); } this._refreshHandler = proxy(this.refresh, this); this._errorHandler = proxy(this._error, this); this._progressHandler = proxy(this._progress, this); ds = this.dataSource = TreeListDataSource.create(dataSource); ds.bind(CHANGE, this._refreshHandler); ds.bind(ERROR, this._errorHandler); ds.bind(PROGRESS, this._progressHandler); }, setDataSource: function (dataSource) { this._dataSource(dataSource); this._sortable(); this._filterable(); this._contentTree.render([]); if (this.options.autoBind) { this.dataSource.fetch(); } }, dataItem: function (element) { var row = $(element).closest('tr'); var model = this.dataSource.getByUid(row.attr(kendo.attr('uid'))); return model; }, editRow: function (row) { var model; if (typeof row === STRING) { row = this.tbody.find(row); } model = this.dataItem(row); if (!model) { return; } if (this._editMode() != 'popup') { model._edit = true; } this._cancelEditor(); this._render(); this._createEditor(model); this.trigger(EDIT, { container: this.editor.wrapper, model: model }); }, _cancelEdit: function (e) { e = extend(e, { container: this.editor.wrapper, model: this.editor.model }); if (this.trigger(CANCEL, e)) { return; } this.cancelRow(); }, cancelRow: function () { this._cancelEditor(); this._render(); }, saveRow: function () { var editor = this.editor; var args; if (!editor) { return; } args = { model: editor.model, container: editor.wrapper }; if (editor.end() && !this.trigger(SAVE, args)) { this.dataSource.sync(); } }, addRow: function (parent) { var editor = this.editor; var index = 0; var model = {}; if (editor && !editor.end()) { return; } if (parent) { if (!(parent instanceof TreeListModel)) { parent = this.dataItem(parent); } model[parent.parentIdField] = parent.id; index = this.dataSource.indexOf(parent) + 1; parent.set('expanded', true); this.dataSource.load(parent).then(proxy(this._insertAt, this, model, index)); return; } this._insertAt(model, index); }, _insertAt: function (model, index) { model = this.dataSource.insert(index, model); var row = this.itemFor(model); this.editRow(row); }, removeRow: function (row) { var model = this.dataItem(row); var args = { model: model, row: row }; if (model && !this.trigger(REMOVE, args)) { this.dataSource.remove(model); this.dataSource.sync(); } }, _cancelEditor: function () { var model; var editor = this.editor; if (editor) { model = editor.model; this._destroyEditor(); this.dataSource.cancelChanges(model); model._edit = false; } }, _destroyEditor: function () { if (!this.editor) { return; } this.editor.close(); this.editor = null; }, _createEditor: function (model) { var row = this.itemFor(model); row = row.add(this._relatedRow(row)); var mode = this._editMode(); var options = { columns: this.columns, model: model, target: this, clearContainer: false, template: this.options.editable.template }; if (mode == 'inline') { this.editor = new Editor(row, options); } else { extend(options, { window: this.options.editable.window, commandRenderer: proxy(function () { return this._buildCommands([ 'update', 'canceledit' ]); }, this), fieldRenderer: this._cellContent, save: proxy(this.saveRow, this), cancel: proxy(this._cancelEdit, this), appendTo: this.wrapper }); this.editor = new PopupEditor(row, options); } }, _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(); }, 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._ensureExpandableColumn(); this._renderCols(); this._renderHeader(); this._render(); this._adjustTablesWidth(); this.trigger(hidden ? COLUMNHIDE : COLUMNSHOW, { column: column }); if (!hidden && !column.width) { this.table.add(this.thead.closest('table')).width(''); } }, _findColumn: function (column) { if (typeof column == 'number') { column = this.columns[column]; } else if (isPlainObject(column)) { column = grep(this.columns, function (item) { return item === column; })[0]; } else { column = grep(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:first ' : 'table:first>.k-grid-header ') + HEADERCELLS; var that = this; this._draggableInstance = new ui.Draggable(this.wrapper, { group: kendo.guid(), filter: selector, hint: function (target) { return $('
').css({ width: target.width(), paddingLeft: target.css('paddingLeft'), paddingRight: target.css('paddingRight'), lineHeight: target.height() + 'px', paddingTop: target.css('paddingTop'), paddingBottom: target.css('paddingBottom') }).html(target.attr(kendo.attr('title')) || target.attr(kendo.attr('field')) || target.text()).prepend(''); } }); this.reorderable = new ui.Reorderable(this.wrapper, { draggable: this._draggableInstance, dragOverContainers: proxy(this._allowDragOverContainers, this), inSameContainer: function (e) { return $(e.source).parent()[0] === $(e.target).parent()[0]; }, change: function (e) { var newIndex = e.newIndex; var oldIndex = e.oldIndex; var before = e.position === 'before'; var column = that.columns[oldIndex]; that.trigger(COLUMNREORDER, { newIndex: newIndex, oldIndex: oldIndex, column: column }); that.reorderColumn(newIndex, column, before); } }); }, _allowDragOverContainers: function (index) { return this.columns[index].lockable !== false; }, reorderColumn: function (destIndex, column, before) { var lockChanged; var columns = this.columns; var sourceIndex = inArray(column, columns); var destColumn = columns[destIndex]; var isLocked = !!destColumn.locked; var nonLockedColumnsLength = this._nonLockedColumns().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; } 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._renderCols(); var ths = $(this.lockedHeader).add(this.thead).find('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, this._lockedColumns().length); this._headerTree.children[0].children = dom; } this._applyLockedContainersWidth(); this.refresh(); if (!lockChanged) { return; } if (isLocked) { this.trigger(COLUMNLOCK, { column: column }); } else { this.trigger(COLUMNUNLOCK, { column: 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 = this._lockedColumns().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 = this._lockedColumns().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 = proxy(this._columnMenuInit, this); var lockedColumnsLength = this._lockedColumns().length; 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: sortable, filterable: filterable, messages: columnMenu.messages, owner: this, closeCallback: $.noop, init: initHandler, pane: this.pane, lockedColumns: column.lockable !== false && lockedColumnsLength > 0 }; if (options.$angular) { menuOptions.$angular = options.$angular; } ths.eq(i).kendoColumnMenu(menuOptions); } }, _columnMenuInit: function (e) { this.trigger(COLUMNMENUINIT, { field: e.field, container: e.container }); } }); if (kendo.ExcelMixin) { kendo.ExcelMixin.extend(TreeList.prototype); } if (kendo.PDFMixin) { kendo.PDFMixin.extend(TreeList.prototype); TreeList.fn._drawPDF = function (progress) { var promise = new $.Deferred(); this._drawPDFShadow({ width: this.wrapper.width() }, { avoidLinks: this.options.pdf.avoidLinks }).done(function (group) { var args = { page: group, pageNumber: 1, progress: 1, totalPages: 1 }; progress.notify(args); promise.resolve(args.page); }).fail(function (err) { promise.reject(err); }); return promise; }; } extend(true, kendo.data, { TreeListDataSource: TreeListDataSource, TreeListModel: TreeListModel }); extend(true, kendo.ui, { TreeList: TreeList }); ui.plugin(TreeList); }(window.kendo.jQuery)); return window.kendo; }, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) { (a3 || a2)(); }));