MXStudio » Coldfusion » Ações e eventos

Ações e eventos


Introdução

Em prosseguimento, nesta será descrita algumas propriedades dos componentes Flash Form.

Pré-requisito

Para utilização dos scripts contidos neste tutorial, é necessário o servidor ColdFusion MX 7.0.1 e o servidor MySql 4.1.

Objetivo

Observar várias propriedades para que o usuário tenha maior identificação com o ActionScript.

Conceitos

Começaremos com o método addEventListener, presente na Classe EventDispatcher já apresentada pelo nosso amigo Hugo Ferreia, ela é exatamente a mesma utilizada no ActionScript – CFORM, não vou reescrever sobre o que o Hugo já dicertou, mas vamos relembrar os parâmetros.

componente.addEventListener (eventName, listener):Void;

eventName – Nomenclatura do evento


listener
– Função que será o ouvinte do evento

Observe bem o parâmetro eventName.
Quando criamos um campo com a tag cfinput em um formulário CFFORM – Flash, ele é convertido para um componente Flash similar, por exemplo, um campo cfinput com type definido como text é convertido para o componente TextInput.
Todo componente Flash pode receber um eventlistener através do método addEventListener.
Você pode até não saber usar este método, mas ao definir um atributo onChange ou onClick em uma tag cfinput, durante a conversão que falei estes atributos serão adicionados ao componente através do addEventListener.

Para atribuir uma ação a um evento, crie uma variável do tipo object (similar a struct) onde a key é o nome do evento, e esta key recebe uma função que será a responsável pela execução da ação. Dependendo da sua necessidade, você pode definir um parâmentro do tipo object ou simplesmente não definir parâmentro.
Mas quando o parâmetro
é definido é possível fazer referência ao componente que sofreu o evento, através da key ‘target’. Exemplificando, você cria um cfinput do tipo text, e com o addEventListener definir o onChange, depois pegar o conteúdo do campo através da key target, uma função seguindo o modelo abaixo será necessária.

//objeto que receberá o ouvinte
var listener:Object = {};
//
o ouvinte responderá pelo evento change, e conterá o parâmentro necessário

listener.change = function (evt:Object):Void{
//evt.target == componente
var valor = evt.target.text;
}
componente.addEventListener (‘change’, listener);

Faça uma visita a matéria do Hugo Ferreira para entenderem melhor como funciona este método.

Conteúdo

Este método é um aliado importante, pois existem eventos que não podem ser definidos na tag cfml, como veremos.
Para demostrar isso construiremos um formulário contendo
cfinput e uma tree.

A base de dados

Antes de mais nada implemente um banco para os testes, contendo a seguinte tabela.

Tabela agenda

