/** * A plugin which is a {@link Ext.tip.ToolTip} which shows itself upon mouseover of a DataView item. * * The associated {@link Ext.data.Model record} is passed into the {@link #setData} method just before * the tip is shown. The record is stored in the `record` property. */Ext.define('Ext.dataview.plugin.ItemTip', { extend: 'Ext.tip.ToolTip', alias: 'plugin.dataviewtip', anchor: true, showOnTap: true, defaultBindProperty: 'data', config: { // So that we can get early access to the owning DataView // in applyBind so we can ensure we have a ViewModel. cmp: null }, listeners: { beforeshow: 'onBeforeShow', scope: 'this' }, init: function(dataview) { this.dataview = dataview; dataview.on({ initialize: this.onDataViewInitialized, scope: this }); dataview.getScrollable().on({ scroll: this.onDataViewScroll, scope: this }); }, destroy: function() { // We need to null out the parent very early, otherwise // it will try and call remove() when this isn't really // a child item. this.parent = null; this.callParent(); }, applyData: function(data) { if (data.isEntity) { data = data.getData(true); } return data; }, updateCmp: function(dataview) { this.dataview = this.parent = dataview; }, onDataViewInitialized: function(dataview) { this.setTarget(dataview.container.el); this.itemSelector = '#' + dataview.container.el.id + '>*'; if (!this.getDelegate()) { this.setDelegate(this.itemSelector); } }, onDataViewScroll: function() { var me = this, isInView; if (me.currentTarget) { isInView = me.dataview.getScrollable().isInView(me.currentTarget); if (!isInView.x && isInView.y) { me.hide(); } if (me.isVisible()) { me.showByTarget(me.currentTarget); } } }, onBeforeShow: function() { var me = this, viewModel = me.getViewModel(), dataview = me.dataview, itemEl = me.currentTarget; if (!itemEl.is(me.itemSelector)) { itemEl = itemEl.up(me.itemSelector); } me.recordIndex = dataview.container.getViewItems().indexOf(itemEl.dom); me.record = dataview.getStore().getAt(me.recordIndex); if (me.getBind()) { viewModel.set('record', me.record); viewModel.set('recordIndex', me.recordIndex); // Flush the data now so that the alignment is correct viewModel.notify(); } else { me.setData(me.record.data); } }, privates: { getConstrainRegion: function() { return this.dataview.getScrollable().getElement().getConstrainRegion(); }, applyBind: function(binds, currentBindings) { var me = this, dataview = me.getCmp(), viewModel = me.getViewModel(), parentViewModel = dataview.lookupViewModel(); // Ensure we have a connected ViewModel before binding is processed. if (viewModel) { viewModel.setParent(parentViewModel); } else { me.setViewModel(Ext.Factory.viewModel({ parent: parentViewModel, data: {} })); } me.callParent([binds, currentBindings]); } }});