Acentuação no Sort do DataGrid
Continuando o caso do Sort no DataGrid, que no post anterior em http://blog.dclick.com.br/2007/06/02/alterando-o-sort-default-do-datagrid-de-case-sensitive-para-case-insensitive/
onde foi relatado como se utilizar a propriedade caseInsensitive, chegamos agora no problema de tratamento de ordenação de palavras acentuadas com palavras não acentuadas. O sort executado, não consegue identificar, a partir do locale de países de língua portuguesa, que palavras acentuadas devem ser tratadas da mesma maneira que palavras sem acentuação para o caso de ordenação. Ou seja, árvore é igual a arvore quando mostramos em ordem num grid.
A solução para este caso, reside no fato da classe SortField ser responsável pela definição de qual função de comparação será usada em objetos do tipo string, para identificar a ordem. Assim com a simples extensão desta classe (ExtendedSortField), conseguimos indicar qual função de ordenação de strings deve ser usada internamente para o resultado esperado.
-
package sort
-
{
-
import mx.collections.SortField;
-
import mx.utils.ObjectUtil;
-
import mx.core.mx_internal;
-
-
use namespace mx_internal;
-
-
public class ExtendedSortField extends SortField
-
{
-
-
override mx_internal function initCompare(obj:Object):void
-
{
-
var isStringField:Boolean = false;
-
-
// if the compare function is not already set then we can set it
-
if (!usingCustomCompareFunction)
-
{
-
if (!numeric)
-
{
-
if (caseInsensitive)
-
isStringField = true;
-
else
-
{
-
// we need to introspect the data a little bit
-
var value:Object;
-
if (name)
-
{
-
try
-
{
-
value = obj[name];
-
}
-
catch (error:Error)
-
{
-
}
-
}
-
//this needs to be an == null check because !value will return true
-
//where value == 0 or value == false
-
if (value == null)
-
{
-
value = obj;
-
}
-
-
var typ:String = typeof(value);
-
switch (typ)
-
{
-
case "string":
-
isStringField = true;
-
break;
-
case "object":
-
if (!(value is Date))
-
{
-
isStringField = true;
-
var test:String;
-
try
-
{
-
test = value.toString();
-
}
-
catch (error2:Error) {}
-
if (!test || test == "[object Object]")
-
{
-
isStringField = false;
-
}
-
}
-
break;
-
}
-
} // else
-
}
-
} // if
-
-
if (isStringField)
-
{
-
compareFunction = stringCompare;
-
}
-
-
super.initCompare(obj);
-
}
-
-
/**
-
* Pull the strings from the objects and call the implementation.
-
*/
-
private function stringCompare(a:Object, b:Object):int
-
{
-
var fa:String;
-
try
-
{
-
fa = name == null ? String(a) : String(a[name]);
-
}
-
catch (error:Error)
-
{
-
}
-
-
var fb:String;
-
try
-
{
-
fb = name == null ? String(b) : String(b[name]);
-
}
-
catch (error:Error)
-
{
-
}
-
-
var sa:String = "";
-
if (fa != null)
-
{
-
sa = String(mx.utils.ObjectUtil.copy(fa));
-
sa = removeSpecialChars(sa);
-
}
-
-
var sb:String = "";
-
if (fb != null)
-
{
-
sb = String(mx.utils.ObjectUtil.copy(fb));
-
sb = removeSpecialChars(sb);
-
}
-
-
return mx.utils.ObjectUtil.stringCompare(sa, sb, caseInsensitive);
-
}
-
-
/**
-
*
-
* @param value String de entrada que será modificada de acorde com a tabela ASCII extendida
-
* @return String alterada
-
*
-
*/
-
public static function removeSpecialChars(value:String):String
-
{
-
var patternTable:Object = new Object();
-
patternTable["A"] = /À|Á|Â|Ã|Ä|Å/g;
-
patternTable["E"] = /È|É|Ê|Ë/g;
-
patternTable["I"] = /Ì|Í|Î|Ï/g;
-
patternTable["O"] = /Ò|Ó|Ô|Õ|Ö/g;
-
patternTable["U"] = /Ù|Ú|Û|Ü/g;
-
patternTable["a"] = /à|á|â|ã|ä/g;
-
patternTable["e"] = /è|é|ê|ë/g;
-
patternTable["i"] = /ì|í|î|ï/g;
-
patternTable["o"] = /ò|ó|ô|õ|ö/g;
-
patternTable["u"] = /ù|ú|û|ü/g;
-
patternTable["C"] = /Ç/g;
-
patternTable["c"] = /ç/g;
-
patternTable["N"] = /Ñ/g;
-
patternTable["n"] = /ñ/g;
-
-
var result:String = value;
-
for (var letter:String in patternTable)
-
{
-
result = result.replace(patternTable[letter], letter);
-
}
-
return result;
-
}
-
}
-
}
Mas para que isso funcione, devemos antes preparar o sort do dataProvider do DataGrid, adicionando neste, conforme o usuário interage com a coluna em questão, os fields do tipo de nossa classe extendida (ExtendedSortField).
Estendendo também a classe DataGrid, adicionamos no seu construtor um listener para o evento DataGridEvent.HEADER_RELEASE.
-
public function ExtendedDataGrid()
-
{
-
// Como o listener foi criado com a mesma prioridade do listener da classe mãe,
-
// este deve ser adicionado ANTES da adição do mesmo da classe mãe,
-
// para que esta implementação seja executada da mesma forma, ANTES.
-
addEventListener(DataGridEvent.HEADER_RELEASE,
-
headerReleaseHandler,
-
false, EventPriority.DEFAULT_HANDLER, true);
-
-
super();
-
}
No handler desse evento, preparamos o dataProvider com o sort adequado.
-
private function headerReleaseHandler(event:DataGridEvent):void
-
{
-
if (!event.isDefaultPrevented())
-
{
-
prepareGridColumnSort(this, dataProvider as ICollectionView,
-
-
event.dataField, !sortCaseSensitive);
-
}
-
}
-
-
/**
-
*
-
* @param grid Instância do DataGrid que será preparado para utilização do caseInsensitive e Numeric
-
* @param gridDataProvider DataProvider do DataGrid, que será observado para criação da classe Sort
-
* @return DataProvider modificado, contendo a classe Sort e SortField definida para cada DataGridColumn do DataGrid
-
*
-
*/
-
private function prepareGridColumnSort(grid:DataGrid, gridDataProvider:ICollectionView, dataField:String, caseInsensitive:Boolean=true):void
-
{
-
var sort:Sort;
-
var field:SortField;
-
var column:DataGridColumn;
-
var bFieldFound:Boolean = false;
-
-
if (gridDataProvider && dataField)
-
{
-
sort = gridDataProvider.sort;
-
-
if (sort == null)
-
{
-
sort = new Sort();
-
}
-
-
for each (field in sort.fields)
-
{
-
if (field.name == dataField)
-
{
-
field.caseInsensitive = caseInsensitive;
-
bFieldFound = true;
-
break;
-
}
-
}
-
-
if (!bFieldFound)
-
{
-
for each (column in grid.columns)
-
{
-
if (dataField == column.dataField)
-
{
-
field = new ExtendedSortField();
-
field.name = column.dataField;
-
field.descending = column.sortDescending;
-
field.caseInsensitive = caseInsensitive;
-
if (column.sortCompareFunction != null)
-
{
-
field.compareFunction = column.sortCompareFunction;
-
}
-
field.numeric = isDataFieldNumber(gridDataProvider, dataField);
-
sort.fields = [field];
-
break;
-
}
-
}
-
}
-
-
gridDataProvider.sort = sort;
-
}
-
}
-
-
/**
-
*
-
* @param gridDataProvider Instância do DataGrid no qual será testado o campo do tipo Number
-
* @param dataField Nome do campo que será testado
-
* @return Resultado boolean indicando se é Number ou não
-
*
-
*/
-
private function isDataFieldNumber(gridDataProvider:ICollectionView, dataField:String):Boolean
-
{
-
if (gridDataProvider && gridDataProvider.length > 0 && dataField)
-
{
-
var obj:Object = gridDataProvider[0];
-
if (obj.hasOwnProperty(dataField) && ((obj[dataField] is Number) || (obj[dataField] is uint) || (obj[dataField] is int)))
-
{
-
return true;
-
}
-
}
-
return false;
-
}
Após estes passos, toda vez que o usuário clicar no cabeçalho de uma coluna, este evento será capturado primeiro pela nossa função handler que irá preparar o sort do dataProvider do DataGrid com nossa classe ExtendedSortField.
Esta por sua vez, sabe como comparar valores string acentuadas, retirando os caracteres especiais antes de efetuar a comparação.
Um comentário para “Acentuação no Sort do DataGrid”
Show de bola!!!
Adicionar comentário
Show de bola!!!

