ucan-ext-js-kitchen-sink
Version:
my-ext-gen-app description for Ext JS app MyExtGenApp
386 lines (318 loc) • 9.51 kB
JavaScript
Ext.define('UCAN.common.util.components.WidgetTreeCell', {
extend: 'Ext.grid.cell.Widget',
xtype: 'widgetTreeCell',
isTreeCell: true,
classCls: Ext.baseCSSPrefix + 'treecell',
collapsedCls: Ext.baseCSSPrefix + 'collapsed',
expandedCls: Ext.baseCSSPrefix + 'expanded',
leafCls: Ext.baseCSSPrefix + 'leaf',
expandableCls: Ext.baseCSSPrefix + 'expandable',
loadingCls: Ext.baseCSSPrefix + 'loading',
selectedCls: Ext.baseCSSPrefix + 'selected',
checkableCls: Ext.baseCSSPrefix + 'treecell-checkable',
checkedCls: Ext.baseCSSPrefix + 'treecell-checked',
trimodeCls: Ext.baseCSSPrefix + 'treecell-trimode',
uncheckedCls: Ext.baseCSSPrefix + 'treecell-unchecked',
config: {
iconClsProperty: 'iconCls',
iconCls: null,
indent: null,
text: {
lazy: true,
$value: ''
},
autoCheckChildren: true,
checkable: null,
checkableField: 'checkable',
checkedField: 'checked',
checkOnTriTap: true,
enableTri: true
},
element: {
reference: 'element',
children: [{
reference: 'innerElement',
cls: Ext.baseCSSPrefix + 'inner-el',
children: [{
reference: 'indentElement',
cls: Ext.baseCSSPrefix + 'indent-el'
}, {
reference: 'expanderElement',
cls: Ext.baseCSSPrefix + 'expander-el ' +
Ext.baseCSSPrefix + 'font-icon'
}, {
reference: 'checkElement',
listeners: {
tap: 'onCheckTap'
},
cls: Ext.baseCSSPrefix + 'check-el ' +
Ext.baseCSSPrefix + 'font-icon'
}, {
reference: 'iconElement',
cls: Ext.baseCSSPrefix + 'icon-el ' +
Ext.baseCSSPrefix + 'font-icon'
}, {
reference: 'bodyElement',
cls: Ext.baseCSSPrefix + 'body-el',
uiCls: 'body-el'
}
]
}
]
},
toolDefaults: {
zone: 'tail'
},
relayedEvents: ['beforecheckchange', 'checkchange'],
constructor: function(config) {
let me = this;
me.callParent([config]);
me.element.on({
scope: me,
tap: 'maybeToggle'
});
me.getGrid().relayEvents(me, me.relayedEvents);
},
toggle: function() {
let me = this,
record = me.getRecord();
if (record.isExpanded()) {
me.collapse();
} else if (record.isExpandable()) {
me.expand();
}
},
collapse: function() {
let me = this,
record = me.getRecord();
me.getGrid()
.fireEventedAction('nodecollapse', [me.row, record, 'collapse'], 'doToggle', this);
},
/**
* Expand this tree node.
*/
expand: function() {
let me = this,
record = me.getRecord(),
tree = me.getGrid(),
siblings, i, len, sibling;
tree.fireEventedAction('nodeexpand', [me.row, record, 'expand'], 'doToggle', me);
// Collapse any other expanded sibling if tree is singleExpand
if (record.isExpanded && !record.isRoot() && tree.getSingleExpand()) {
siblings = record.parentNode.childNodes;
for (i = 0, len = siblings.length; i < len; ++i) {
sibling = siblings[i];
if (sibling !== record) {
sibling.collapse();
}
}
}
},
refresh: function(ctx) {
let record;
this.callParent([ctx]);
record = this.getRecord();
if (record) {
this.doNodeUpdate(record);
}
},
updateCheckable: function() {
this.syncCheckElement();
},
updateIconCls: function(iconCls, oldIconCls) {
let me = this;
me.iconElement.replaceCls(oldIconCls, iconCls);
},
updateUi: function(ui, oldUi) {
this.callParent([ui, oldUi]);
// ensure indent is measured from the dom when syncIndent() is called
this._indent = null;
this.syncIndent();
},
syncCheckElement: function() {
let me = this,
record = me.getRecord(),
cellCheckable = me.getCheckable(),
checkedCls = me.checkedCls,
trimodeCls = me.trimodeCls,
uncheckedCls = me.uncheckedCls,
checkable = null,
checked = null,
shouldTri;
if (record) {
checkable = record.get(me.getCheckableField());
checked = record.get(me.getCheckedField());
}
if (
(cellCheckable && checkable !== false) ||
(cellCheckable !== false && checkable && checked != null) ||
(cellCheckable === null && checked != null)
) {
me.addCls(me.checkableCls);
shouldTri = me.shouldTri();
if (checked || shouldTri) {
if (me.getEnableTri() && cellCheckable !== null) {
me.bubbleUp(record);
}
if (shouldTri && cellCheckable !== null) {
me.replaceCls([checkedCls, uncheckedCls], trimodeCls);
} else {
me.replaceCls([trimodeCls, uncheckedCls], checkedCls);
}
} else {
if (checked !== null || cellCheckable !== null) {
me.replaceCls([checkedCls, trimodeCls], uncheckedCls);
}
}
} else {
me.removeCls([me.checkableCls, checkedCls, trimodeCls, uncheckedCls]);
}
},
onCheckTap: function() {
let me = this,
record = me.getRecord(),
checkField, current, checked;
if (!record || me.getCheckable() === false ||
record.get(me.getCheckableField() === false)
) {
return;
}
checkField = me.getCheckedField();
current = record.get(checkField);
checked = current && current !== true ? this.getCheckOnTriTap() : !current;
if (me.fireEvent('beforecheckchange', me, checked, current, record) !== false) {
record.set(checkField, checked);
if (me.getCheckable() !== null) {
if (me.getAutoCheckChildren()) {
record.cascade(function(child) {
if (child !== record) {
child.set(checkField, checked);
}
});
}
if (me.getEnableTri()) {
me.bubbleUp(record);
}
}
me.fireEvent('checkchange', me, checked, record);
}
},
bubbleUp: function(node) {
let me = this,
parent = node.parentNode,
shouldTri;
if (!parent) {
return;
}
shouldTri = me.shouldTri(parent, true);
parent.set('checked', shouldTri ? 'tri' : node.get('checked'));
me.bubbleUp(parent);
},
shouldTri: function(record, forceCheck) {
let checkedField, checked, childNodes, found;
record = record || this.getRecord();
if (!this.getEnableTri() || !record) {
return false;
}
checkedField = this.getCheckedField();
checked = record.get(checkedField);
if (checked != null && (!forceCheck || record.isLeaf())) {
return checked === 'tri';
}
childNodes = record.childNodes;
if (childNodes) {
return childNodes.some(function(child, idx) {
checked = child.get(checkedField);
if (
idx && (
!!checked !== !!found ||
(checked && checked !== true)
)
) {
return true;
}
found = checked;
});
}
return false;
},
privates: {
doNodeUpdate: function(record) {
let me = this,
iconClsProperty = me.getIconClsProperty(),
iconCls = me.getIconCls(),
el = me.element;
if (iconClsProperty && !Ext.isEmpty(iconCls)) {
me.setIconCls(iconCls);
}
el.toggleCls(me.loadingCls, record.data.loading);
el.toggleCls(me.leafCls, record.isLeaf());
me.syncExpandCls();
me.syncIndent();
me.syncCheckElement();
},
getGrid: function() {
return this.row.grid;
},
syncExpandCls: function() {
let me, record, expandable, element, expanded, expandedCls, collapsedCls;
if (!this.updatingExpandCls) {
me = this;
record = me.getRecord();
expandable = record.isExpandable();
element = me.element;
expanded = record.isExpanded();
expandedCls = me.expandedCls;
collapsedCls = me.collapsedCls;
me.updatingExpandCls = true;
element.toggleCls(me.expandableCls, expandable);
if (expandable) {
element.toggleCls(expandedCls, expanded);
element.toggleCls(collapsedCls, !expanded);
} else {
element.removeCls([expandedCls, collapsedCls]);
}
me.updatingExpandCls = false;
}
},
syncIndent: function() {
let me = this,
column = me.getColumn(),
indentSize, record, depth,
store;
if (column) {
indentSize = column._indentSize;
record = me.getRecord();
if (!indentSize) {
column._indentSize = indentSize = parseInt(
me.el.getStyle('background-position'), 10);
}
if (record) {
store = record.getTreeStore();
depth = (store && store.rootVisible)
? record.data.depth
: record.data.depth - 1;
me.indentElement.dom.style.width = (depth * indentSize) + 'px';
}
}
},
maybeToggle: function(e) {
let me = this,
record = me.getRecord(),
wasExpanded = record.isExpanded(),
grid = me.getGrid();
if (!record.isLeaf() && (
!grid.getExpanderOnly() || e.target === me.expanderElement.dom
)) {
me.toggle();
}
if (record.isExpanded() !== wasExpanded) {
e.nodeToggled = true;
e.stopEvent();
}
},
doToggle: function(row, record, fn) {
record[fn]();
}
}
});