Verdade seja dita: trabalhar com “itemRenderers” e “itemEditors” no Flex não é tão fácil quanto parece. Não é incomum as pessoas postarem dúvidas sobre este assunto nas listas de discussão pela Net a fora. É por isso que eu sempre recomendo fortemente a leitura do capitulo “Using Item Renderers and Item Editors” da documentação.
Uma alteração comum que as pessoas geralmente querem no funcionamento do List - e que pode ser resolvida com a ajuda de um “ItemRenderer”- consiste em permitir ao usuário selecionar múltiplos itens sem ter que pressionar o CTRL. Recentemente abriram uma thread na FlexDev sobre isso e eu fiz uma implementação que acho que ficou simples.
Leia o artigo completo »
- Por Beck Novaes em 25/October/2007
- 2 Comentários »
No Translations
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.
Actionscript:
-
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.
Actionscript:
-
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.
Actionscript:
-
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.
- Por Marcello Rego em 18/October/2007
- 1 Comentário »
No Translations
Finalmente uma emissora de TV Brasileira resolveu disponibilizar uma aplicação de qualidade para seus vídeos na Web. O site Mundo Record é show de bola. Não me conformo como a toda poderosa Rede Globo ainda continua com o Windows Media Vídeo. Eu nunca consigo assistir nada por lá.

Os vídeos do Terra também são muito ruins de assitir! Terrível experiência para o usuário.
Ou seja, hoje em dia se não for Flash Vídeo eu nem perco o meu tempo. Fazer download de Codec? Buffering demorado? Esqueça!
Engraçado é que há alguns anos atrás eu via muita gente dizer que e Flash ia morrer, que o Flash era ruim para a Web, etc. Eu adoraria saber o que estas pessoas pensam agora com a explosão do Flash Vídeo e com o crescimento das RIAs.
- Por Beck Novaes em 11/October/2007
- 8 Comentários »
No Translations
Ontem foi, para mim, a melhor sessão que ocorre em todas as MAX, os Sneak Peacks. Para quem não sabe, essa sssão mostra os desenvolvimentos e inovações para as próximas versões dos produtos da Adobe. Inclusive existe a possibilidade que algumas dessas inovações não serem publicadas.
Poderia ficar escrevendo muito sobre isso, mas recomendo que vejam no YouTube os vídeos da MAX. Algumas das principais novidades foram:
Integração do Flash com C e C++;
O exemplo dado foi colocar mensagens feitas em Flex por cima do Counter Strike (ou jogo semelhante).
Flash Player incorporado ao Acrobat Reader;
Exemplos muito interessantes de vídeo dentro do Reader, conferência de dentro de um documento com os participanetes que estão lendo o mesmo, encontrar locais no Yahoo! Maps a partir do texto que está no Reader enfim, qualquer .swf dentro de um PDF.
Possibilidade de desenhar articulações do Flash;
Realmente é uma grande novidade. O exemplo foi rápido e de grande impacto. O palestrante desenhou 3 elipses simulando um braço, colocou o novo objeto de articulação nas justas e pronto!!! O braço estava arituculado com movimentos reais. No final ele mostrou um inseto ariculado com no máximo 40 linhas de código. Muito bom!!!
Mudança no modo como se faz animações no Flash;
Esse é muito difícil de explicar. Pense que não existirá mais keyframes. Veja o vídeo.
Flex Builder para Linux (já postado);
Photoshop Express (já postado);
Foi apresentado o novo contratado da Adobe, assunto de um post do Beck;
Semana que vem devo estar fazendo posts mais técnicos sobre as novidades que vi por aqui. Principalmente a nova arquitetura de componentes mostrada por Ely Greenfield na sessão Flex Roadmap e várias dicas de otimização de AS3, visando performance.
Assistam os vídeos!!! Procurem por MAX 2007.
- Por Rafael Martinelli em 3/October/2007
- 4 Comentários »
No Translations
Antes tarde do que nunca!!! Saiu o alpha do Flex Builder para Linux http://labs.adobe.com/technologies/flex/flexbuilder_linux/
A demo feita na MAX foi com Ubuntu.
Enjoy!!!
- Por Rafael Martinelli em 3/October/2007
- 2 Comentários »
No Translations
Seguindo na linha dos serviços, acabamos de ver um Sneak Peak mostrando o Photoshop Express. É um editor de imagem na web feito em Flex com recursos essenciais, mas muito bem feito. A idéia é muito boa pois engloba colaboração. mas ainda não tem nem data para sair.
Para onde eles estão indo? Competir com Google, Yahoo! e Microsoft em serviços????? Eis a questão!!!!
- Por Rafael Martinelli em 2/October/2007
- Nenhum Comentário »
No Translations
Desde ontem, em virtude da MAX, uma série de updates e novos produtos estão disponíveis no Adobe Labs. Alguns deles são:
Flex 3 beta 2;
Air beta 2;
Dreamweaver Extension for AIR
Flash Air Extension
Buzzword beta
Aproveitem!!!
- Por Rafael Martinelli em 2/October/2007
- 1 Comentário »
No Translations