X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/7a654f8d43fdb43d78b63d90528bed6e86b608cc..3789b528d8dd8aad4558e38e22d775bcab1cbd36:/src/view/View.js diff --git a/src/view/View.js b/src/view/View.js index 5b534df8..dd2d09bc 100644 --- a/src/view/View.js +++ b/src/view/View.js @@ -9,51 +9,52 @@ * 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 DataView to a {@link Ext.data.Store} and renders it into an {@link Ext.panel.Panel}.

+ * The example below binds a DataView to a {@link Ext.data.Store} and renders it into an {@link Ext.panel.Panel}. + * * {@img Ext.DataView/Ext.DataView.png Ext.DataView component} - *

-    Ext.regModel('Image', {
-        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(
-        '',
-            '
', - '', - '
{caption}', - '
', - '
' - ); - - Ext.create('Ext.DataView', { - store: Ext.data.StoreManager.lookup('imagesStore'), - tpl: imageTpl, - itemSelector: 'div.thumb-wrap', - emptyText: 'No images available', - renderTo: Ext.getBody() - }); - *
+ * + * Ext.regModel('Image', { + * 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="thumb-wrap">', + * '<img src="{src}" />', + * '<br/><span>{caption}</span>', + * '</div>', + * '</tpl>' + * ); + * + * Ext.create('Ext.DataView', { + * store: Ext.data.StoreManager.lookup('imagesStore'), + * tpl: imageTpl, + * itemSelector: 'div.thumb-wrap', + * emptyText: 'No images available', + * renderTo: Ext.getBody() + * }); + * * @xtype dataview */ Ext.define('Ext.view.View', { extend: 'Ext.view.AbstractView', alternateClassName: 'Ext.view.View', alias: 'widget.dataview', - + inheritableStatics: { EventMap: { mousedown: 'MouseDown', @@ -68,7 +69,7 @@ Ext.define('Ext.view.View', { keydown: 'KeyDown' } }, - + addCmpEvents: function() { this.addEvents( /** @@ -336,7 +337,7 @@ Ext.define('Ext.view.View', { * @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. @@ -356,9 +357,9 @@ Ext.define('Ext.view.View', { }, // private afterRender: function(){ - var me = this, + var me = this, listeners; - + me.callParent(); listeners = { @@ -372,43 +373,61 @@ Ext.define('Ext.view.View', { mouseout: me.handleEvent, keydown: me.handleEvent }; - + me.mon(me.getTargetEl(), listeners); - + if (me.store) { me.bindStore(me.store, true); } }, - + handleEvent: function(e) { if (this.processUIEvent(e) !== false) { this.processSpecialEvent(e); } }, - + // Private template method processItemEvent: Ext.emptyFn, processContainerEvent: Ext.emptyFn, processSpecialEvent: Ext.emptyFn, - - processUIEvent: function(e, type) { - type = type || e.type; + + /* + * 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 false; + }, + + processUIEvent: function(e) { var me = this, item = e.getTarget(me.getItemSelector(), me.getTargetEl()), map = this.statics().EventMap, - index, record; - + index, record, + type = e.type, + overItem = me.mouseOverItem, + newType; + if (!item) { - // 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 (type == 'mouseover' && me.mouseOverItem && typeof me.mouseOverItem.offsetParent === "object" && Ext.fly(me.mouseOverItem).getRegion().contains(e.getPoint())) { - item = me.mouseOverItem; + if (type == 'mouseover' && me.stillOverItem(e, overItem)) { + item = overItem; } - + // 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(); @@ -417,54 +436,53 @@ Ext.define('Ext.view.View', { } } } - + if (item) { index = me.indexOf(item); if (!record) { record = me.getRecord(item); } - - if (me.processItemEvent(type, record, item, index, e) === false) { + + if (me.processItemEvent(record, item, index, e) === false) { return false; } - - type = me.isNewItemEvent(type, item, e); - if (type === false) { + + newType = me.isNewItemEvent(item, e); + if (newType === false) { return false; } - + if ( - (me['onBeforeItem' + map[type]](record, item, index, e) === false) || - (me.fireEvent('beforeitem' + type, me, record, item, index, e) === false) || - (me['onItem' + map[type]](record, item, index, e) === false) - ) { + (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; } - - me.fireEvent('item' + type, me, record, item, index, e); - } + + me.fireEvent('item' + newType, me, record, item, index, e); + } else { if ( - (me.processContainerEvent(type, e) === false) || + (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; } - + me.fireEvent('container' + type, me, e); } - + return true; }, - - isNewItemEvent: function(type, item, e) { + + isNewItemEvent: function (item, e) { var me = this, overItem = me.mouseOverItem, - contains, - isItem; - + type = e.type; + switch (type) { case 'mouseover': if (item === overItem) { @@ -472,27 +490,18 @@ Ext.define('Ext.view.View', { } me.mouseOverItem = item; return 'mouseenter'; - break; - + case 'mouseout': - /* - * Need an extra check here to see if it's the parent element. See the - * comment re: the browser bug at the start of processUIEvent - */ - if (overItem && typeof overItem.offsetParent === "object") { - contains = Ext.fly(me.mouseOverItem).getRegion().contains(e.getPoint()); - isItem = Ext.fly(e.getTarget()).hasCls(me.itemSelector); - if (contains && isItem) { - return false; - } + // 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'; - break; } return type; }, - + // private onItemMouseEnter: function(record, item, index, e) { if (this.trackOver) { @@ -522,7 +531,7 @@ Ext.define('Ext.view.View', { onBeforeItemDblClick: Ext.emptyFn, onBeforeItemContextMenu: Ext.emptyFn, onBeforeItemKeyDown: Ext.emptyFn, - + // @private, template methods onContainerMouseDown: Ext.emptyFn, onContainerMouseUp: Ext.emptyFn, @@ -540,7 +549,7 @@ Ext.define('Ext.view.View', { onBeforeContainerDblClick: Ext.emptyFn, onBeforeContainerContextMenu: Ext.emptyFn, onBeforeContainerKeyDown: Ext.emptyFn, - + /** * Highlight 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 @@ -560,7 +569,7 @@ Ext.define('Ext.view.View', { clearHighlight: function() { var me = this, highlighted = me.highlightedItem; - + if (highlighted) { Ext.fly(highlighted).removeCls(me.overItemCls); delete me.highlightedItem;