PDA

View Full Version : View Selection handling, proposed change.



rad_nq
16 Mar 2007, 7:18 AM
The following code submission was done on a subclass of JsonView, but hopefully this can be put into the *official* build.

1) Currently JsonView when handling selection of items does not follow Windows/OS X/ Linux standard UI practice. Meaning if you have selected 5 items and CTRL-Click on a selected item it does not de-select.

2) Also, currently selection does not take into account the selected item may already be selected so it does a clearSelections and then selects the same one. Causing a new selection event, from a UI perspective the selection has NOT changed.
Note: This only happens in certain cases. For example if you use a DragZone over top of a JsonView as in the Photo album example the ImageDragZone selects the item when it is clicked. The DragZone allows click to pass through to the JsonView on simple click as it is not a DnD event, the JsonView then re-selects the same item causing this.


The following code consists of a few minor tweaks to the YAHOO.ext.JsonView (1.0 appears to have same code).

//the only bit of magic here is IF the last item in selection list was clicked and removed, we adjust
//this.lastSelection to point to the new last item in selection array.
//Part of this is because the selection list can change outside of this method, (Drag events).


onItemClick : function(item, index, e){
if(this.fireEvent('beforeclick', this, index, item, e) !== false){
if(this.multiSelect || this.singleSelect){
if(this.multiSelect && e.shiftKey && this.lastSelection){
this.select(this.getNodes(this.indexOf(this.lastSelection), index), false);
this.lastSelection = this.getSelectedNodes()[this.getSelectionCount() - 1];//Needed for CTRL de-select.
}else{
//If the last selection is at the end of the selection array then
//check for deselection (
var normalSelect = true;
if(this.multiSelect && e.ctrlKey){
var oldSelect = this.getSelectedNodes();
if(this.lastSelection == oldSelect[oldSelect.length - 1]){
var index = oldSelect.indexOf(item);
if(index >= 0){//If this item is already selected, de-select.
var selection=oldSelect.concat([]);//Copy array so we can pass to select.
selection.splice(index, 1);//REMOVE current item.
this.select(selection, false);
normalSelect = false;
if(this.lastSelection == item){
this.lastSelection = selection[selection.length -1 ];
}
}
}
}
if(normalSelect){
this.select(item, this.multiSelect && e.ctrlKey);
this.lastSelection = item;
}
}
e.preventDefault();
}
return true;
}else{
return false;
}
},


//Added logic here, we do not clearSelection even if keepExisting is false IF we have single selection
//and nodeInfo is already selected.


select : function(nodeInfo, keepExisting, suppressEvent){
if(nodeInfo instanceof Array){
if(!keepExisting){//In the event of an array, clear all the selections.
this.clearSelections(true);
}
for(var i = 0, len = nodeInfo.length; i < len; i++) {
this.select(nodeInfo[i], true, true);
}
}else{//In the event of a single selection, do not re-add if this node is already selected.
var node = this.getNode(nodeInfo);
if(node){
var isSelected = this.isSelected(node);
//If multiple items are selected and we are going to single selection
if(!keepExisting && this.getSelectedNodes().length > 1){
this.clearSelections(true);
this.select(nodeInfo, keepExisting, true);//supress event, but beforeselect will still be fired.
}else if(!isSelected){//is current node part of selection.
if(!keepExisting){
this.clearSelections(true);
}
if(this.fireEvent('beforeselect', this, node, this.selections) !== false){
YAHOO.util.Dom.addClass(node, this.selectedClass);
this.selections.push(node);
}
}else {
suppressEvent = true;//There was no clear selection made, and no selection added. Do not fire event.
}
}
}
if(!suppressEvent){
this.fireEvent('selectionchange', this, this.selections);
}
},

rad_nq
16 Mar 2007, 7:37 AM
View.clearSelections still fires events even when there is no selection. This happens when using a JsonView and under the 0.4 code base between object creation and jview.load(..) finishing there are 2 selection events fired due to refresh(..) clearing selection.


The main if statement in clearSelections needs:


&& this.selections && this.selections.length > 0
added.
So in 0.4

if(this.multiSelect || this.singleSelect){
becomes

if((this.multiSelect || this.singleSelect) && this.selections && this.selections.length > 0){