X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6746dc89c47ed01b165cc1152533605f97eb8e8d..refs/heads/master:/docs/source/View3.html diff --git a/docs/source/View3.html b/docs/source/View3.html index 91c04c5a..ae1c1f66 100644 --- a/docs/source/View3.html +++ b/docs/source/View3.html @@ -3,8 +3,8 @@
/** - * @class Ext.tree.View - * @extends Ext.view.Table +/** + * A mechanism for displaying data using custom layout templates and formatting. + * + * The View uses an {@link Ext.XTemplate} as its internal templating mechanism, and is bound to an + * {@link Ext.data.Store} so that as the data in the store changes the view is automatically updated + * to reflect the changes. The view also provides built-in behavior for many common events that can + * occur for its contained items including click, doubleclick, mouseover, mouseout, etc. as well as a + * built-in selection model. **In order to use these features, an {@link #itemSelector} config must + * be provided for the DataView to determine what nodes it will be working with.** + * + * The example below binds a View to a {@link Ext.data.Store} and renders it into an {@link Ext.panel.Panel}. + * + * @example + * Ext.define('Image', { + * extend: 'Ext.data.Model', + * fields: [ + * { name:'src', type:'string' }, + * { name:'caption', type:'string' } + * ] + * }); + * + * Ext.create('Ext.data.Store', { + * id:'imagesStore', + * model: 'Image', + * data: [ + * { src:'http://www.sencha.com/img/20110215-feat-drawing.png', caption:'Drawing & Charts' }, + * { src:'http://www.sencha.com/img/20110215-feat-data.png', caption:'Advanced Data' }, + * { src:'http://www.sencha.com/img/20110215-feat-html5.png', caption:'Overhauled Theme' }, + * { src:'http://www.sencha.com/img/20110215-feat-perf.png', caption:'Performance Tuned' } + * ] + * }); + * + * var imageTpl = new Ext.XTemplate( + * '<tpl for=".">', + * '<div style="margin-bottom: 10px;" class="thumb-wrap">', + * '<img src="{src}" />', + * '<br/><span>{caption}</span>', + * '</div>', + * '</tpl>' + * ); + * + * Ext.create('Ext.view.View', { + * store: Ext.data.StoreManager.lookup('imagesStore'), + * tpl: imageTpl, + * itemSelector: 'div.thumb-wrap', + * emptyText: 'No images available', + * renderTo: Ext.getBody() + * }); */ -Ext.define('Ext.tree.View', { - extend: 'Ext.view.Table', - alias: 'widget.treeview', - - loadingCls: Ext.baseCSSPrefix + 'grid-tree-loading', - expandedCls: Ext.baseCSSPrefix + 'grid-tree-node-expanded', - - expanderSelector: '.' + Ext.baseCSSPrefix + 'tree-expander', - checkboxSelector: '.' + Ext.baseCSSPrefix + 'tree-checkbox', - expanderIconOverCls: Ext.baseCSSPrefix + 'tree-expander-over', - - blockRefresh: true, - - /** - * @cfg {Boolean} rootVisible <tt>false</tt> to hide the root node (defaults to <tt>true</tt>) - */ - rootVisible: true, - - /** - * @cfg {Boolean} animate <tt>true</tt> to enable animated expand/collapse (defaults to the value of {@link Ext#enableFx Ext.enableFx}) - */ - - expandDuration: 250, - collapseDuration: 250, - - toggleOnDblClick: true, - - initComponent: function() { - var me = this; - - if (me.initialConfig.animate === undefined) { - me.animate = Ext.enableFx; - } - - me.store = Ext.create('Ext.data.NodeStore', { - recursive: true, - rootVisible: me.rootVisible, - listeners: { - beforeexpand: me.onBeforeExpand, - expand: me.onExpand, - beforecollapse: me.onBeforeCollapse, - collapse: me.onCollapse, - scope: me - } - }); - - if (me.node) { - me.setRootNode(me.node); +Ext.define('Ext.view.View', { + extend: 'Ext.view.AbstractView', + alternateClassName: 'Ext.DataView', + alias: 'widget.dataview', + + inheritableStatics: { + EventMap: { + mousedown: 'MouseDown', + mouseup: 'MouseUp', + click: 'Click', + dblclick: 'DblClick', + contextmenu: 'ContextMenu', + mouseover: 'MouseOver', + mouseout: 'MouseOut', + mouseenter: 'MouseEnter', + mouseleave: 'MouseLeave', + keydown: 'KeyDown', + focus: 'Focus' } - me.animQueue = {}; - me.callParent(arguments); - }, - - onClear: function(){ - this.store.removeAll(); }, - setRootNode: function(node) { - var me = this; - me.store.setNode(node); - me.node = node; - if (!me.rootVisible) { - node.expand(); - } + addCmpEvents: function() { + this.addEvents( + /** + * @event beforeitemmousedown + * Fires before the mousedown event on an item is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'beforeitemmousedown', + /** + * @event beforeitemmouseup + * Fires before the mouseup event on an item is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'beforeitemmouseup', + /** + * @event beforeitemmouseenter + * Fires before the mouseenter event on an item is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'beforeitemmouseenter', + /** + * @event beforeitemmouseleave + * Fires before the mouseleave event on an item is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'beforeitemmouseleave', + /** + * @event beforeitemclick + * Fires before the click event on an item is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'beforeitemclick', + /** + * @event beforeitemdblclick + * Fires before the dblclick event on an item is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'beforeitemdblclick', + * @event beforeitemcontextmenu + * Fires before the contextmenu event on an item is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'beforeitemcontextmenu', + /** + * @event beforeitemkeydown + * Fires before the keydown event on an item is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object. Use {@link Ext.EventObject#getKey getKey()} to retrieve the key that was pressed. + */ + 'beforeitemkeydown', + /** + * @event itemmousedown + * Fires when there is a mouse down on an item + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'itemmousedown', + /** + * @event itemmouseup + * Fires when there is a mouse up on an item + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'itemmouseup', + /** + * @event itemmouseenter + * Fires when the mouse enters an item. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'itemmouseenter', + /** + * @event itemmouseleave + * Fires when the mouse leaves an item. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'itemmouseleave', + /** + * @event itemclick + * Fires when an item is clicked. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'itemclick', + /** + * @event itemdblclick + * Fires when an item is double clicked. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'itemdblclick', + * @event itemcontextmenu + * Fires when an item is right clicked. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object + */ + 'itemcontextmenu', + /** + * @event itemkeydown + * Fires when a key is pressed while an item is currently selected. + * @param {Ext.view.View} this + * @param {Ext.data.Model} record The record that belongs to the item + * @param {HTMLElement} item The item's element + * @param {Number} index The item's index + * @param {Ext.EventObject} e The raw event object. Use {@link Ext.EventObject#getKey getKey()} to retrieve the key that was pressed. + */ + 'itemkeydown', + /** + * @event beforecontainermousedown + * Fires before the mousedown event on the container is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'beforecontainermousedown', + /** + * @event beforecontainermouseup + * Fires before the mouseup event on the container is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'beforecontainermouseup', + /** + * @event beforecontainermouseover + * Fires before the mouseover event on the container is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'beforecontainermouseover', + /** + * @event beforecontainermouseout + * Fires before the mouseout event on the container is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'beforecontainermouseout', + /** + * @event beforecontainerclick + * Fires before the click event on the container is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'beforecontainerclick', + /** + * @event beforecontainerdblclick + * Fires before the dblclick event on the container is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'beforecontainerdblclick', + * @event beforecontainercontextmenu + * Fires before the contextmenu event on the container is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'beforecontainercontextmenu', + /** + * @event beforecontainerkeydown + * Fires before the keydown event on the container is processed. Returns false to cancel the default action. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object. Use {@link Ext.EventObject#getKey getKey()} to retrieve the key that was pressed. + */ + 'beforecontainerkeydown', + /** + * @event containermouseup + * Fires when there is a mouse up on the container + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'containermouseup', + /** + * @event containermouseover + * Fires when you move the mouse over the container. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'containermouseover', + /** + * @event containermouseout + * Fires when you move the mouse out of the container. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'containermouseout', + /** + * @event containerclick + * Fires when the container is clicked. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'containerclick', + /** + * @event containerdblclick + * Fires when the container is double clicked. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'containerdblclick', + * @event containercontextmenu + * Fires when the container is right clicked. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object + */ + 'containercontextmenu', + /** + * @event containerkeydown + * Fires when a key is pressed while the container is focused, and no item is currently selected. + * @param {Ext.view.View} this + * @param {Ext.EventObject} e The raw event object. Use {@link Ext.EventObject#getKey getKey()} to retrieve the key that was pressed. + */ + 'containerkeydown', + + /** + * @event selectionchange + * Fires when the selected nodes change. Relayed event from the underlying selection model. + * @param {Ext.view.View} this + * @param {HTMLElement[]} selections Array of the selected nodes + */ + 'selectionchange', + /** + * @event beforeselect + * Fires before a selection is made. If any handlers return false, the selection is cancelled. + * @param {Ext.view.View} this + * @param {HTMLElement} node The node to be selected + * @param {HTMLElement[]} selections Array of currently selected nodes + */ + 'beforeselect' + ); }, - - onRender: function() { + // private + afterRender: function(){ var me = this, - opts = {delegate: me.expanderSelector}, - el; + listeners; - me.callParent(arguments); + me.callParent(); - el = me.el; - el.on({ - scope: me, - delegate: me.expanderSelector, - mouseover: me.onExpanderMouseOver, - mouseout: me.onExpanderMouseOut - }); - el.on({ + listeners = { scope: me, - delegate: me.checkboxSelector, - click: me.onCheckboxChange - }); - }, + /* + * We need to make copies of this since some of the events fired here will end up triggering + * a new event to be called and the shared event object will be mutated. In future we should + * investigate if there are any issues with creating a new event object for each event that + * is fired. + */ + freezeEvent: true, + click: me.handleEvent, + mousedown: me.handleEvent, + mouseup: me.handleEvent, + dblclick: me.handleEvent, + contextmenu: me.handleEvent, + mouseover: me.handleEvent, + mouseout: me.handleEvent, + keydown: me.handleEvent + }; - onCheckboxChange: function(e, t) { - var item = e.getTarget(this.getItemSelector(), this.getTargetEl()), - record, value; - - if (item) { - record = this.getRecord(item); - value = !record.get('checked'); - record.set('checked', value); - this.fireEvent('checkchange', record, value); - } - }, + me.mon(me.getTargetEl(), listeners); - getChecked: function() { - var checked = []; - this.node.cascadeBy(function(rec){ - if (rec.get('checked')) { - checked.push(rec); - } - }); - return checked; - }, - - isItemChecked: function(rec){ - return rec.get('checked'); + if (me.store) { + me.bindStore(me.store, true); + } }, - createAnimWrap: function(record, index) { - var thHtml = '', - headerCt = this.panel.headerCt, - headers = headerCt.getGridColumns(), - i = 0, len = headers.length, item, - node = this.getNode(record), - tmpEl, nodeEl; - - for (; i < len; i++) { - item = headers[i]; - thHtml += '<th style="width: ' + (item.hidden ? 0 : item.getDesiredWidth()) + 'px; height: 0px;"></th>'; + handleEvent: function(e) { + if (this.processUIEvent(e) !== false) { + this.processSpecialEvent(e); } - - nodeEl = Ext.get(node); - tmpEl = nodeEl.insertSibling({ - tag: 'tr', - html: [ - '<td colspan="' + headerCt.getColumnCount() + '">', - '<div class="' + Ext.baseCSSPrefix + 'tree-animator-wrap' + '">', - '<table class="' + Ext.baseCSSPrefix + 'grid-table" style="width: ' + headerCt.getFullWidth() + 'px;"><tbody>', - thHtml, - '</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') - }; }, - getAnimWrap: function(parent) { - if (!this.animate) { - return null; - } + // Private template method + processItemEvent: Ext.emptyFn, + processContainerEvent: Ext.emptyFn, + processSpecialEvent: Ext.emptyFn, - // We are checking to see which parent is having the animation wrap - while (parent) { - if (parent.animWrap) { - return parent.animWrap; - } - parent = parent.parentNode; + /* + * Returns true if this mouseover/out event is still over the overItem. + */ + stillOverItem: function (event, overItem) { + var nowOver; + + // There is this weird bug when you hover over the border of a cell it is saying + // the target is the table. + // BrowserBug: IE6 & 7. If me.mouseOverItem has been removed and is no longer + // in the DOM then accessing .offsetParent will throw an "Unspecified error." exception. + // typeof'ng and checking to make sure the offsetParent is an object will NOT throw + // this hard exception. + if (overItem && typeof(overItem.offsetParent) === "object") { + // mouseout : relatedTarget == nowOver, target == wasOver + // mouseover: relatedTarget == wasOver, target == nowOver + nowOver = (event.type == 'mouseout') ? event.getRelatedTarget() : event.getTarget(); + return Ext.fly(overItem).contains(nowOver); } - return null; + + return false; }, - doAdd: function(nodes, records, index) { - // If we are adding records which have a parent that is currently expanding - // lets add them to the animation wrap + processUIEvent: function(e) { var me = this, - record = records[0], - parent = record.parentNode, - a = me.all.elements, - relativeIndex = 0, - animWrap = me.getAnimWrap(parent), - targetEl, children, len; - - if (!animWrap || !animWrap.expanding) { - me.resetScrollers(); - return me.callParent(arguments); - } + item = e.getTarget(me.getItemSelector(), me.getTargetEl()), + map = this.statics().EventMap, + index, record, + type = e.type, + overItem = me.mouseOverItem, + newType; + + if (!item) { + if (type == 'mouseover' && me.stillOverItem(e, overItem)) { + item = overItem; + } - // We need the parent that has the animWrap, not the nodes parent - parent = animWrap.record; - - // If there is an anim wrap we do our special magic logic - targetEl = animWrap.targetEl; - children = targetEl.dom.childNodes; - - // We subtract 1 from the childrens length because we have a tr in there with the th'es - len = children.length - 1; - - // The relative index is the index in the full flat collection minus the index of the wraps parent - relativeIndex = index - me.indexOf(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 { - // +1 because of the tr with th'es that is already there - Ext.fly(children[relativeIndex + 1]).insertSibling(nodes, 'before', true); + // Try to get the selected item to handle the keydown event, otherwise we'll just fire a container keydown event + if (type == 'keydown') { + record = me.getSelectionModel().getLastSelected(); + if (record) { + item = me.getNode(record); + } + } } - // We also have to update the CompositeElementLite collection of the DataView - Ext.Array.insert(a, 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); - } - }, - - doRemove: function(record, index) { - // If we are adding records which have a parent that is currently expanding - // lets add them to the animation wrap - var me = this, - parent = record.parentNode, - all = me.all, - animWrap = me.getAnimWrap(record), - node = all.item(index).dom; - - if (!animWrap || !animWrap.collapsing) { - me.resetScrollers(); - return me.callParent(arguments); - } + if (item) { + index = me.indexOf(item); + if (!record) { + record = me.getRecord(item); + } - animWrap.targetEl.appendChild(node); - all.removeElement(index); - }, + if (me.processItemEvent(record, item, index, e) === false) { + return false; + } - onBeforeExpand: function(parent, records, index) { - var me = this, - animWrap; - - if (!me.rendered || !me.animate) { - return; - } + newType = me.isNewItemEvent(item, e); + if (newType === false) { + return false; + } - if (me.getNode(parent)) { - animWrap = me.getAnimWrap(parent); - if (!animWrap) { - animWrap = parent.animWrap = me.createAnimWrap(parent); - animWrap.animateEl.setHeight(0); + if ( + (me['onBeforeItem' + map[newType]](record, item, index, e) === false) || + (me.fireEvent('beforeitem' + newType, me, record, item, index, e) === false) || + (me['onItem' + map[newType]](record, item, index, e) === false) + ) { + return false; } - 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; - } - }, - onExpand: function(parent) { - var me = this, - queue = me.animQueue, - id = parent.getId(), - animWrap, - animateEl, - targetEl, - queueItem; - - if (me.singleExpand) { - me.ensureSingleExpand(parent); + me.fireEvent('item' + newType, me, record, item, index, e); } - - animWrap = me.getAnimWrap(parent); + else { + if ( + (me.processContainerEvent(e) === false) || + (me['onBeforeContainer' + map[type]](e) === false) || + (me.fireEvent('beforecontainer' + type, me, e) === false) || + (me['onContainer' + map[type]](e) === false) + ) { + return false; + } - if (!animWrap) { - me.resetScrollers(); - return; + me.fireEvent('container' + type, me, e); } - - animateEl = animWrap.animateEl; - targetEl = animWrap.targetEl; - - animateEl.stopAnimation(); - // @TODO: we are setting it to 1 because quirks mode on IE seems to have issues with 0 - queue[id] = true; - animateEl.slideIn('t', { - duration: me.expandDuration, - listeners: { - scope: me, - lastframe: function() { - // Move all the nodes out of the anim wrap to their proper location - animWrap.el.insertSibling(targetEl.query(me.itemSelector), 'before'); - animWrap.el.remove(); - me.resetScrollers(); - delete animWrap.record.animWrap; - delete queue[id]; - } - } - }); - - animWrap.isAnimating = true; - }, - - resetScrollers: function(){ - var panel = this.panel; - - panel.determineScrollbars(); - panel.invalidateScroller(); + + return true; }, - onBeforeCollapse: function(parent, records, index) { + isNewItemEvent: function (item, e) { var me = this, - animWrap; - - if (!me.rendered || !me.animate) { - return; - } + overItem = me.mouseOverItem, + type = e.type; - if (me.getNode(parent)) { - animWrap = me.getAnimWrap(parent); - if (!animWrap) { - animWrap = parent.animWrap = 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; + switch (type) { + case 'mouseover': + if (item === overItem) { + return false; + } + me.mouseOverItem = item; + return 'mouseenter'; + + case 'mouseout': + // If the currently mouseovered item contains the mouseover target, it's *NOT* a mouseleave + if (me.stillOverItem(e, overItem)) { + return false; + } + me.mouseOverItem = null; + return 'mouseleave'; } + return type; }, - - onCollapse: function(parent) { - var me = this, - queue = me.animQueue, - id = parent.getId(), - animWrap = me.getAnimWrap(parent), - animateEl, targetEl; - - if (!animWrap) { - me.resetScrollers(); - return; + + // private + onItemMouseEnter: function(record, item, index, e) { + if (this.trackOver) { + this.highlightItem(item); } - - animateEl = animWrap.animateEl; - targetEl = animWrap.targetEl; - - queue[id] = true; - - // @TODO: we are setting it to 1 because quirks mode on IE seems to have issues with 0 - animateEl.stopAnimation(); - animateEl.slideOut('t', { - duration: me.collapseDuration, - listeners: { - scope: me, - lastframe: function() { - animWrap.el.remove(); - delete animWrap.record.animWrap; - me.resetScrollers(); - delete queue[id]; - } - } - }); - animWrap.isAnimating = true; }, - - /** - * 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()]; - }, - - collectData: function(records) { - var data = this.callParent(arguments), - rows = data.rows, - len = rows.length, - i = 0, - row, record; - - for (; i < len; i++) { - row = rows[i]; - record = records[i]; - if (record.get('qtip')) { - row.rowAttr = 'data-qtip="' + record.get('qtip') + '"'; - if (record.get('qtitle')) { - row.rowAttr += ' ' + 'data-qtitle="' + record.get('qtitle') + '"'; - } - } - if (record.isExpanded()) { - row.rowCls = (row.rowCls || '') + ' ' + this.expandedCls; - } - if (record.isLoading()) { - row.rowCls = (row.rowCls || '') + ' ' + this.loadingCls; - } + + // private + onItemMouseLeave : function(record, item, index, e) { + if (this.trackOver) { + this.clearHighlight(); } - - return data; - }, - - /** - * Expand a record that is loaded in the view. - * @param {Ext.data.Model} record The record to expand - * @param {Boolean} deep (optional) True to expand nodes all the way down the tree hierarchy. - * @param {Function} callback (optional) The function to run after the expand is completed - * @param {Object} scope (optional) The scope of the callback function. - */ - expand: function(record, deep, callback, scope) { - return record.expand(deep, callback, scope); }, - - /** - * Collapse a record that is loaded in the view. - * @param {Ext.data.Model} record The record to collapse - * @param {Boolean} deep (optional) True to collapse nodes all the way up the tree hierarchy. - * @param {Function} callback (optional) The function to run after the collapse is completed - * @param {Object} scope (optional) The scope of the callback function. + + // @private, template methods + onItemMouseDown: Ext.emptyFn, + onItemMouseUp: Ext.emptyFn, + onItemFocus: Ext.emptyFn, + onItemClick: Ext.emptyFn, + onItemDblClick: Ext.emptyFn, + onItemContextMenu: Ext.emptyFn, + onItemKeyDown: Ext.emptyFn, + onBeforeItemMouseDown: Ext.emptyFn, + onBeforeItemMouseUp: Ext.emptyFn, + onBeforeItemFocus: Ext.emptyFn, + onBeforeItemMouseEnter: Ext.emptyFn, + onBeforeItemMouseLeave: Ext.emptyFn, + onBeforeItemClick: Ext.emptyFn, + onBeforeItemDblClick: Ext.emptyFn, + onBeforeItemContextMenu: Ext.emptyFn, + onBeforeItemKeyDown: Ext.emptyFn, + + // @private, template methods + onContainerMouseDown: Ext.emptyFn, + onContainerMouseUp: Ext.emptyFn, + onContainerMouseOver: Ext.emptyFn, + onContainerMouseOut: Ext.emptyFn, + onContainerClick: Ext.emptyFn, + onContainerDblClick: Ext.emptyFn, + onContainerContextMenu: Ext.emptyFn, + onContainerKeyDown: Ext.emptyFn, + onBeforeContainerMouseDown: Ext.emptyFn, + onBeforeContainerMouseUp: Ext.emptyFn, + onBeforeContainerMouseOver: Ext.emptyFn, + onBeforeContainerMouseOut: Ext.emptyFn, + onBeforeContainerClick: Ext.emptyFn, + onBeforeContainerDblClick: Ext.emptyFn, + onBeforeContainerContextMenu: Ext.emptyFn, + onBeforeContainerKeyDown: Ext.emptyFn, + + /** + * Highlights a given item in the DataView. This is called by the mouseover handler if {@link #overItemCls} + * and {@link #trackOver} are configured, but can also be called manually by other code, for instance to + * handle stepping through the list via keyboard navigation. + * @param {HTMLElement} item The item to highlight */ - collapse: function(record, deep, callback, scope) { - return record.collapse(deep, callback, scope); + highlightItem: function(item) { + var me = this; + me.clearHighlight(); + me.highlightedItem = item; + Ext.fly(item).addCls(me.overItemCls); }, - - /** - * Toggle a record between expanded and collapsed. - * @param {Ext.data.Record} recordInstance + + /** + * Un-highlights the currently highlighted item, if any. */ - toggle: function(record) { - this[record.isExpanded() ? 'collapse' : 'expand'](record); - }, - - onItemDblClick: function(record, item, index) { - this.callParent(arguments); - if (this.toggleOnDblClick) { - this.toggle(record); - } - }, - - onBeforeItemMouseDown: function(record, item, index, e) { - if (e.getTarget(this.expanderSelector, item)) { - return false; - } - return this.callParent(arguments); - }, - - onItemClick: function(record, item, index, e) { - if (e.getTarget(this.expanderSelector, item)) { - this.toggle(record); - return false; + clearHighlight: function() { + var me = this, + highlighted = me.highlightedItem; + + if (highlighted) { + Ext.fly(highlighted).removeCls(me.overItemCls); + delete me.highlightedItem; } - return this.callParent(arguments); - }, - - onExpanderMouseOver: function(e, t) { - e.getTarget(this.cellSelector, 10, true).addCls(this.expanderIconOverCls); - }, - - onExpanderMouseOut: function(e, t) { - e.getTarget(this.cellSelector, 10, true).removeCls(this.expanderIconOverCls); }, - - /** - * Gets the base TreeStore from the bound TreePanel. - */ - getTreeStore: function() { - return this.panel.store; - }, - - ensureSingleExpand: function(node) { - var parent = node.parentNode; - if (parent) { - parent.eachChild(function(child) { - if (child !== node && child.isExpanded()) { - child.collapse(); - } - }); + + refresh: function() { + var me = this; + me.clearHighlight(); + me.callParent(arguments); + if (!me.isFixedHeight()) { + me.doComponentLayout(); } } });