<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js"><span id='Ext-tree-View'>/**
|
</span> * Used as a view by {@link Ext.tree.Panel TreePanel}.
|
*/
|
Ext.define('Ext.tree.View', {
|
extend: 'Ext.view.Table',
|
alias: 'widget.treeview',
|
|
requires: [
|
'Ext.data.NodeStore'
|
],
|
|
<span id='Ext-tree-View-property-isTreeView'> /**
|
</span> * @property {Boolean} isTreeView
|
* `true` in this class to identify an object as an instantiated TreeView, or subclass thereof.
|
*/
|
isTreeView: true,
|
|
<span id='Ext-tree-View-cfg-loadingCls'> loadingCls: Ext.baseCSSPrefix + 'grid-tree-loading',
|
</span><span id='Ext-tree-View-property-expandedCls'> expandedCls: Ext.baseCSSPrefix + 'grid-tree-node-expanded',
|
</span><span id='Ext-tree-View-property-leafCls'> leafCls: Ext.baseCSSPrefix + 'grid-tree-node-leaf',
|
</span>
|
<span id='Ext-tree-View-property-expanderSelector'> expanderSelector: '.' + Ext.baseCSSPrefix + 'tree-expander',
|
</span><span id='Ext-tree-View-property-checkboxSelector'> checkboxSelector: '.' + Ext.baseCSSPrefix + 'tree-checkbox',
|
</span><span id='Ext-tree-View-property-expanderIconOverCls'> expanderIconOverCls: Ext.baseCSSPrefix + 'tree-expander-over',
|
</span>
|
<span id='Ext-tree-View-property-nodeAnimWrapCls'> // Class to add to the node wrap element used to hold nodes when a parent is being
|
</span> // collapsed or expanded. During the animation, UI interaction is forbidden by testing
|
// for an ancestor node with this class.
|
nodeAnimWrapCls: Ext.baseCSSPrefix + 'tree-animator-wrap',
|
|
<span id='Ext-tree-View-cfg-blockRefresh'> blockRefresh: true,
|
</span>
|
<span id='Ext-tree-View-cfg-loadMask'> /**
|
</span> * @cfg {Boolean}
|
* @inheritdoc
|
*/
|
loadMask: false,
|
|
<span id='Ext-tree-View-cfg-rootVisible'> /**
|
</span> * @cfg {Boolean} rootVisible
|
* False to hide the root node.
|
*/
|
rootVisible: true,
|
|
<span id='Ext-tree-View-cfg-deferInitialRefresh'> /**
|
</span> * @cfg {Boolean} deferInitialRefresh
|
* Must be false for Tree Views because the root node must be rendered in order to be updated with its child nodes.
|
*/
|
deferInitialRefresh: false,
|
|
<span id='Ext-tree-View-cfg-animate'> /**
|
</span> * @cfg {Boolean} animate
|
* True to enable animated expand/collapse (defaults to the value of {@link Ext#enableFx Ext.enableFx})
|
*/
|
|
expandDuration: 250,
|
<span id='Ext-tree-View-property-collapseDuration'> collapseDuration: 250,
|
</span>
|
<span id='Ext-tree-View-property-toggleOnDblClick'> toggleOnDblClick: true,
|
</span>
|
<span id='Ext-tree-View-cfg-stripeRows'> stripeRows: false,
|
</span>
|
<span id='Ext-tree-View-property-uiFields'> // fields that will trigger a change in the ui that aren't likely to be bound to a column
|
</span> uiFields: ['expanded', 'loaded', 'checked', 'expandable', 'leaf', 'icon', 'iconCls', 'loading', 'qtip', 'qtitle'],
|
|
<span id='Ext-tree-View-property-treeRowTpl'> // treeRowTpl which is inserted into thwe rowTpl chain before the base rowTpl. Sets tree-specific classes and attributes
|
</span> treeRowTpl: [
|
'{%',
|
'this.processRowValues(values);',
|
'this.nextTpl.applyOut(values, out, parent);',
|
'delete values.rowAttr["data-qtip"];',
|
'delete values.rowAttr["data-qtitle"];',
|
'%}', {
|
priority: 10,
|
processRowValues: function(rowValues) {
|
var record = rowValues.record,
|
view = rowValues.view,
|
qtip = record.get('qtip'),
|
qtitle = record.get('qttle');
|
|
rowValues.rowAttr = {};
|
if (qtip) {
|
rowValues.rowAttr['data-qtip'] = qtip;
|
}
|
if (qtitle) {
|
rowValues.rowAttr['data-qtitle'] = qtitle;
|
}
|
if (record.isExpanded()) {
|
rowValues.rowClasses.push(view.expandedCls);
|
}
|
if (record.isLeaf()) {
|
rowValues.rowClasses.push(view.leafCls);
|
}
|
if (record.isLoading()) {
|
rowValues.rowClasses.push(view.loadingCls);
|
}
|
}
|
}
|
],
|
|
<span id='Ext-tree-View-method-initComponent'> initComponent: function() {
|
</span> var me = this,
|
treeStore = me.panel.getStore(),
|
store = me.store;
|
|
if (me.initialConfig.animate === undefined) {
|
me.animate = Ext.enableFx;
|
}
|
|
if (!store || store === treeStore) {
|
me.store = store = new Ext.data.NodeStore({
|
treeStore: treeStore,
|
recursive: true,
|
rootVisible: me.rootVisible
|
});
|
}
|
|
if (me.node) {
|
me.setRootNode(me.node);
|
}
|
me.animQueue = {};
|
me.animWraps = {};
|
me.addEvents(
|
<span id='Ext-tree-View-event-afteritemexpand'> /**
|
</span> * @event afteritemexpand
|
* Fires after an item has been visually expanded and is visible in the tree.
|
* @param {Ext.data.NodeInterface} node The node that was expanded
|
* @param {Number} index The index of the node
|
* @param {HTMLElement} item The HTML element for the node that was expanded
|
*/
|
'afteritemexpand',
|
<span id='Ext-tree-View-event-afteritemcollapse'> /**
|
</span> * @event afteritemcollapse
|
* Fires after an item has been visually collapsed and is no longer visible in the tree.
|
* @param {Ext.data.NodeInterface} node The node that was collapsed
|
* @param {Number} index The index of the node
|
* @param {HTMLElement} item The HTML element for the node that was collapsed
|
*/
|
'afteritemcollapse',
|
<span id='Ext-tree-View-event-nodedragover'> /**
|
</span> * @event nodedragover
|
* Fires when a tree node is being targeted for a drag drop, return false to signal drop not allowed.
|
* @param {Ext.data.NodeInterface} targetNode The target node
|
* @param {String} position The drop position, "before", "after" or "append",
|
* @param {Object} dragData Data relating to the drag operation
|
* @param {Ext.EventObject} e The event object for the drag
|
*/
|
'nodedragover'
|
);
|
me.callParent(arguments);
|
me.addRowTpl(Ext.XTemplate.getTpl(me, 'treeRowTpl'));
|
},
|
|
<span id='Ext-tree-View-method-onBeforeFill'> onBeforeFill: function(treeStore, fillRoot) {
|
</span> this.store.suspendEvents();
|
},
|
|
<span id='Ext-tree-View-method-onFillComplete'> onFillComplete: function(treeStore, fillRoot, newNodes) {
|
</span> var me = this,
|
store = me.store,
|
start = store.indexOf(newNodes[0]);
|
|
store.resumeEvents();
|
|
// Always update the current node, since the load may be triggered
|
// by .load() directly instead of .expand() on the node
|
fillRoot.triggerUIUpdate();
|
|
// In the cases of expand, the records might not be in the store yet,
|
// so jump out early and expand will handle it later
|
if (!newNodes.length || start === -1) {
|
return;
|
}
|
|
// Insert new nodes into the view
|
me.onAdd(me.store, newNodes, start);
|
|
me.refreshPartner();
|
},
|
|
<span id='Ext-tree-View-method-onBeforeSort'> onBeforeSort: function() {
|
</span> this.store.suspendEvents();
|
},
|
|
<span id='Ext-tree-View-method-onSort'> onSort: function(o) {
|
</span> // The store will fire sort events for the nodes that bubble from the tree.
|
// We only want the final one when sorting is completed, fired by the store
|
if (o.isStore) {
|
this.store.resumeEvents();
|
this.refresh();
|
this.refreshPartner();
|
}
|
},
|
|
<span id='Ext-tree-View-method-refreshPartner'> refreshPartner: function() {
|
</span> var partner = this.lockingPartner;
|
if (partner) {
|
partner.refresh();
|
}
|
},
|
|
<span id='Ext-tree-View-method-getMaskStore'> getMaskStore: function() {
|
</span> return this.panel.getStore();
|
},
|
|
<span id='Ext-tree-View-method-afterRender'> afterRender: function() {
|
</span> var me = this;
|
me.callParent(arguments);
|
|
me.el.on({
|
scope: me,
|
delegate: me.expanderSelector,
|
mouseover: me.onExpanderMouseOver,
|
mouseout: me.onExpanderMouseOut,
|
click: {
|
delegate: me.checkboxSelector,
|
fn: me.onCheckboxChange,
|
scope: me
|
}
|
});
|
},
|
|
<span id='Ext-tree-View-method-afterComponentLayout'> afterComponentLayout: function() {
|
</span> this.callParent(arguments);
|
var stretcher = this.stretcher;
|
if (stretcher) {
|
stretcher.setWidth((this.getWidth() - Ext.getScrollbarSize().width));
|
}
|
},
|
|
<span id='Ext-tree-View-method-processUIEvent'> processUIEvent: function(e) {
|
</span> // If the clicked node is part of an animation, ignore the click.
|
// This is because during a collapse animation, the associated Records
|
// will already have been removed from the Store, and the event is not processable.
|
if (e.getTarget('.' + this.nodeAnimWrapCls, this.el)) {
|
return false;
|
}
|
return this.callParent(arguments);
|
},
|
|
<span id='Ext-tree-View-method-onClear'> onClear: function() {
|
</span> this.store.removeAll();
|
},
|
|
<span id='Ext-tree-View-method-setRootNode'> setRootNode: function(node) {
|
</span> var me = this;
|
me.store.setNode(node);
|
me.node = node;
|
},
|
|
<span id='Ext-tree-View-method-onCheckboxChange'> onCheckboxChange: function(e, t) {
|
</span> var me = this,
|
item = e.getTarget(me.getItemSelector(), me.getTargetEl());
|
|
if (item) {
|
me.onCheckChange(me.getRecord(item));
|
}
|
},
|
|
<span id='Ext-tree-View-method-onCheckChange'> onCheckChange: function(record) {
|
</span> var checked = record.get('checked');
|
if (Ext.isBoolean(checked)) {
|
checked = !checked;
|
record.set('checked', checked);
|
this.fireEvent('checkchange', record, checked);
|
}
|
},
|
|
<span id='Ext-tree-View-method-getChecked'> getChecked: function() {
|
</span> var checked = [];
|
this.node.cascadeBy(function(rec){
|
if (rec.get('checked')) {
|
checked.push(rec);
|
}
|
});
|
return checked;
|
},
|
|
<span id='Ext-tree-View-method-isItemChecked'> isItemChecked: function(rec) {
|
</span> return rec.get('checked');
|
},
|
|
<span id='Ext-tree-View-method-createAnimWrap'> /**
|
</span> * @private
|
*/
|
createAnimWrap: function(record, index) {
|
var me = this,
|
node = me.getNode(record),
|
tmpEl, nodeEl,
|
columnSizer = [];
|
|
me.renderColumnSizer(columnSizer);
|
nodeEl = Ext.get(node);
|
tmpEl = nodeEl.insertSibling({
|
tag: 'tr',
|
html: [
|
'<td colspan="' + me.panel.headerCt.getColumnCount() + '">',
|
'<div class="' + me.nodeAnimWrapCls + '">',
|
// Table has to have correct classes to get sized by the dynamic CSS rules
|
'<table class="' + Ext.baseCSSPrefix + me.id + '-table ' + Ext.baseCSSPrefix + 'grid-table" style="border:0" cellspacing="0" cellpadding="0">',
|
columnSizer.join(''),
|
'<tbody></tbody></table>',
|
'</div>',
|
'</td>'
|
].join('')
|
}, 'after');
|
|
return {
|
record: record,
|
node: node,
|
el: tmpEl,
|
expanding: false,
|
collapsing: false,
|
animating: false,
|
animateEl: tmpEl.down('div'),
|
targetEl: tmpEl.down('tbody')
|
};
|
},
|
|
<span id='Ext-tree-View-method-getAnimWrap'> /**
|
</span> * @private
|
* Returns the animation wrapper element for the specified parent node, used to wrap the child nodes as
|
* they slide up or down during expand/collapse.
|
*
|
* @param parent The parent node to be expanded or collapsed
|
*
|
* @param [bubble=true] If the passed parent node does not already have a wrap element created, by default
|
* this function will bubble up to each parent node looking for a valid wrap element to reuse, returning
|
* the first one it finds. This is the appropriate behavior, e.g., for the collapse direction, so that the
|
* entire expanded set of branch nodes can collapse as a single unit.
|
*
|
* However for expanding each parent node should instead always create its own animation wrap if one
|
* doesn't exist, so that its children can expand independently of any other nodes -- this is crucial
|
* when executing the "expand all" behavior. If multiple nodes attempt to reuse the same ancestor wrap
|
* element concurrently during expansion it will lead to problems as the first animation to complete will
|
* delete the wrap el out from under other running animations. For that reason, when expanding you should
|
* always pass `bubble: false` to be on the safe side.
|
*
|
* If the passed parent has no wrap (or there is no valid ancestor wrap after bubbling), this function
|
* will return null and the calling code should then call {@link #createAnimWrap} if needed.
|
*
|
* @return {Ext.Element} The wrapping element as created in {@link #createAnimWrap}, or null
|
*/
|
getAnimWrap: function(parent, bubble) {
|
if (!this.animate) {
|
return null;
|
}
|
|
var wraps = this.animWraps,
|
wrap = wraps[parent.internalId];
|
|
if (bubble !== false) {
|
while (!wrap && parent) {
|
parent = parent.parentNode;
|
if (parent) {
|
wrap = wraps[parent.internalId];
|
}
|
}
|
}
|
return wrap;
|
},
|
|
<span id='Ext-tree-View-method-doAdd'> doAdd: function(records, index) {
|
</span> // If we are adding records which have a parent that is currently expanding
|
// lets add them to the animation wrap
|
var me = this,
|
nodes = me.bufferRender(records, index, true),
|
record = records[0],
|
parent = record.parentNode,
|
all = me.all,
|
relativeIndex,
|
animWrap = me.getAnimWrap(parent),
|
targetEl, children, len;
|
|
if (!animWrap || !animWrap.expanding) {
|
return me.callParent(arguments);
|
}
|
|
// We need the parent that has the animWrap, not the node's parent
|
parent = animWrap.record;
|
|
// If there is an anim wrap we do our special magic logic
|
targetEl = animWrap.targetEl;
|
children = targetEl.dom.childNodes;
|
len = children.length;
|
|
// The relative index is the index in the full flat collection minus the index of the wraps parent
|
relativeIndex = index - me.indexInStore(parent) - 1;
|
|
// If we are adding records to the wrap that have a higher relative index then there are currently children
|
// it means we have to append the nodes to the wrap
|
if (!len || relativeIndex >= len) {
|
targetEl.appendChild(nodes);
|
}
|
// If there are already more children then the relative index it means we are adding child nodes of
|
// some expanded node in the anim wrap. In this case we have to insert the nodes in the right location
|
else {
|
Ext.fly(children[relativeIndex]).insertSibling(nodes, 'before', true);
|
}
|
|
// We also have to update the node cache of the DataView
|
all.insert(index, nodes);
|
|
// If we were in an animation we need to now change the animation
|
// because the targetEl just got higher.
|
if (animWrap.isAnimating) {
|
me.onExpand(parent);
|
}
|
},
|
|
<span id='Ext-tree-View-method-onRemove'> onRemove : function(ds, records, indexes) {
|
</span> var me = this,
|
empty, i;
|
|
if (me.viewReady) {
|
empty = me.store.getCount() === 0;
|
|
// Nothing left, just refresh the view.
|
if (empty) {
|
me.refresh();
|
}
|
else {
|
// Remove in reverse order so that indices remain correct
|
for (i = indexes.length - 1; i >= 0; --i) {
|
me.doRemove(records[i], indexes[i]);
|
}
|
}
|
|
// Only loop through firing the event if there's anyone listening
|
if (me.hasListeners.itemremove) {
|
for (i = indexes.length - 1; i >= 0; --i) {
|
me.fireEvent('itemremove', records[i], indexes[i]);
|
}
|
}
|
}
|
},
|
|
<span id='Ext-tree-View-method-doRemove'> doRemove: function(record, index) {
|
</span> // If we are adding records which have a parent that is currently expanding
|
// lets add them to the animation wrap
|
var me = this,
|
all = me.all,
|
animWrap = me.getAnimWrap(record),
|
item = all.item(index),
|
node = item ? item.dom : null;
|
|
if (!node || !animWrap || !animWrap.collapsing) {
|
return me.callParent(arguments);
|
}
|
|
// Insert the item at the beginning of the animate el - child nodes are removed
|
// in reverse order so that the index can be used.
|
animWrap.targetEl.dom.insertBefore(node, animWrap.targetEl.dom.firstChild);
|
all.removeElement(index);
|
},
|
|
<span id='Ext-tree-View-method-onBeforeExpand'> onBeforeExpand: function(parent, records, index) {
|
</span> var me = this,
|
animWrap;
|
|
if (me.rendered && me.all.getCount() && me.animate) {
|
if (me.getNode(parent)) {
|
animWrap = me.getAnimWrap(parent, false);
|
if (!animWrap) {
|
animWrap = me.animWraps[parent.internalId] = me.createAnimWrap(parent);
|
animWrap.animateEl.setHeight(0);
|
}
|
else if (animWrap.collapsing) {
|
// If we expand this node while it is still expanding then we
|
// have to remove the nodes from the animWrap.
|
animWrap.targetEl.select(me.itemSelector).remove();
|
}
|
animWrap.expanding = true;
|
animWrap.collapsing = false;
|
}
|
}
|
},
|
|
<span id='Ext-tree-View-method-onExpand'> onExpand: function(parent) {
|
</span> var me = this,
|
queue = me.animQueue,
|
id = parent.getId(),
|
node = me.getNode(parent),
|
index = node ? me.indexOf(node) : -1,
|
animWrap,
|
animateEl,
|
targetEl,
|
fromHeight = Ext.isIEQuirks ? 1 : 0 // Quirks mode on IE seems to have issues with 0;
|
|
if (me.singleExpand) {
|
me.ensureSingleExpand(parent);
|
}
|
|
// The item is not visible yet
|
if (index === -1) {
|
return;
|
}
|
|
animWrap = me.getAnimWrap(parent, false);
|
|
if (!animWrap) {
|
parent.isExpandingOrCollapsing = false;
|
me.fireEvent('afteritemexpand', parent, index, node);
|
me.refreshSize();
|
return;
|
}
|
|
animateEl = animWrap.animateEl;
|
targetEl = animWrap.targetEl;
|
|
animateEl.stopAnimation();
|
queue[id] = true;
|
|
// Must set element height because animation does not set initial condition until first tick has elapsed
|
animateEl.dom.style.height = fromHeight + 'px';
|
animateEl.animate({
|
from: {
|
height: fromHeight
|
},
|
to: {
|
height: targetEl.getHeight()
|
},
|
duration: me.expandDuration,
|
listeners: {
|
afteranimate: function() {
|
// Move all the nodes out of the anim wrap to their proper location
|
// Must do this in afteranimate because lastframe does not fire if the
|
// animation is stopped.
|
var items = targetEl.query(me.itemSelector);
|
if (items.length) {
|
animWrap.el.insertSibling(items, 'before', true);
|
}
|
animWrap.el.remove();
|
me.refreshSize();
|
delete me.animWraps[animWrap.record.internalId];
|
delete queue[id];
|
}
|
},
|
callback: function() {
|
parent.isExpandingOrCollapsing = false;
|
me.fireEvent('afteritemexpand', parent, index, node);
|
}
|
});
|
|
animWrap.isAnimating = true;
|
},
|
|
<span id='Ext-tree-View-method-onBeforeCollapse'> // Triggered by the NodeStore's onNodeCollapse event.
|
</span> onBeforeCollapse: function(parent, records, index, callback, scope) {
|
var me = this,
|
animWrap;
|
|
if (me.rendered && me.all.getCount()) {
|
if (me.animate) {
|
// Only process if the collapsing node is in the UI.
|
// A node may be collapsed as part of a recursive ancestor collapse, and if it
|
// has already been removed from the UI by virtue of an ancestor being collapsed, we should not do anything.
|
if (Ext.Array.contains(parent.stores, me.store)) {
|
animWrap = me.getAnimWrap(parent);
|
if (!animWrap) {
|
animWrap = me.animWraps[parent.internalId] = me.createAnimWrap(parent, index);
|
}
|
else if (animWrap.expanding) {
|
// If we collapse this node while it is still expanding then we
|
// have to remove the nodes from the animWrap.
|
animWrap.targetEl.select(this.itemSelector).remove();
|
}
|
animWrap.expanding = false;
|
animWrap.collapsing = true;
|
animWrap.callback = callback;
|
animWrap.scope = scope;
|
}
|
} else {
|
// Cache any passed callback for use in the onCollapse post collapse handler non-animated codepath
|
me.onCollapseCallback = callback;
|
me.onCollapseScope = scope;
|
}
|
}
|
},
|
|
<span id='Ext-tree-View-method-onCollapse'> onCollapse: function(parent) {
|
</span> var me = this,
|
queue = me.animQueue,
|
id = parent.getId(),
|
node = me.getNode(parent),
|
index = node ? me.indexOf(node) : -1,
|
animWrap = me.getAnimWrap(parent),
|
animateEl;
|
|
// If the collapsed node is already removed from the UI
|
// by virtue of being a descendant of a collapsed node, then
|
// we have nothing to do here.
|
if (!me.all.getCount() || !Ext.Array.contains(parent.stores, me.store)) {
|
return;
|
}
|
|
// Not animating, all items will have been added, so updateLayout and resume layouts
|
if (!animWrap) {
|
parent.isExpandingOrCollapsing = false;
|
me.fireEvent('afteritemcollapse', parent, index, node);
|
me.refreshSize();
|
|
// Call any collapse callback cached in the onBeforeCollapse handler
|
Ext.callback(me.onCollapseCallback, me.onCollapseScope);
|
me.onCollapseCallback = me.onCollapseScope = null;
|
return;
|
}
|
|
animateEl = animWrap.animateEl;
|
|
queue[id] = true;
|
|
animateEl.stopAnimation();
|
animateEl.animate({
|
to: {
|
height: Ext.isIEQuirks ? 1 : 0 // Quirks mode on IE seems to have issues with 0
|
},
|
duration: me.collapseDuration,
|
listeners: {
|
afteranimate: function() {
|
// In case lastframe did not fire because the animation was stopped.
|
animWrap.el.remove();
|
me.refreshSize();
|
delete me.animWraps[animWrap.record.internalId];
|
delete queue[id];
|
}
|
},
|
callback: function() {
|
parent.isExpandingOrCollapsing = false;
|
me.fireEvent('afteritemcollapse', parent, index, node);
|
|
// Call any collapse callback cached in the onBeforeCollapse handler
|
Ext.callback(animWrap.callback, animWrap.scope);
|
animWrap.callback = animWrap.scope = null;
|
}
|
});
|
animWrap.isAnimating = true;
|
},
|
|
<span id='Ext-tree-View-method-isAnimating'> /**
|
</span> * Checks if a node is currently undergoing animation
|
* @private
|
* @param {Ext.data.Model} node The node
|
* @return {Boolean} True if the node is animating
|
*/
|
isAnimating: function(node) {
|
return !!this.animQueue[node.getId()];
|
},
|
|
<span id='Ext-tree-View-method-expand'> /**
|
</span> * Expands a record that is loaded in the view.
|
*
|
* If an animated collapse or expand of the record is in progress, this call will be ignored.
|
* @param {Ext.data.Model} record The record to expand
|
* @param {Boolean} [deep] True to expand nodes all the way down the tree hierarchy.
|
* @param {Function} [callback] The function to run after the expand is completed
|
* @param {Object} [scope] The scope of the callback function.
|
*/
|
expand: function(record, deep, callback, scope) {
|
var me = this,
|
doAnimate = !!me.animate,
|
result;
|
|
// Block toggling if we are already animating an expand or collapse operation.
|
if (!doAnimate || !record.isExpandingOrCollapsing) {
|
if (!record.isLeaf()) {
|
record.isExpandingOrCollapsing = doAnimate;
|
}
|
|
// Need to suspend layouts because the expand process makes multiple changes to the UI
|
// in addition to inserting new nodes. Folder and elbow images have to change, so we
|
// need to coalesce all resulting layouts.
|
Ext.suspendLayouts();
|
result = record.expand(deep, callback, scope);
|
Ext.resumeLayouts(true);
|
return result;
|
}
|
},
|
|
<span id='Ext-tree-View-method-collapse'> /**
|
</span> * Collapses a record that is loaded in the view.
|
*
|
* If an animated collapse or expand of the record is in progress, this call will be ignored.
|
* @param {Ext.data.Model} record The record to collapse
|
* @param {Boolean} [deep] True to collapse nodes all the way up the tree hierarchy.
|
* @param {Function} [callback] The function to run after the collapse is completed
|
* @param {Object} [scope] The scope of the callback function.
|
*/
|
collapse: function(record, deep, callback, scope) {
|
var me = this,
|
doAnimate = !!me.animate;
|
|
// Block toggling if we are already animating an expand or collapse operation.
|
if (!doAnimate || !record.isExpandingOrCollapsing) {
|
if (!record.isLeaf()) {
|
record.isExpandingOrCollapsing = doAnimate;
|
}
|
return record.collapse(deep, callback, scope);
|
}
|
},
|
|
<span id='Ext-tree-View-method-toggle'> /**
|
</span> * Toggles a record between expanded and collapsed.
|
*
|
* If an animated collapse or expand of the record is in progress, this call will be ignored.
|
* @param {Ext.data.Model} record
|
* @param {Boolean} [deep] True to collapse nodes all the way up the tree hierarchy.
|
* @param {Function} [callback] The function to run after the expand/collapse is completed
|
* @param {Object} [scope] The scope of the callback function.
|
*/
|
toggle: function(record, deep, callback, scope) {
|
if (record.isExpanded()) {
|
this.collapse(record, deep, callback, scope);
|
} else {
|
this.expand(record, deep, callback, scope);
|
}
|
},
|
|
<span id='Ext-tree-View-method-onItemDblClick'> onItemDblClick: function(record, item, index) {
|
</span> var me = this,
|
editingPlugin = me.editingPlugin;
|
|
me.callParent(arguments);
|
if (me.toggleOnDblClick && record.isExpandable() && !(editingPlugin && editingPlugin.clicksToEdit === 2)) {
|
me.toggle(record);
|
}
|
},
|
|
<span id='Ext-tree-View-method-onBeforeItemMouseDown'> onBeforeItemMouseDown: function(record, item, index, e) {
|
</span> if (e.getTarget(this.expanderSelector, item)) {
|
return false;
|
}
|
return this.callParent(arguments);
|
},
|
|
<span id='Ext-tree-View-method-onItemClick'> onItemClick: function(record, item, index, e) {
|
</span> if (e.getTarget(this.expanderSelector, item) && record.isExpandable()) {
|
this.toggle(record, e.ctrlKey);
|
return false;
|
}
|
return this.callParent(arguments);
|
},
|
|
<span id='Ext-tree-View-method-onExpanderMouseOver'> onExpanderMouseOver: function(e, t) {
|
</span> e.getTarget(this.cellSelector, 10, true).addCls(this.expanderIconOverCls);
|
},
|
|
<span id='Ext-tree-View-method-onExpanderMouseOut'> onExpanderMouseOut: function(e, t) {
|
</span> e.getTarget(this.cellSelector, 10, true).removeCls(this.expanderIconOverCls);
|
},
|
|
<span id='Ext-tree-View-method-getStoreListeners'> getStoreListeners: function(){
|
</span> var me = this,
|
listeners = me.callParent(arguments);
|
|
return Ext.apply(listeners, {
|
beforeexpand: me.onBeforeExpand,
|
expand: me.onExpand,
|
beforecollapse: me.onBeforeCollapse,
|
collapse: me.onCollapse,
|
write: me.onStoreWrite,
|
datachanged: me.onStoreDataChanged
|
});
|
},
|
|
<span id='Ext-tree-View-method-onBindStore'> onBindStore: function(){
|
</span> var me = this,
|
treeStore = me.getTreeStore();
|
|
me.callParent(arguments);
|
|
me.mon(treeStore, {
|
scope: me,
|
beforefill: me.onBeforeFill,
|
fillcomplete: me.onFillComplete
|
});
|
|
if (!treeStore.remoteSort) {
|
// If we're local sorting, we don't want the view to be
|
// continually updated during the sort process
|
me.mon(treeStore, {
|
scope: me,
|
beforesort: me.onBeforeSort,
|
sort: me.onSort
|
});
|
}
|
},
|
|
<span id='Ext-tree-View-method-onUnbindStore'> onUnbindStore: function(){
|
</span> var me = this,
|
treeStore = me.getTreeStore();
|
|
me.callParent(arguments);
|
|
me.mun(treeStore, {
|
scope: me,
|
beforefill: me.onBeforeFill,
|
fillcomplete: me.onFillComplete
|
});
|
|
if (!treeStore.remoteSort) {
|
me.mun(treeStore, {
|
scope: me,
|
beforesort: me.onBeforeSort,
|
sort: me.onSort
|
});
|
}
|
},
|
|
<span id='Ext-tree-View-method-getTreeStore'> /**
|
</span> * Gets the base TreeStore from the bound TreePanel.
|
*/
|
getTreeStore: function() {
|
return this.panel.store;
|
},
|
|
<span id='Ext-tree-View-method-ensureSingleExpand'> ensureSingleExpand: function(node) {
|
</span> var parent = node.parentNode;
|
if (parent) {
|
parent.eachChild(function(child) {
|
if (child !== node && child.isExpanded()) {
|
child.collapse();
|
}
|
});
|
}
|
},
|
|
<span id='Ext-tree-View-method-shouldUpdateCell'> shouldUpdateCell: function(record, column, changedFieldNames){
|
</span> if (changedFieldNames) {
|
var i = 0,
|
len = changedFieldNames.length;
|
|
for (; i < len; ++i) {
|
if (Ext.Array.contains(this.uiFields, changedFieldNames[i])) {
|
return true;
|
}
|
}
|
}
|
return this.callParent(arguments);
|
},
|
|
<span id='Ext-tree-View-method-onStoreWrite'> /**
|
</span> * Re-fires the NodeStore's "write" event as a TreeStore event
|
* @private
|
* @param {Ext.data.NodeStore} store
|
* @param {Ext.data.Operation} operation
|
*/
|
onStoreWrite: function(store, operation) {
|
var treeStore = this.panel.store;
|
treeStore.fireEvent('write', treeStore, operation);
|
},
|
|
<span id='Ext-tree-View-method-onStoreDataChanged'> /**
|
</span> * Re-fires the NodeStore's "datachanged" event as a TreeStore event
|
* @private
|
* @param {Ext.data.NodeStore} store
|
* @param {Ext.data.Operation} operation
|
*/
|
onStoreDataChanged: function(store, operation) {
|
var treeStore = this.panel.store;
|
treeStore.fireEvent('datachanged', treeStore);
|
}
|
});
|
</pre>
|
</body>
|
</html>
|