/**
* Ext JS Library 3.4.0
* Copyright(c) 2006-2011 Sencha Inc.
* licensing@sencha.com
* http://www.sencha.com/license
*/
Ext.ns('Ext.ux.tree');
/**
* @class Ext.ux.tree.TreeGrid
* @extends Ext.tree.TreePanel
*
* @xtype treegrid
*/
Ext.ux.tree.TreeGrid = Ext.extend(Ext.tree.TreePanel, {
rootVisible: false,
useArrows: true,
lines: false,
borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
cls: 'x-treegrid',
columnResize: true,
enableSort: true,
reserveScrollOffset: true,
enableHdMenu: true,
columnsText: 'Columns',
initComponent: function () {
if (!this.root) {
this.root = new Ext.tree.AsyncTreeNode({ text: 'Root' });
}
// initialize the loader
var l = this.loader;
if (!l) {
l = new Ext.ux.tree.TreeGridLoader({
dataUrl: this.dataUrl,
requestMethod: this.requestMethod,
store: this.store,
});
} else if (Ext.isObject(l) && !l.load) {
l = new Ext.ux.tree.TreeGridLoader(l);
}
this.loader = l;
Ext.ux.tree.TreeGrid.superclass.initComponent.call(this);
this.initColumns();
if (this.enableSort) {
this.treeGridSorter = new Ext.ux.tree.TreeGridSorter(
this,
this.enableSort
);
}
if (this.columnResize) {
this.colResizer = new Ext.tree.ColumnResizer(this.columnResize);
this.colResizer.init(this);
}
var c = this.columns;
if (!this.internalTpl) {
this.internalTpl = new Ext.XTemplate(
'
',
''
);
}
if (!this.colgroupTpl) {
this.colgroupTpl = new Ext.XTemplate(
''
);
}
},
initColumns: function () {
var cs = this.columns,
len = cs.length,
columns = [],
i,
c;
for (i = 0; i < len; i++) {
c = cs[i];
if (!c.isColumn) {
c.xtype = c.xtype
? /^tg/.test(c.xtype)
? c.xtype
: 'tg' + c.xtype
: 'tgcolumn';
c = Ext.create(c);
}
c.init(this);
columns.push(c);
if (this.enableSort !== false && c.sortable !== false) {
c.sortable = true;
this.enableSort = true;
}
}
this.columns = columns;
},
onRender: function () {
Ext.tree.TreePanel.superclass.onRender.apply(this, arguments);
this.el.addClass('x-treegrid');
this.outerCt = this.body.createChild({
cls:
'x-tree-root-ct x-treegrid-ct ' +
(this.useArrows
? 'x-tree-arrows'
: this.lines
? 'x-tree-lines'
: 'x-tree-no-lines'),
});
this.internalTpl.overwrite(this.outerCt, { columns: this.columns });
this.mainHd = Ext.get(this.outerCt.dom.firstChild);
this.innerHd = Ext.get(this.mainHd.dom.firstChild);
this.innerBody = Ext.get(this.outerCt.dom.lastChild);
this.innerCt = Ext.get(this.innerBody.dom.firstChild);
this.colgroupTpl.insertFirst(this.innerCt, { columns: this.columns });
if (this.hideHeaders) {
this.el.child('.x-grid3-header').setDisplayed('none');
} else if (this.enableHdMenu !== false) {
this.hmenu = new Ext.menu.Menu({ id: this.id + '-hctx' });
if (this.enableColumnHide !== false) {
this.colMenu = new Ext.menu.Menu({
id: this.id + '-hcols-menu',
});
this.colMenu.on({
scope: this,
beforeshow: this.beforeColMenuShow,
itemclick: this.handleHdMenuClick,
});
this.hmenu.add({
itemId: 'columns',
hideOnClick: false,
text: this.columnsText,
menu: this.colMenu,
iconCls: 'x-cols-icon',
});
}
this.hmenu.on('itemclick', this.handleHdMenuClick, this);
}
},
setRootNode: function (node) {
node.attributes.uiProvider = Ext.ux.tree.TreeGridRootNodeUI;
node = Ext.ux.tree.TreeGrid.superclass.setRootNode.call(this, node);
if (this.innerCt) {
this.colgroupTpl.insertFirst(this.innerCt, {
columns: this.columns,
});
}
return node;
},
clearInnerCt: function () {
if (Ext.isIE) {
var dom = this.innerCt.dom;
while (dom.firstChild) {
dom.removeChild(dom.firstChild);
}
} else {
Ext.ux.tree.TreeGrid.superclass.clearInnerCt.call(this);
}
},
initEvents: function () {
Ext.ux.tree.TreeGrid.superclass.initEvents.apply(this, arguments);
this.mon(this.innerBody, 'scroll', this.syncScroll, this);
this.mon(this.innerHd, 'click', this.handleHdDown, this);
this.mon(this.mainHd, {
scope: this,
mouseover: this.handleHdOver,
mouseout: this.handleHdOut,
});
},
onResize: function (w, h) {
Ext.ux.tree.TreeGrid.superclass.onResize.apply(this, arguments);
var bd = this.innerBody.dom;
var hd = this.innerHd.dom;
if (!bd) {
return;
}
if (Ext.isNumber(h)) {
bd.style.height =
this.body.getHeight(true) - hd.offsetHeight + 'px';
}
if (Ext.isNumber(w)) {
var sw = Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
if (
this.reserveScrollOffset ||
bd.offsetWidth - bd.clientWidth > 10
) {
this.setScrollOffset(sw);
} else {
var me = this;
setTimeout(function () {
me.setScrollOffset(
bd.offsetWidth - bd.clientWidth > 10 ? sw : 0
);
}, 10);
}
}
},
updateColumnWidths: function () {
var cols = this.columns,
colCount = cols.length,
groups = this.outerCt.query('colgroup'),
groupCount = groups.length,
c,
g,
i,
j;
for (i = 0; i < colCount; i++) {
c = cols[i];
for (j = 0; j < groupCount; j++) {
g = groups[j];
g.childNodes[i].style.width = (c.hidden ? 0 : c.width) + 'px';
}
}
for (
i = 0, groups = this.innerHd.query('td'), len = groups.length;
i < len;
i++
) {
c = Ext.fly(groups[i]);
if (cols[i] && cols[i].hidden) {
c.addClass('x-treegrid-hd-hidden');
} else {
c.removeClass('x-treegrid-hd-hidden');
}
}
var tcw = this.getTotalColumnWidth();
Ext.fly(this.innerHd.dom.firstChild).setWidth(
tcw + (this.scrollOffset || 0)
);
this.outerCt.select('table').setWidth(tcw);
this.syncHeaderScroll();
},
getVisibleColumns: function () {
var columns = [],
cs = this.columns,
len = cs.length,
i;
for (i = 0; i < len; i++) {
if (!cs[i].hidden) {
columns.push(cs[i]);
}
}
return columns;
},
getTotalColumnWidth: function () {
var total = 0;
for (
var i = 0, cs = this.getVisibleColumns(), len = cs.length;
i < len;
i++
) {
total += cs[i].width;
}
return total;
},
setScrollOffset: function (scrollOffset) {
this.scrollOffset = scrollOffset;
this.updateColumnWidths();
},
// private
handleHdDown: function (e, t) {
var hd = e.getTarget('.x-treegrid-hd');
if (hd && Ext.fly(t).hasClass('x-grid3-hd-btn')) {
var ms = this.hmenu.items,
cs = this.columns,
index = this.findHeaderIndex(hd),
c = cs[index],
sort = c.sortable;
e.stopEvent();
Ext.fly(hd).addClass('x-grid3-hd-menu-open');
this.hdCtxIndex = index;
this.fireEvent('headerbuttonclick', ms, c, hd, index);
this.hmenu.on(
'hide',
function () {
Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
},
this,
{ single: true }
);
this.hmenu.show(t, 'tl-bl?');
} else if (hd) {
var index = this.findHeaderIndex(hd);
this.fireEvent('headerclick', this.columns[index], hd, index);
}
},
// private
handleHdOver: function (e, t) {
var hd = e.getTarget('.x-treegrid-hd');
if (hd && !this.headersDisabled) {
index = this.findHeaderIndex(hd);
this.activeHdRef = t;
this.activeHdIndex = index;
var el = Ext.get(hd);
this.activeHdRegion = el.getRegion();
el.addClass('x-grid3-hd-over');
this.activeHdBtn = el.child('.x-grid3-hd-btn');
if (this.activeHdBtn) {
this.activeHdBtn.dom.style.height =
hd.firstChild.offsetHeight - 1 + 'px';
}
}
},
// private
handleHdOut: function (e, t) {
var hd = e.getTarget('.x-treegrid-hd');
if (hd && (!Ext.isIE || !e.within(hd, true))) {
this.activeHdRef = null;
Ext.fly(hd).removeClass('x-grid3-hd-over');
hd.style.cursor = '';
}
},
findHeaderIndex: function (hd) {
hd = hd.dom || hd;
var cs = hd.parentNode.childNodes;
for (var i = 0, c; (c = cs[i]); i++) {
if (c == hd) {
return i;
}
}
return -1;
},
// private
beforeColMenuShow: function () {
var cols = this.columns,
colCount = cols.length,
i,
c;
this.colMenu.removeAll();
for (i = 1; i < colCount; i++) {
c = cols[i];
if (c.hideable !== false) {
this.colMenu.add(
new Ext.menu.CheckItem({
itemId: 'col-' + i,
text: c.header,
checked: !c.hidden,
hideOnClick: false,
disabled: c.hideable === false,
})
);
}
}
},
// private
handleHdMenuClick: function (item) {
var index = this.hdCtxIndex,
id = item.getItemId();
if (
this.fireEvent(
'headermenuclick',
this.columns[index],
id,
index
) !== false
) {
index = id.substr(4);
if (index > 0 && this.columns[index]) {
this.setColumnVisible(index, !item.checked);
}
}
return true;
},
setColumnVisible: function (index, visible) {
this.columns[index].hidden = !visible;
this.updateColumnWidths();
},
/**
* Scrolls the grid to the top
*/
scrollToTop: function () {
this.innerBody.dom.scrollTop = 0;
this.innerBody.dom.scrollLeft = 0;
},
// private
syncScroll: function () {
this.syncHeaderScroll();
var mb = this.innerBody.dom;
this.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
},
// private
syncHeaderScroll: function () {
var mb = this.innerBody.dom;
this.innerHd.dom.scrollLeft = mb.scrollLeft;
this.innerHd.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore)
},
registerNode: function (n) {
Ext.ux.tree.TreeGrid.superclass.registerNode.call(this, n);
if (!n.uiProvider && !n.isRoot && !n.ui.isTreeGridNodeUI) {
n.ui = new Ext.ux.tree.TreeGridNodeUI(n);
}
},
});
Ext.reg('treegrid', Ext.ux.tree.TreeGrid);