diff options
Diffstat (limited to 'js/dojo/dojox/grid/LazyTreeGrid.js')
| -rw-r--r-- | js/dojo/dojox/grid/LazyTreeGrid.js | 837 |
1 files changed, 837 insertions, 0 deletions
diff --git a/js/dojo/dojox/grid/LazyTreeGrid.js b/js/dojo/dojox/grid/LazyTreeGrid.js new file mode 100644 index 0000000..3ad3030 --- /dev/null +++ b/js/dojo/dojox/grid/LazyTreeGrid.js @@ -0,0 +1,837 @@ +//>>built +require({cache:{ +'url:dojox/grid/resources/Expando.html':"<div class=\"dojoxGridExpando\"\n\t><div class=\"dojoxGridExpandoNode\" dojoAttachEvent=\"onclick:onToggle\"\n\t\t><div class=\"dojoxGridExpandoNodeInner\" dojoAttachPoint=\"expandoInner\"></div\n\t></div\n></div>\n"}}); +define("dojox/grid/LazyTreeGrid", [ + "dojo/_base/kernel", + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/_base/event", + "dojo/_base/array", + "dojo/query", + "dojo/parser", + "dojo/dom-construct", + "dojo/dom-class", + "dojo/dom-style", + "dojo/dom-geometry", + "dojo/dom", + "dojo/keys", + "dojo/text!./resources/Expando.html", + "dijit/_Widget", + "dijit/_TemplatedMixin", + "./TreeGrid", + "./_Builder", + "./_View", + "./_Layout", + "./cells/tree", + "./_RowManager", + "./_FocusManager", + "./_EditManager", + "./DataSelection", + "./util" +], function(dojo, declare, lang, event, array, query, parser, domConstruct, + domClass, domStyle, domGeometry, dom, keys, template, _widget, _templatedMixin, + TreeGrid, _Builder, _View, _Layout, TreeCell, _RowManager, _FocusManager, _EditManager, DataSelection, util){ + +var _LazyExpando = declare("dojox.grid._LazyExpando", [_widget, _templatedMixin], { + grid: null, + view: null, + rowIdx: -1, + cellIdx: -1, + level: 0, + itemId: "", + templateString: template, + onToggle: function(evt){ + // summary: + // The onclick handler of expando, expand/collapse a tree node if has children. + if(this.grid._treeCache.items[this.rowIdx]){ + this.grid.focus.setFocusIndex(this.rowIdx, this.cellIdx); + this.setOpen(!this.grid._treeCache.items[this.rowIdx].opened); + try{ + event.stop(evt); + }catch(e){} + } + }, + setOpen: function(open){ + // summary: + // expand/collapse the row where the expando is in. + var g = this.grid, + item = g._by_idx[this.rowIdx].item; + if(item && g.treeModel.mayHaveChildren(item) && !g._loading && g._treeCache.items[this.rowIdx].opened !== open){ + g._treeCache.items[this.rowIdx].opened = open; + g.expandoFetch(this.rowIdx, open); + this._updateOpenState(item); + } + }, + _updateOpenState: function(item){ + var g = this.grid, state; + if(item && g.treeModel.mayHaveChildren(item)){ + state = g._treeCache.items[this.rowIdx].opened; + this.expandoInner.innerHTML = state ? "-" : "+"; + domClass.toggle(this.domNode, "dojoxGridExpandoOpened", state); + this.domNode.parentNode.setAttribute("aria-expanded", state); + }else{ + domClass.remove(this.domNode, "dojoxGridExpandoOpened"); + } + }, + setRowNode: function(rowIdx, rowNode, view){ + if(this.cellIdx < 0 || !this.itemId){ + return false; + } + this.view = view; + this.grid = view.grid; + this.rowIdx = rowIdx; + var marginPos = this.grid.isLeftToRight() ? "marginLeft" : "marginRight"; + domStyle.set(this.domNode.parentNode, marginPos, (this.level * 1.125) + "em"); + this._updateOpenState(this.grid._by_idx[this.rowIdx].item); + return true; + } +}); + +var _TreeGridContentBuilder = declare("dojox.grid._TreeGridContentBuilder", _Builder._ContentBuilder, { + generateHtml: function(inDataIndex, rowIndex){ + var html = this.getTableArray(), + grid = this.grid, + v = this.view, + cells = v.structure.cells, + item = grid.getItem(rowIndex), + level = 0, + toggleClass = "", + treePath = grid._treeCache.items[rowIndex] ? grid._treeCache.items[rowIndex].treePath : null; + util.fire(this.view, "onBeforeRow", [rowIndex, cells]); + if(item && lang.isArray(treePath)){ + level = treePath.length; + toggleClass = grid.treeModel.mayHaveChildren(item) ? "" : "dojoxGridNoChildren"; + } + var i = 0, j = 0, row, cell, + mergedCells, totalWidth = 0, totalWidthes = []; + for(; row = cells[j]; j++){ + if(row.hidden || row.header){ + continue; + } + html.push('<tr class="' + toggleClass + '">'); + // cell merge + mergedCells = this._getColSpans(level); + if(mergedCells){ + array.forEach(mergedCells, function(c){ + for(i = 0; cell = row[i]; i++){ + if(i >= c.start && i <= c.end){ + totalWidth += this._getCellWidth(row, i); + } + } + totalWidthes.push(totalWidth); + totalWidth = 0; + }, this); + } + var m, cc, cs, pbm, k = 0; + for(i = 0; cell = row[i]; i++){ + m = cell.markup; + cc = cell.customClasses = []; + cs = cell.customStyles = []; + if(mergedCells && mergedCells[k] && (i >= mergedCells[k].start && i <= mergedCells[k].end)){ + var primaryIdx = mergedCells[k].primary || mergedCells[k].start; + if(i == primaryIdx){ + m[5] = cell.formatAtLevel(item, level, rowIndex); + m[1] = cc.join(' '); + pbm = domGeometry.getMarginBox(cell.getHeaderNode()).w - domGeometry.getContentBox(cell.getHeaderNode()).w; + cs = cell.customStyles = ['width:' + (totalWidthes[k] - pbm) + "px"]; + m[3] = cs.join(';'); + html.push.apply(html, m); + }else if(i == mergedCells[k].end){ + k++; + continue; + }else{ + continue; + } + }else{ + m[5] = cell.formatAtLevel(item, level, rowIndex); + m[1] = cc.join(' '); + m[3] = cs.join(';'); + html.push.apply(html, m); + } + } + html.push('</tr>'); + } + html.push('</table>'); + return html.join(''); // String + }, + _getColSpans: function(level){ + var colSpans = this.grid.colSpans; + return colSpans && colSpans[level] ? colSpans[level] : null; + }, + _getCellWidth: function(cells, colIndex){ + var curCell = cells[colIndex], node = curCell.getHeaderNode(); + if(curCell.hidden){ + return 0; + } + if(colIndex == cells.length - 1 || array.every(cells.slice(colIndex + 1), function(cell){ + return cell.hidden; + })){ + var headerNodePos = domGeometry.position(cells[colIndex].view.headerContentNode.firstChild); + return headerNodePos.x + headerNodePos.w - domGeometry.position(node).x; + }else{ + var nextCell; + do{ + nextCell = cells[++colIndex]; + }while(nextCell.hidden); + return domGeometry.position(nextCell.getHeaderNode()).x - domGeometry.position(node).x; + } + } +}); + +declare("dojox.grid._TreeGridView", _View, { + _contentBuilderClass: _TreeGridContentBuilder, + postCreate: function(){ + this.inherited(arguments); + this._expandos = {}; + this.connect(this.grid, '_onCleanupExpandoCache', '_cleanupExpandoCache'); + }, + destroy: function(){ + this._cleanupExpandoCache(); + this.inherited(arguments); + }, + _cleanupExpandoCache: function(identity){ + if(identity && this._expandos[identity]){ + this._expandos[identity].destroy(); + delete this._expandos[identity]; + }else{ + var i; + for(i in this._expandos){ + this._expandos[i].destroy(); + } + this._expandos = {}; + } + }, + onAfterRow: function(rowIndex, cells, rowNode){ + query("span.dojoxGridExpando", rowNode).forEach(function(n){ + if(n && n.parentNode){ + var idty, expando, _byIdx = this.grid._by_idx; + if(_byIdx && _byIdx[rowIndex] && _byIdx[rowIndex].idty){ + idty = _byIdx[rowIndex].idty; + expando = this._expandos[idty]; + } + if(expando){ + domConstruct.place(expando.domNode, n, "replace"); + expando.itemId = n.getAttribute("itemId"); + expando.cellIdx = parseInt(n.getAttribute("cellIdx"), 10); + if(isNaN(expando.cellIdx)){ + expando.cellIdx = -1; + } + }else{ + expando = parser.parse(n.parentNode)[0]; + if(idty){ + this._expandos[idty] = expando; + } + } + if(!expando.setRowNode(rowIndex, rowNode, this)){ + expando.domNode.parentNode.removeChild(expando.domNode); + } + domConstruct.destroy(n); + } + }, this); + this.inherited(arguments); + }, + updateRow: function(rowIndex){ + var grid = this.grid, item; + if(grid.keepSelection){ + item = grid.getItem(rowIndex); + if(item){ + grid.selection.preserver._reSelectById(item, rowIndex); + } + } + this.inherited(arguments); + } +}); + +var LazyTreeCell = lang.mixin(lang.clone(TreeCell), { + formatAtLevel: function(item, level, rowIndex){ + if(!item){ + return this.formatIndexes(rowIndex, item, level); + } + var result = "", ret = "", content; + if(this.isCollapsable && this.grid.store.isItem(item)){ + ret = '<span ' + dojo._scopeName + 'Type="dojox.grid._LazyExpando" level="' + level + '" class="dojoxGridExpando"' + + ' itemId="' + this.grid.store.getIdentity(item) + '" cellIdx="' + this.index + '"></span>'; + } + content = this.formatIndexes(rowIndex, item, level); + result = ret !== "" ? '<div>' + ret + content + '</div>' : content; + return result; + }, + formatIndexes: function(rowIndex, item, level){ + var info = this.grid.edit.info, + d = this.get ? this.get(rowIndex, item) : (this.value || this.defaultValue); + if(this.editable && (this.alwaysEditing || (info.rowIndex === rowIndex && info.cell === this))){ + return this.formatEditing(d, rowIndex); + }else{ + return this._defaultFormat(d, [d, rowIndex, level, this]); + } + } +}); + +var _LazyTreeLayout = declare("dojox.grid._LazyTreeLayout", _Layout, { + // summary: + // Override the dojox.grid._TreeLayout to modify the _TreeGridView and cell formatter + setStructure: function(structure){ + var g = this.grid, s = structure; + if(g && !array.every(s, function(i){ + return !!i.cells; + })){ + s = arguments[0] = [{cells:[s]}];//intentionally change arguments[0] + } + if(s.length === 1 && s[0].cells.length === 1){ + s[0].type = "dojox.grid._TreeGridView"; + this._isCollapsable = true; + s[0].cells[0][this.grid.expandoCell].isCollapsable = true; + } + this.inherited(arguments); + }, + addCellDef: function(rowIndex, cellIndex, def){ + var obj = this.inherited(arguments); + return lang.mixin(obj, LazyTreeCell); + } +}); + +var _LazyTreeGridCache = declare("dojox.grid._LazyTreeGridCache", null, { + // summary: + // An internal object used to cache the tree path and open state of each item. + // The form of the cache items would be an object array: + // [{opened: true/false, treePath: [level0 parent id, level1 parent id, ...]}] + // example: + // | [{opened: true, treePath: []}, + // | {opened: false, treePath: ["root0"]}, + // | {opened: false, treePath: ["root0"]}, + // | {opened: false, treePath: []}, + // | ...] + constructor: function(){ + this.items = []; + }, + getSiblingIndex: function(rowIndex, treePath){ + var i = rowIndex - 1, indexCount = 0, tp; + for(; i >=0; i--){ + tp = this.items[i] ? this.items[i].treePath : []; + if(tp.join('/') === treePath.join('/')){ + indexCount++; + }else if(tp.length < treePath.length){ + break; + } + } + return indexCount; + }, + removeChildren: function(rowIndex){ + // find next sibling index + var i = rowIndex + 1, count, tp, + treePath = this.items[rowIndex] ? this.items[rowIndex].treePath : []; + for(; i < this.items.length; i++){ + tp = this.items[i] ? this.items[i].treePath : []; + if(tp.join('/') === treePath.join('/') || tp.length <= treePath.length){ + break; + } + } + count = i - (rowIndex + 1); + this.items.splice(rowIndex + 1, count); + return count; + } +}); + +var LazyTreeGrid = declare("dojox.grid.LazyTreeGrid", TreeGrid, { + // summary: + // An enhanced TreeGrid widget which supports lazy-loading for nested children items + // + // description: + // LazyTreeGrid inherits from dojo.grid.TreeGrid and applies virtual scrolling mechanism + // to nested children rows so that it's possible to deal with complex tree structure data set + // with nested and huge children rows. It's also compatible with dijit.tree.ForestStoreModel + // + // Most methods and properties pertaining to dojox.grid.DataGrid + // and dojox.grid.TreeGrid also apply here + // + // LazyTreeGrid does not support summary row/items aggregate due to the lazy-loading rationale. + _layoutClass: _LazyTreeLayout, + _size: 0, + // treeModel: dijit.tree.ForestStoreModel | dojox.grid.LazyTreeGridStoreModel + // A tree store model object. + treeModel: null, + // defaultState: Object + // Used to restore the state of LazyTreeGrid. + // This object should ONLY be obtained from `LazyTreeGrid.getState()`. + defaultState: null, + // colSpans: Object + // a json object that defines column span of each level rows + // attributes: + // 0/1/..: which level need to colspan + // start: start column index of colspan + // end: end column index of colspan + // primary: index of column which content will be displayed (default is value of start). + // example: + // | colSpans = { + // | 0: [ + // | {start: 0, end: 1, primary: 0}, + // | {start: 2, end: 4, primary: 3} + // | ], + // | 1: [ + // | {start: 0, end: 3, primary: 1} + // | ] + // | }; + colSpans: null, + + postCreate: function(){ + this._setState(); + this.inherited(arguments); + if(!this._treeCache){ + this._treeCache = new _LazyTreeGridCache(); + } + if(!this.treeModel || !(this.treeModel instanceof dijit.tree.ForestStoreModel)){ + throw new Error("dojox.grid.LazyTreeGrid: must be used with a treeModel which is an instance of dijit.tree.ForestStoreModel"); + } + domClass.add(this.domNode, "dojoxGridTreeModel"); + dom.setSelectable(this.domNode, this.selectable); + }, + createManagers: function(){ + this.rows = new _RowManager(this); + this.focus = new _FocusManager(this); + this.edit = new _EditManager(this); + }, + createSelection: function(){ + this.selection = new DataSelection(this); + }, + setModel: function(treeModel){ + if(!treeModel){ + return; + } + this._setModel(treeModel); + this._cleanup(); + this._refresh(true); + }, + setStore: function(store, query, queryOptions){ + if(!store){ + return; + } + this._setQuery(query, queryOptions); + this.treeModel.query = query; + this.treeModel.store = store; + this.treeModel.root.children = []; + this.setModel(this.treeModel); + }, + onSetState: function(){ + // summary: + // Event fired when a default state being set. + }, + _setState: function(){ + if(this.defaultState){ + this._treeCache = this.defaultState.cache; + this.sortInfo = this.defaultState.sortInfo || 0; + this.query = this.defaultState.query || this.query; + this._lastScrollTop = this.defaultState.scrollTop; + if(this.keepSelection){ + this.selection.preserver._selectedById = this.defaultState.selection; + }else{ + this.selection.selected = this.defaultState.selection || []; + } + this.onSetState(); + } + }, + getState: function(){ + // summary: + // Get the current state of LazyTreeGrid including expanding, sorting, selection and scroll top state. + var _this = this, + selection = this.keepSelection ? this.selection.preserver._selectedById : this.selection.selected; + return { + cache: lang.clone(_this._treeCache), + query: lang.clone(_this.query), + sortInfo: lang.clone(_this.sortInfo), + scrollTop: lang.clone(_this.scrollTop), + selection: lang.clone(selection) + }; + }, + _setQuery: function(query, queryOptions){ + this.inherited(arguments); + this.treeModel.query = query; + }, + filter: function(query, reRender){ + this._cleanup(); + this.inherited(arguments); + }, + destroy: function(){ + this._cleanup(); + this.inherited(arguments); + }, + expand: function(itemId){ + // summary: + // Expand the row with the given itemId. + // id: string? + this._fold(itemId, true); + }, + collapse: function(itemId){ + // summary: + // Collapse the row with the given itemId. + // id: string? + this._fold(itemId, false); + }, + refresh: function(keepState){ + // summary: + // Refresh, and persist the expand/collapse state when keepState equals true + // keepState: boolean + if(!keepState){ + this._cleanup(); + } + this._refresh(true); + }, + _cleanup: function(){ + this._treeCache.items = []; + this._onCleanupExpandoCache(); + }, + setSortIndex: function(inIndex, inAsc){ + // Need to clean up the cache before sorting + if(this.canSort(inIndex + 1)){ + this._cleanup(); + } + this.inherited(arguments); + }, + _refresh: function(isRender){ + this._clearData(); + this.updateRowCount(this._size); + this._fetch(0, true); + }, + render: function(){ + this.inherited(arguments); + this.setScrollTop(this.scrollTop); + }, + _onNew: function(item, parentInfo){ + var addingChild = parentInfo && this.store.isItem(parentInfo.item) && array.some(this.treeModel.childrenAttrs, function(c){ + return c === parentInfo.attribute; + }); + var items = this._treeCache.items, byIdx = this._by_idx; + if(!addingChild){ + items.push({opened: false, treePath: []}); + this._size += 1; + this.inherited(arguments); + }else{ + var parentItem = parentInfo.item, + parentIdty = this.store.getIdentity(parentItem), + rowIndex = -1, i = 0; + for(; i < byIdx.length; i++){ + if(parentIdty === byIdx[i].idty){ + rowIndex = i; + break; + } + } + if(rowIndex >= 0){ + if(items[rowIndex] && items[rowIndex].opened){ + var parentTreePath = items[rowIndex].treePath, pos = rowIndex + 1; + for(; pos < items.length; pos++){ + if(items[pos].treePath.length <= parentTreePath.length){ + break; + } + } + var treePath = parentTreePath.slice(); + treePath.push(parentIdty); + this._treeCache.items.splice(pos, 0, {opened: false, treePath: treePath}); + // update grid._by_idx + var idty = this.store.getIdentity(item); + this._by_idty[idty] = { idty: idty, item: item }; + byIdx.splice(pos, 0, this._by_idty[idty]); + // update grid + this._size += 1; + this.updateRowCount(this._size); + this._updateRenderedRows(pos); + }else{ + this.updateRow(rowIndex); + } + } + } + }, + _onDelete: function(item){ + var i = 0, rowIndex = -1, idty = this.store.getIdentity(item); + for(; i < this._by_idx.length; i++){ + if(idty === this._by_idx[i].idty){ + rowIndex = i; + break; + } + } + if(rowIndex >= 0){ + var items = this._treeCache.items, treePath = items[rowIndex] ? items[rowIndex].treePath : [], tp, count = 1; + i = rowIndex + 1; + for(; i < this._size; i++, count++){ + tp = items[i] ? items[i].treePath : []; + if(items[i].treePath.length <= treePath.length){ + break; + } + } + items.splice(rowIndex, count); + this._onCleanupExpandoCache(idty); + this._by_idx.splice(rowIndex, count); + this._size -= count; + this.updateRowCount(this._size); + this._updateRenderedRows(rowIndex); + } + }, + _onCleanupExpandoCache: function(identity){}, + _fetch: function(start, isRender){ + if(!this._loading){ + this._loading = true; + } + start = start || 0; + var count = this._size - start > 0 ? Math.min(this.rowsPerPage, this._size - start) : this.rowsPerPage; + var i = 0; + var fetchedItems = []; + this._reqQueueLen = 0; + for(; i < count; i++){ + if(this._by_idx[start + i]){ + fetchedItems.push(this._by_idx[start + i].item); + }else{ + break; + } + } + if(fetchedItems.length === count){ + this._reqQueueLen = 1; + this._onFetchBegin(this._size, {startRowIdx: start, count: count}); + this._onFetchComplete(fetchedItems, {startRowIdx: start, count: count}); + }else{ + var level, nextLevel, len = 1, items = this._treeCache.items, + treePath = items[start] ? items[start].treePath : []; + for(i = 1; i < count; i++){ + level = items[start + len - 1] ? items[start + len - 1].treePath.length : 0; + nextLevel = items[start + len] ? items[start + len].treePath.length : 0; + if(level !== nextLevel){ + this._reqQueueLen++; + this._fetchItems({startRowIdx: start, count: len, treePath: treePath}); + start = start + len; + len = 1; + treePath = items[start] ? items[start].treePath : 0; + }else{ + len++; + } + } + this._reqQueueLen++; + this._fetchItems({startRowIdx: start, count: len, treePath: treePath}); + } + }, + _fetchItems: function(req){ + if(this._pending_requests[req.startRowIdx]){ + return; + } + this.showMessage(this.loadingMessage); + this._pending_requests[req.startRowIdx] = true; + var onError = lang.hitch(this, '_onFetchError'), + start = this._treeCache.getSiblingIndex(req.startRowIdx, req.treePath); + if(req.treePath.length === 0){ + this.store.fetch({ + start: start, + startRowIdx: req.startRowIdx, + treePath: req.treePath, + count: req.count, + query: this.query, + sort: this.getSortProps(), + queryOptions: this.queryOptions, + onBegin: lang.hitch(this, '_onFetchBegin'), + onComplete: lang.hitch(this, '_onFetchComplete'), + onError: lang.hitch(this, '_onFetchError') + }); + }else{ + var parentId = req.treePath[req.treePath.length - 1], parentItem; + var queryObj = { + start: start, + startRowIdx: req.startRowIdx, + treePath: req.treePath, + count: req.count, + parentId: parentId, + sort: this.getSortProps() + }; + var _this = this; + var onComplete = function(){ + var f = lang.hitch(_this, '_onFetchComplete'); + if(arguments.length == 1){ + f.apply(_this, [arguments[0], queryObj]); + }else{ + f.apply(_this, arguments); + } + }; + if(this._by_idty[parentId]){ + parentItem = this._by_idty[parentId].item; + this.treeModel.getChildren(parentItem, onComplete, onError, queryObj); + }else{ + this.store.fetchItemByIdentity({ + identity: parentId, + onItem: function(item){ + _this.treeModel.getChildren(item, onComplete, onError, queryObj); + }, + onError: onError + }); + } + } + }, + _onFetchBegin: function(size, request){ + if(this._treeCache.items.length === 0){ + this._size = parseInt(size, 10); + } + size = this._size; + // this._size = size = this._treeCache.items.length; + this.inherited(arguments); + }, + _onFetchComplete: function(items, request){ + var startRowIdx = request.startRowIdx, + count = request.count, + start = items.length <= count ? 0: request.start, + treePath = request.treePath || []; + if(lang.isArray(items) && items.length > 0){ + var i = 0, len = Math.min(count, items.length); + for(; i < len; i++){ + if(!this._treeCache.items[startRowIdx + i]){ + this._treeCache.items[startRowIdx + i] = {opened: false, treePath: treePath}; + } + if(!this._by_idx[startRowIdx + i]){ + this._addItem(items[start + i], startRowIdx + i, true); + } + // this._treeCache.items.splice(startRowIdx + i, 0, {opened: false, treePath: treePath}); + } + this.updateRows(startRowIdx, len); + } + if(this._size == 0){ + this.showMessage(this.noDataMessage); + }else{ + this.showMessage(); + } + this._pending_requests[startRowIdx] = false; + this._reqQueueLen--; + if(this._loading && this._reqQueueLen === 0){ + this._loading = false; + if(this._lastScrollTop){ + this.setScrollTop(this._lastScrollTop); + } + } + }, + expandoFetch: function(rowIndex, open){ + // summary: + // Function for fetch children of a given row + if(this._loading || !this._by_idx[rowIndex]){return;} + this._loading = true; + this._toggleLoadingClass(rowIndex, true); + this.expandoRowIndex = rowIndex; + var item = this._by_idx[rowIndex].item; + // this._pages = []; + if(open){ + var queryObj = { + start: 0, + count: this.rowsPerPage, + parentId: this.store.getIdentity(this._by_idx[rowIndex].item), + sort: this.getSortProps() + }; + this.treeModel.getChildren(item, lang.hitch(this, "_onExpandoComplete"), lang.hitch(this, "_onFetchError"), queryObj); + }else{ + // get the whole children number when clear the children from cache + var num = this._treeCache.removeChildren(rowIndex); + // remove the items from grid._by_idx + this._by_idx.splice(rowIndex + 1, num); + this._bop = this._eop = -1; + //update grid + this._size -= num; + this.updateRowCount(this._size); + this._updateRenderedRows(rowIndex + 1); + this._toggleLoadingClass(rowIndex, false); + if(this._loading){ + this._loading = false; + } + this.focus._delayedCellFocus(); + } + }, + _onExpandoComplete: function(childItems, request, size){ + size = isNaN(size) ? childItems.length : parseInt(size, 10); + var treePath = this._treeCache.items[this.expandoRowIndex].treePath.slice(0); + treePath.push(this.store.getIdentity(this._by_idx[this.expandoRowIndex].item)); + var i = 1, idty; + for(; i <= size; i++){ + this._treeCache.items.splice(this.expandoRowIndex + i, 0, {treePath: treePath, opened: false}); + } + this._size += size; + this.updateRowCount(this._size); + for(i = 0; i < size; i++){ + if(childItems[i]){ + idty = this.store.getIdentity(childItems[i]); + this._by_idty[idty] = { idty: idty, item: childItems[i] }; + this._by_idx.splice(this.expandoRowIndex + 1 + i, 0, this._by_idty[idty]); + }else{ + this._by_idx.splice(this.expandoRowIndex + 1 + i, 0, null); + } + } + this._updateRenderedRows(this.expandoRowIndex + 1); + this._toggleLoadingClass(this.expandoRowIndex, false); + this.stateChangeNode = null; + if(this._loading){ + this._loading = false; + } + if(this.autoHeight === true){ + this._resize(); + } + this.focus._delayedCellFocus(); + }, + styleRowNode: function(rowIndex, rowNode){ + if(rowNode){ + this.rows.styleRowNode(rowIndex, rowNode); + } + }, + onStyleRow: function(row){ + if(!this.layout._isCollapsable){ + this.inherited(arguments); + return; + } + row.customClasses = (row.odd ? " dojoxGridRowOdd" : "") + (row.selected ? " dojoxGridRowSelected" : "") + (row.over ? " dojoxGridRowOver" : ""); + this.focus.styleRow(row); + this.edit.styleRow(row); + }, + onKeyDown: function(e){ + if(e.altKey || e.metaKey){ + return; + } + var expando = dijit.findWidgets(e.target)[0]; + if(e.keyCode === keys.ENTER && expando instanceof _LazyExpando){ + expando.onToggle(); + } + this.inherited(arguments); + }, + _toggleLoadingClass: function(rowIndex, flag){ + var views = this.views.views, node, + rowNode = views[views.length - 1].getRowNode(rowIndex); + if(rowNode){ + node = query('.dojoxGridExpando', rowNode)[0]; + if(node){ + domClass.toggle(node, "dojoxGridExpandoLoading", flag); + } + } + }, + _updateRenderedRows: function(start){ + array.forEach(this.scroller.stack, function(p){ + if(p * this.rowsPerPage >= start){ + this.updateRows(p * this.rowsPerPage, this.rowsPerPage); + }else if((p + 1) * this.rowsPerPage >= start){ + this.updateRows(start, (p + 1) * this.rowsPerPage - start + 1); + } + }, this); + }, + _fold: function(itemId, open){ + var rowIndex = -1, i = 0, byIdx = this._by_idx, idty = this._by_idty[itemId]; + if(idty && idty.item && this.treeModel.mayHaveChildren(idty.item)){ + for(; i < byIdx.length; i++){ + if(byIdx[i] && byIdx[i].idty === itemId){ + rowIndex = i; + break; + } + } + if(rowIndex >= 0){ + var rowNode = this.views.views[this.views.views.length - 1].getRowNode(rowIndex); + if(rowNode){ + var expando = dijit.findWidgets(rowNode)[0]; + if(expando){ + expando.setOpen(open); + } + } + } + } + } +}); + +LazyTreeGrid.markupFactory = function(props, node, ctor, cellFunc){ + return TreeGrid.markupFactory(props, node, ctor, cellFunc); +}; + +return LazyTreeGrid; + +});
\ No newline at end of file |
