PDA

View Full Version : DataView should fire mouse events when not on an item



Animal
30 Dec 2008, 3:55 AM
For example the contextmenu event.

We may need to catch it just when clicking on the DataView's Element, not necessarily on one of the items.

This is the way the context menu works on Windows explorer in icon view. If you right click on an item, you get "Cut" and "Copy". If you right click on an empty part of the view, you just get the "Paste" enable if you already have something in the clipboard.

This is exactly what I am facing. Right clicking on a DataView to perform overall DataView operations as well as operations on individual nodes.

So for example the context menu event should be handled thus:



Ext.override(Ext.DataView, {
onContextMenu : function(e){
var item = e.getTarget(this.itemSelector, this.el);
// 3.0 code var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
this.fireEvent("contextmenu", this, item ? this.indexOf(item) : -1, item, e);
}
});


The consumer of this event must be aware that the user might not have clicked on a node.

With selected nodes: http://i131.photobucket.com/albums/p286/TimeTrialAnimal/contextmenuselection.jpg

Between nodes with no selected nodes to delete/cut/copy/download:

http://i131.photobucket.com/albums/p286/TimeTrialAnimal/contextmenunoselection.jpg

jay@moduscreate.com
30 Dec 2008, 8:25 AM
+1

evant
30 Dec 2008, 3:08 PM
Looks fine, however it could cause some backward compat issues in the 2.x branch, since you can assume that the contextmenu only fires when it's triggered on a node in the DataView.

Animal
31 Dec 2008, 2:39 AM
Maybe have it as a 3.0 change with a release note then?

Because it makes sense to have events fire even if you are not over a child node.

To handle this, the DataView's height needs to be at least the height of its containing Element. Obviously if the DataView's contents cause it to expand to overflow its containing Element, then there's no problem, but if the DataView happens to be empty, then the user will not be able to right click to paste into it because it will be zero height.

So I also propose the following. Additions in red:



refresh : function(){
// Fit the height of the DataView to its parent element so that
// mouse events can be detected when few or no child nodes exist.
if (this.fitHeight) { // Or some such config option which specifies events on "blank" areas.
this.doFitHeight.defer(1, this);
}

this.clearSelections(false, true);
this.el.update("");
var records = this.store.getRange();
if(records.length < 1){
if(!this.deferEmptyText || this.hasSkippedEmptyText){
this.el.update(this.emptyText);
}
this.hasSkippedEmptyText = true;
this.all.clear();
return;
}
this.tpl.overwrite(this.el, this.collectData(records, 0));
this.all.fill(Ext.query(this.itemSelector, this.el.dom));
this.updateIndexes(0);
},

// private
// ensure that the DataView fills its containing element
doFitHeight: function() {
var e = this.el; // 3.0 this.getTemplateTarget()
var pHeight = Ext.fly(e.dom.parentNode).getHeight() - e.getFrameWidth('tb');
if (e.getHeight() < pHeight) {
e.setStyle('height', pHeight + 'px');
} else {
e.setStyle('height', 'auto');
}
}

Animal
31 Dec 2008, 3:22 AM
To summarize, perhaps we need a containerMouseEvents: true config to allow mouse events when not over child nodes. So the changes would be



Ext.override(Ext.DataView, {
onContextMenu : function(e){
var item = e.getTarget(this.itemSelector, this.el);
// 3.0 var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
var itemIdx = item ? this.indexOf(item) : -1;
if ((itemIdx !== -1) || this.containerMouseEvents) {
this.fireEvent("contextmenu", this, itemIdx, item, e);
}
},

refresh : function(){
// If we are firing mouse events even when not over a child node, then
// fit the height of the DataView to its parent element so that
// mouse events can be detected when few or no child nodes exist.
if (this.containerMouseEvents) {
this.fitHeight.defer(1, this);
}

this.clearSelections(false, true);
this.el.update("");
var records = this.store.getRange();
if(records.length < 1){
if(!this.deferEmptyText || this.hasSkippedEmptyText){
this.el.update(this.emptyText);
}
this.hasSkippedEmptyText = true;
this.all.clear();
return;
}
this.tpl.overwrite(this.el, this.collectData(records, 0));
this.all.fill(Ext.query(this.itemSelector, this.el.dom));
this.updateIndexes(0);
},

// private
// ensure that the DataView fills its containing element
fitHeight: function() {
var e = this.el; // 3.0 this.getTemplateTarget()
// 3.0 var e = this.getTemplateTarget()
var p = Ext.get(e.dom.parentNode);
var pHeight = p.getHeight() - e.getFrameWidth('tb');
if (e.getHeight() < pHeight) {
e.setStyle('height', pHeight + 'px');
} else {
e.setStyle('height', 'auto');
}
}
});