<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The source code</title>
- <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../prettify/prettify.js"></script>
+ <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>
</head>
<body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><span id='Ext-tree-View'>/**
-</span> * @class Ext.tree.View
- * @extends Ext.view.Table
+ <pre class="prettyprint lang-js"><span id='Ext-view-View'>/**
+</span> * 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,
-
-<span id='Ext-tree-View-cfg-rootVisible'> /**
-</span> * @cfg {Boolean} rootVisible <tt>false</tt> to hide the root node (defaults to <tt>true</tt>)
- */
- rootVisible: true,
-
-<span id='Ext-tree-View-cfg-animate'> /**
-</span> * @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(
+<span id='Ext-view-View-event-beforeitemmousedown'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforeitemmouseup'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforeitemmouseenter'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforeitemmouseleave'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforeitemclick'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforeitemdblclick'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforeitemcontextmenu'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforeitemkeydown'> /**
+</span> * @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',
+<span id='Ext-view-View-event-itemmousedown'> /**
+</span> * @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',
+<span id='Ext-view-View-event-itemmouseup'> /**
+</span> * @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',
+<span id='Ext-view-View-event-itemmouseenter'> /**
+</span> * @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',
+<span id='Ext-view-View-event-itemmouseleave'> /**
+</span> * @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',
+<span id='Ext-view-View-event-itemclick'> /**
+</span> * @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',
+<span id='Ext-view-View-event-itemdblclick'> /**
+</span> * @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',
+<span id='Ext-view-View-event-itemcontextmenu'> /**
+</span> * @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',
+<span id='Ext-view-View-event-itemkeydown'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforecontainermousedown'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforecontainermouseup'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforecontainermouseover'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforecontainermouseout'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforecontainerclick'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforecontainerdblclick'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforecontainercontextmenu'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforecontainerkeydown'> /**
+</span> * @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',
+<span id='Ext-view-View-event-containermouseup'> /**
+</span> * @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',
+<span id='Ext-view-View-event-containermouseover'> /**
+</span> * @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',
+<span id='Ext-view-View-event-containermouseout'> /**
+</span> * @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',
+<span id='Ext-view-View-event-containerclick'> /**
+</span> * @event containerclick
+ * Fires when the container is clicked.
+ * @param {Ext.view.View} this
+ * @param {Ext.EventObject} e The raw event object
+ */
+ 'containerclick',
+<span id='Ext-view-View-event-containerdblclick'> /**
+</span> * @event containerdblclick
+ * Fires when the container is double clicked.
+ * @param {Ext.view.View} this
+ * @param {Ext.EventObject} e The raw event object
+ */
+ 'containerdblclick',
+<span id='Ext-view-View-event-containercontextmenu'> /**
+</span> * @event containercontextmenu
+ * Fires when the container is right clicked.
+ * @param {Ext.view.View} this
+ * @param {Ext.EventObject} e The raw event object
+ */
+ 'containercontextmenu',
+<span id='Ext-view-View-event-containerkeydown'> /**
+</span> * @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',
+
+<span id='Ext-view-View-event-selectionchange'> /**
+</span> * @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',
+<span id='Ext-view-View-event-beforeselect'> /**
+</span> * @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;
},
-
-<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()];
- },
-
- 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;
- },
-
-<span id='Ext-tree-View-method-expand'> /**
-</span> * 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);
},
-
-<span id='Ext-tree-View-method-collapse'> /**
-</span> * 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,
+
+<span id='Ext-view-View-method-highlightItem'> /**
+</span> * 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);
},
-
-<span id='Ext-tree-View-method-toggle'> /**
-</span> * Toggle a record between expanded and collapsed.
- * @param {Ext.data.Record} recordInstance
+
+<span id='Ext-view-View-method-clearHighlight'> /**
+</span> * 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);
},
-
-<span id='Ext-tree-View-method-getTreeStore'> /**
-</span> * 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();
}
}
});</pre>