CREATE TABLE agenda (
id int(11) NOT NULL auto_increment,
nome varchar(70) default NULL,
telefone varchar(15) default NULL,
email varchar(40) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into agenda values (1, ‘Pedro Claudio’, ‘02121xxxx-xxxx’, ‘pcsilva@gmail.com’);

Caso não saiba como executar o código visite a matéria Configurando MySQL no CFMX7, e em seguinda insira este script em uma cfquery, outras dúvidas visite o Fórum ColdFusion.

Implementando

O nosso formulário ficará com o seguinte layout.

Construa o formulário cfform, que é bem básico, você não sentirá dificuldades em reconhecer os comandos, caso já tenha contato com cfml.

Observe os eventos das tags.

<!— cria form —>
<cfform name=”form1″ format=”flash” width=”520″ onload=”#as_onload#” >
<!— cria grupo como panel —>
<cfformgroup id=”oPanel” label=”Agenda” type=”panel” height=”265″>
<!— cria checkbox —>
<cfinput name=”oCheckBox” label=”Visualizar agenda” type=”checkbox” onClick=”#as_oCheckBox#” />
<!— agrupa componentes horizontalmente —>
<cfformgroup type=”horizontal”>
<!— cria components Tree —>
<cftree name=”aTree” width=”150″ height=”140″ />
<cfformgroup id=”grupoCampos” type=”hdividedbox” height=”140″ >
<!— cria componente TextInput —>
<cfinput name=”nome” label=”Nome” type=”text” required=”yes” validate=”noblanks” />
<cfinput name=”email” label=”e-mail” type=”text” required=”yes” validate=”email” />
<cfinput name=”telefone” label=”Telefone” type=”text” validate=”noblanks” />
<!— agrupa botões excluir, limpar e salvar —>
<cfformgroup type=”horizontal”>
<cfinput name=”bt_del” type=”button” value=”Excluir” onClick=”#as_bt_del#” />
<cfinput name=”bt_limpar” type=”button” value=”Limpar” onClick=”#as_bt_limpar#” />
<cfinput name=”bt_salvar” type=”button” value=”Salvar” onClick=”#as_bt_salvar#” />
</cfformgroup>
</cfformgroup>
</cfformgroup>
<!— cria uma linha similar ao HR do html —>
<cfformitem type=”hrule” />
<!— cria checkbox para exibição do log —>
<cfinput name=”oLog” label=”Exibir log” type=”checkbox” onClick=”#as_oLog#” />
</cfformgroup>
<!— textarea exibira o log —>
<cftextarea name=”texto” height=”88″ style=”font-size:9px; margin-left:1″ visible=”no” />
</cfform>

Como foi visto nos eventos das tags, será inserido muito actionscript.

Ao clicar no checkbox que possui o label
‘Visualizar agenda’, o código a ser executado buscará dados no banco e atribuirá ao componente Tree, ou limpará a Tree e informará a ação no textarea.

<!— código é executado quando do click no checkbox —>
<cfsavecontent variable=”as_oCheckBox”>
//verifica se checkbox está selecionado, estando recupera dados
if(_root.oCheckBox.selected){
_root.texto.htmlText = ‘<li>[Remoting] Solicitando dados</li>’ + _root.texto.htmlText;
_global.Agenda(‘get’,{});
}else{
_root.aTree.dataProvider = null;
_root.texto.htmlText = ‘<li>[Remoting] destruindo tree</li>’ + _root.texto.htmlText;
}
</cfsavecontent>

No click do checkbox que possui o label
Exibir log, exibirá ou ocultará o textarea contendo o log, informando a ação ocorrida.

<!— código é executado quando do click no checkbox para exibição de log —>
<cfsavecontent variable=”as_oLog”>
if(_root.oLog.selected){
_root.texto.visible = true;
_root.texto.htmlText = ‘<li>[Log] Exibindo log</li>’ + _root.texto.htmlText;
}else{
_root.texto.visible = false;
_root.texto.htmlText = ‘<li>[Log] Ocultando log</li>’ + _root.texto.htmlText;
}
</cfsavecontent>

Para limpar o formulário utilizaremos o seguinte script.

<!— código é executado quando do click no botão excluir —>
<cfsavecontent variable=”as_bt_limpar”>
//limpa campos e validadores
_root.nome.text = ”;
_root.email.text = ”;
_root.telefone.text = ”;
_root.disableAllValidators();
_root.enableAllValidators();
CFFormValidators.resetInValidFields();
_root.aTree.selectedNode = null;
</cfsavecontent>

A ação de exclusão também é bem simples.

<!— código é executado quando do click no botão excluir —>
<cfsavecontent variable=”as_bt_del”>
//verifica se a tree possui um nó selecionado
if(_root.aTree.selectedNode != undefined){
var arg = {};
arg.id = _root.aTree.selectedNode.attributes.data;
_global.Agenda(‘del’,arg);
}
</cfsavecontent>

Daqui por diante peço que tenha bastante atenção.
Este script possui uma regra simples para saber qual direção tomar quando o botão salvar for clicado, se vai ser uma inclusão ou uma alteração. Partindo do princípio que depois da tree estando selecionada, não há como o cliente retirar a selação, este será o nosso controle. A tree possuindo seleção, os dados do formulário serão para atualizar, do contrário é uma inclusão.

<!— código é executado quando do click no botão salvar — >
<cfsavecontent variable=”as_bt_salvar”>
//inicia validação
CFFormValidators.resetInValidFields();
//valída formulário
if(mx.validators.Validator.isStructureValid(_root, ‘form1′)){
var arg = {};
arg.nome = _root.nome.text;
arg.telefone = _root.telefone.text;
arg.email = _root.email.text;
//testa se existe nó selecionado
if(_root.aTree.selectedNode == undefined){
//não existe seleção na tree, a inserção será executada
_global.Agenda(‘add’,arg);
}else{
//existe nó selecionado, recupera id do nó
arg.id = _root.aTree.selectedNode.attributes.data;
//executa update
_global.Agenda(‘edit’,arg);
}
}else{
//existindo erros na validação o popup é exibido
_root.userOnError();
}
</cfsavecontent>

Aqui foi criada uma chamada remoting que permitisse uma reutilização da função. Este código será adicionado ao atributo onLoad da tag CFFORM.

<!— a execução deve acontecer antes de qualquer ação—>
<cfsavecontent variable=”as_onload_global_agenda”>
//função utilizada para todoas as comunicações de dados
_global.Agenda = function(type,arg){
var mensagem = “”;
//depedendo do tipo da ação são criados parâmtros ou destruídos
switch(type){
case “edit”:
mensagem =”Contato atualizado”;
break;
case “add”:
mensagem =”Novo contato adicionado”;
break;
case “del”:
mensagem =”Contato excluído”;
break;
case “get”:
_root.nome.text = ”;
_root.email.text = ”;
_root.telefone.text = ”;
_root.disableAllValidators();
_root.enableAllValidators();
CFFormValidators.resetInValidFields();
_root.aTree.selectedNode = null;
mensagem =”Reconstruindo tree”;
break;
}
//exibe cursor clock
mx.managers.CursorManager.setBusyCursor();
var gatewayurl:String = “http://localhost:8080/cfusion/flashservices/gateway”;
var responseHandler = {};
responseHandler.onResult = function( result ):Void {
//deleta cursor clock
mx.managers.CursorManager.removeBusyCursor();
if(result){
//verifica se ação é recuperação de daods, sendo irá abrir o primeiro nó
if(type == “get”){
_root.aTree.dataProvider = null;
_root.aTree.dataProvider = result;
_root.aTree.setIsOpen(_root.aTree.getTreeNodeAt(0),true,null,null);
}else{
_global.Agenda(‘get’,{});
}
_root.texto.htmlText = “<li>[Remoting] “+mensagem+”</li>” + _root.texto.htmlText;
}else{
_root.texto.htmlText = “<li>[Remoting][Erro query] Não foi possivel manipular os dados</li>” + _root.texto.htmlText;
}
}
responseHandler.onStatus = function( stat: Object ):Void {
mx.managers.CursorManager.removeBusyCursor();
_root.texto.htmlText = “<li>[Remoting] +stat.description+</li>” + _root.texto.htmlText;
}
var gatewayConnection = mx.remoting.NetServices.createGatewayConnection(gatewayurl);
var Service = gatewayConnection.getService(“mxstudio.agenda.entradas”, responseHandler);
//dependendo do tipo da ação uma função será excutada
switch(type){
case “edit”:
Service.update(arg);
break;
case “add”:
Service.set(arg);
break;
case “del”:
Service.del(arg);
break;
case “get”:
Service.get(arg);
break;
}
}
</cfsavecontent>

Para obter um controle maior sobre as eventos na tree, devemos saber quais eventos devem ser implementados, são eles:

nodeOpen – evento disparado quando um nó é aberto;
nodeClose – o oposto do anterior.
Estes eventos são específicos de uma Tree, isso não quer dizer que a tree não possua outros eventos.
Além disso poderá ser vistos alguns métodos, pelos quais podemos saber o que está acontecendo na tree, são eles:

Tree.getTreeNodeAt(index) – retorna o nó referente ao índice,

Tree.getIsBranch(nó_selecionado) – retorna true quando o nó selecionado é uma pasta

Tree.getIsOpen(nó_selecionado) – retorna true se a pasta estiver aberta,
Tree.selectedNode – propriedade onde todas as informações do nó selecionado estarão.
Este código será adicionado ao atributo onLoad da tag CFFORM.

<!— a execução deve acontecer antes de qualquer ação—>
<cfsavecontent variable=”as_onload_create_listener”>

// encapsulamento do código comum aos listeners
var createLog = function(action,target){
//verifica se existe um nó selecionado
if(target.selectedNode == undefined){
//Seleciona o primeiro nó da tree
target.selectedNode = target.getTreeNodeAt(0);
}
//recupera dados do item selecionado
var oNode = target.selectedNode;
//recupera o texto exibido no nó
var Texto = oNode.attributes.label;
//verifica se o nó selecionado é uma pasta
if(_root.aTree.getIsBranch(target.selectedNode)){
//verifica se a pasta seleciona está aberta
Texto = (_root.aTree.getIsOpen(target.selectedNode))?”Foi aberta a pasta “:”Foi fechada a pasta “;
Texto += oNode.attributes.label;
}
//atribui a informação ao textarea
_root.texto.htmlText = “<li>["+action+"] “+Texto+”</li>” + _root.texto.htmlText;
}

//cria objeto para receber eventos
var Listener:Object = {};

//evento é disparado quando nó é aberto
Listener.nodeOpen = function(evt) {
createLog(“nodeOpen”,evt.target);
};

//evento é disparado quando nó é fechado
Listener.nodeClose = function(evt) {
createLog(“nodeClose”,evt.target);
};

//evento é disparado quando nó é selecionado
Listener.change = function(evt) {
createLog(“change”,evt.target);
//verifica se nó é uma pessoa, sendo pessoa preenche campos para edição
if(!_root.aTree.getIsBranch(evt.target.selectedNode)){
_root.nome.text = evt.target.selectedNode.attributes.label;
_root.email.text = evt.target.selectedNode.attributes.email;
_root.telefone.text = evt.target.selectedNode.attributes.telefone;
_root.enableAllValidators();
}
};

//atribui cada uma dos eventos à tree, pode ser feito de outra forma
_root.aTree.addEventListener(“nodeOpen”, Listener);
_root.aTree.addEventListener(“nodeClose”, Listener);
_root.aTree.addEventListener(“change”, Listener);
_root.aTree.addEventListener(“load”, Listener);

</cfsavecontent>

Um pequena pausa.

Bom, falei de nó que não acaba mais, a estrutura de dados de uma Tree é um XML no seguinte formato.

<root data=” label=’Agenda’>
<filho data=’1′ label=’pedro’ />
</root>

Mas como foi visto no ouvinte do evento change, retirei mais informações do nó, isto porque o xml que criei tem o seguinte formato.

<root data=” label=’Agenda’>
<filho data=’1′ label=’pedro’ email=’email@email’ telefone=’1111111′ />
</root>

Caso seja necessário criar nós em sequência, ou sub-pastas, você pode alterar o xml de forma que lhe atenda, porém os atributos data e label devem existir sempre.

<root data=” label=’Agenda’>
<filho data=’1′ label=’pedro’ email=’email@email’ telefone=’1111111′ >
<neto data=’1′ label=’pedro’ email=’email@email’ telefone=’1111111′ />
</filho>
</root>

Nós já criamos dois scripts que serão atribuidos ao evento onload do CFFORM, agora vamos junta-los e ainda colocar mais algum código.

<!— a execução deve acontecer antes de qualquer ação—>
<cfsavecontent variable=”as_onload”>
//agrupa código para atribuição ao onload do cfform
<cfoutput>#as_onload_global_agenda#</cfoutput>
<cfoutput>#as_onload_create_listener#</cfoutput>
_root.texto.editable =false;
_root.texto.selectable =false;
_root.texto.html = true;
</cfsavecontent>

Com isso a pagina CFM está concluída.
Agora apenas vejamos o código CFC.

entradas.cfc

<cfcomponent>
<cffunction name=”get” access=”remote” output=”false” description=”Método utulizado para recuperar dados”>

<!— recupera dados —>
<cfquery name=”getAgenda” datasource=”mxstudio” >
select id, nome, telefone, email from agenda
</cfquery>

<!— cria variável contendo dado no padrão xml —>
<cfset xmlDoc =”<node data=” label=’Agenda’>” />
<cfloop query=”getAgenda”>
<cfset xmlDoc =xmlDoc&”<node data=’#getAgenda.id#’ label=’#getAgenda.nome#’ ” />
<cfset xmlDoc =xmlDoc&” telefone=’#getAgenda.telefone#’ email=’#getAgenda.email#’ />” />
</cfloop>
<cfset xmlDoc =xmlDoc&”</node>” />

<!— retorna xml —>
<cfreturn XMLParse(xmlDoc) />
</cffunction>

<cffunction name=”set” access=”remote” output=”false” description=”Método utilizado para inserção de dados na database”>

<!— define parâmetros —>
<cfargument name=”nome” type=”string” required=”yes” />
<cfargument name=”telefone” type=”string” required=”yes” />
<cfargument name=”email” type=”string” required=”yes” />

<!— inicia prevenção de erros —>
<cftry>

<!— insere dados na database —>
<cfquery datasource=”mxstudio” >
insert into agenda (nome, telefone, email) values (
<cfqueryparam cfsqltype=”cf_sql_varchar” value=”#Arguments.nome#” />,
<cfqueryparam cfsqltype=”cf_sql_varchar” value=”#Arguments.telefone#” />,
<cfqueryparam cfsqltype=”cf_sql_varchar” value=”#Arguments.email#” />
)
</cfquery>
<cfcatch type=”database”>

<!— caso ocorra algum erro retornará false —>
<cfreturn false />
</cfcatch>
</cftry>

<!— retornará true caso a inserção seja bem sucedida —>
<cfreturn true />
</cffunction>

<cffunction name=”update” access=”remote” output=”false” description=”método utilizado para atualiar um registro da database”>

<!— define parâmetros —>
<cfargument name=”id” type=”numeric” required=”yes” />
<cfargument name=”nome” type=”string” required=”yes” />
<cfargument name=”telefone” type=”string” required=”yes” />
<cfargument name=”email” type=”string” required=”yes” />

<!— inicia prevenção de erros —>
<cftry>

<!— atualiza dados na database —>
<cfquery datasource=”mxstudio” >
update agenda
set nome = <cfqueryparam cfsqltype=”cf_sql_varchar” value=”#Arguments.nome#” />,
telefone = <cfqueryparam cfsqltype=”cf_sql_varchar” value=”#Arguments.telefone#” />,
email = <cfqueryparam cfsqltype=”cf_sql_varchar” value=”#Arguments.email#” />
where id = <cfqueryparam cfsqltype=”cf_sql_integer” value=”#Arguments.id#” />
</cfquery>

<cfcatch type=”database”>

<!— caso ocorra algum erro retornará false —>
<cfreturn false />
</cfcatch>

</cftry>

<!— retornará true caso a atualização seja bem sucedida —>
<cfreturn true />
</cffunction>

<cffunction name=”del” access=”remote” output=”false” description=”Método usado para excluir um registro na database”>

<!— define parâmetro —>
<cfargument name=”id” type=”numeric” required=”yes” />

<!— inicia prevenção de erros —>
<cftry>

<!— deleta dados na database —>
<cfquery datasource=”mxstudio” >
delete from agenda
where id = <cfqueryparam cfsqltype=”cf_sql_integer” value=”#Arguments.id#” />
</cfquery>
<cfcatch type=”database”>

<!— caso ocorra algum erro retornará false —>
<cfreturn false />
</cfcatch>
</cftry>

<!— retornará true caso a exclusão seja bem sucedida —>
<cfreturn true />
</cffunction>

</cfcomponent>

Nosso formulário ao final.


Pedro Claudio – pcsilva@mxstudio.com.br
visite o fórum MXStudio ColdFusion

FormatCF(new Array(‘form.cfm_f’,'form.cfm_g’,'form.cfm_h’,'form.cfm_i’,'form.cfm_j’,'form.cfm_k’));
FormatCF(new Array(‘form.cfm_a’,'form.cfm_b’,'form.cfm_c’,'form.cfm_d’,'form.cfm_e’));
FormatCF(new Array(‘form.cfm_l’,'form.cfm’));


Deixe um Comentario

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="">

Pedro Claudio

Últimos Artigos do Autor