Mostrando postagens com marcador BDS. Mostrar todas as postagens
Mostrando postagens com marcador BDS. Mostrar todas as postagens

quarta-feira, 15 de abril de 2009

Validação de CPF e CNPJ com Javascript - Delphi/Intraweb

Mais um da série ... (da séria série ...)
Ok, já fizemos vários artigos sobre como usar Javascript no Intraweb. Tenho gastado tempo registrando essa abordagem por vários motivos:

Um deles é (uma tecla que venho batendo bastante) a importância de buscar um equilíbrio, distribuído responsabilidades entre client-side e server-side (obviamente, me refiro ao contexto restrito os sistemas desenvolvidos para plataforma web). Um segundo motivo pode ser: “Como fazer isso, se eu uso Delphi/Intraweb?” Na medida em que essa é uma questão que considero possuir alguma relevância. Outro motivo, porem, trata sobre “Qual implicação, ou quais implicações, terei ao percorrer este caminho?” Tenho procurado, nos assuntos abordados, trazer alguns elementos que apontem para a responder a essa questão.
Justamente, esse último ponto, sobre as implicações, ou seja, falar sobre algumas vantagens e desvantagens, é um dos objetivos desse texto. No Intraweb existem certas particularidades ao se aplicar o Javascript, uma delas é o evento “onSubmit” do form definido numa página web. Veremos, então, sobre isso mais adiante.


Neste artigo pretendo mostrar também como podemos usar a passagem por parâmetro, de uma função Javascript, para a referência de um objeto “html” de um form no Intraweb. Seguindo a metodologia de ir do mais simples para o mais complexo, iniciaremos nossa parte prática com a criação de uma função para validação no lado cliente. Validação essa para a qual atribuiremos a responsabilidade de exemplificar esse uso de parâmetros, ao qual me referi, em Javascript, relacionado aos objetos Intraweb.
Quero usar um exemplo que seja prático, ordinário, para um cenário de sistemas de informação. Portanto, vamos criar uma função para validar CPF, uma outra para validar CNPJ e uma terceira função que vai opcionalmente validar CNPJ, CPF, ou os dois simultaneamente. Desta forma teremos uma função polivalente (a qual servirá para validar ambos os casos), cujo o processamento será realizado no lado do cliente.


Javascript para validar CNPJ, CPF no Delphi/Intraweb

Inicie um novo projeto Intraweb no Delphi, adicione no IWForm1 um IWEdit e três IWButtons. Em seguida, defina uma área de declarações de constantes e digite conforme ilustrado abaixo:


implementation

uses IWBaseForm;

{$R *.dfm}
const
AQuebraLinhaJsZN = #13;
AFncCriticaCIC =
' function CriticaCIC(ZnNumCic, ZnCnpjBool, ZnCpfBool){ ' + AQuebraLinhaJsZN +
' alert("www.estacaozn.blogspot.com verifica CPF/CNPJ");' + AQuebraLinhaJsZN +
' var CicValidoZn = false; ' + AQuebraLinhaJsZN +
' ' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && !ZnCpfBool) { ' + AQuebraLinhaJsZN +
' if(!ZnVerificaCnpj(ZnNumCic)){ ' + AQuebraLinhaJsZN +
' alert("CNPJ Inválido"); ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' else if (!ZnCnpjBool && ZnCpfBool){ ' + AQuebraLinhaJsZN +
' if (!ZnVerificaCPF(ZnNumCic)){ ' + AQuebraLinhaJsZN +
' alert("CPF inválido"); ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' ;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' else { ' + AQuebraLinhaJsZN +
' CicValidoZn = ZnVerificaCnpj(ZnNumCic); ' + AQuebraLinhaJsZN +
' if(CicValidoZn){ ' + AQuebraLinhaJsZN +
' return true;} ' + AQuebraLinhaJsZN +
' else{ ' + AQuebraLinhaJsZN +
' CicValidoZn = ZnVerificaCPF(ZnNumCic); ' + AQuebraLinhaJsZN +
' if(!CicValidoZn){ ' + AQuebraLinhaJsZN +
' alert("CIC Inválido") ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' var ZnMsg = ""; ' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CPJ ou CNPJ"; }' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && !ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CNPJ"; }' + AQuebraLinhaJsZN +
' if (!ZnCnpjBool && ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CPF"; }' + AQuebraLinhaJsZN +
' alert("Valor Validado Ok, " +ZnMsg + ": " + ZnNumCic.value);' + AQuebraLinhaJsZN +
' return true;} ' + AQuebraLinhaJsZN;

AFncCriticaCPF =
' function ZnVerificaCPF (ZnCpfObj){ ' + AQuebraLinhaJsZN +
' var gmSort = new Array(ZnCpfObj.value.length); ' + AQuebraLinhaJsZN +
' for (i=0; i< ZnCpfObj.value.length; i++){gmSort[i] = ZnCpfObj.value.charAt(i);} ' + AQuebraLinhaJsZN +
' gmSort.sort(); ' + AQuebraLinhaJsZN +
' if (gmSort[0] == gmSort[gmSort.length -1]){ ' + AQuebraLinhaJsZN +
' alert("www.estacaozn.blogspot.com: Os números são iguais: " + ZnCpfObj.value); ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' ZnAuxCal = 0; ' + AQuebraLinhaJsZN +
' for (ZnCont = 0; ZnCont < 9; ZnCont ++) ' + AQuebraLinhaJsZN +
' ZnAuxCal += parseInt(ZnCpfObj.value.charAt(ZnCont)) * (10 - ZnCont); ' + AQuebraLinhaJsZN +
' DgVZn = 11 - (ZnAuxCal % 11); ' + AQuebraLinhaJsZN +
' if (DgVZn == 10 || DgVZn == 11) ' + AQuebraLinhaJsZN +
' DgVZn = 0; ' + AQuebraLinhaJsZN +
' if (DgVZn != parseInt(ZnCpfObj.value.charAt(9))) ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' ZnAuxCal = 0; ' + AQuebraLinhaJsZN +
' for (ZnCont = 0; ZnCont < 10; ZnCont ++) ' + AQuebraLinhaJsZN +
' ZnAuxCal += parseInt(ZnCpfObj.value.charAt(ZnCont)) * (11 - ZnCont); ' + AQuebraLinhaJsZN +
' DgVZn = 11 - (ZnAuxCal % 11); ' + AQuebraLinhaJsZN +
' if (DgVZn == 10 || DgVZn == 11) ' + AQuebraLinhaJsZN +
' DgVZn = 0; ' + AQuebraLinhaJsZN +
' if (DgVZn != parseInt(ZnCpfObj.value.charAt(10))){ ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' //alert("O CPF INFORMADO É VÁLIDO."); ' + AQuebraLinhaJsZN +
' return true; ' + AQuebraLinhaJsZN +
'} ' + AQuebraLinhaJsZN;

AFncCriticaCNPJ =
' function ZnVerificaCnpj(ZNObjInput){' + AQuebraLinhaJsZN +
' var ZnDigitos, ZnDg, ZnSum, ZnCount;' + AQuebraLinhaJsZN +
' var ZnResult, ZnPos, tamanho;' + AQuebraLinhaJsZN +
' var ZnAuxCNPJ = ZNObjInput.value.replace(/\D+/g, "");' + AQuebraLinhaJsZN +
'' + AQuebraLinhaJsZN +
' if (ZnAuxCNPJ.length != 14){' + AQuebraLinhaJsZN +
' ZNObjInput.focus();' + AQuebraLinhaJsZN +
' return false;' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' var gmSort = new Array(ZNObjInput.value.length); ' + AQuebraLinhaJsZN +
' for (i=0; i< ZNObjInput.value.length; i++){gmSort[i] = ZNObjInput.value.charAt(i);} ' + AQuebraLinhaJsZN +
' gmSort.sort(); ' + AQuebraLinhaJsZN +
' if (gmSort[0] == gmSort[gmSort.length -1]){ ' + AQuebraLinhaJsZN +
' alert("www.estacaozn.blogspot.com: Os números são iguais: " + ZNObjInput.value); ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
'' + AQuebraLinhaJsZN +
' ZnAuxTamanho = ZnAuxCNPJ.length - 2' + AQuebraLinhaJsZN +
' ZnDigitos = ZnAuxCNPJ.substring(0,ZnAuxTamanho);' + AQuebraLinhaJsZN +
' ZnDg = ZnAuxCNPJ.substring(ZnAuxTamanho);' + AQuebraLinhaJsZN +
' ZnSum = 0;' + AQuebraLinhaJsZN +
' ZnPos = ZnAuxTamanho - 7;' + AQuebraLinhaJsZN +
' for (ZnCount = ZnAuxTamanho; ZnCount >= 1; ZnCount--){' + AQuebraLinhaJsZN +
' ZnSum += ZnDigitos.charAt(ZnAuxTamanho - ZnCount) * ZnPos--;' + AQuebraLinhaJsZN +
' if (ZnPos < 2)' + AQuebraLinhaJsZN +
' ZnPos = 9;' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' ZnResult = ZnSum % 11 < 2 ? 0 : 11 - ZnSum % 11;' + AQuebraLinhaJsZN +
' if (ZnResult != ZnDg.charAt(0)){' + AQuebraLinhaJsZN +
' ZNObjInput.focus();' + AQuebraLinhaJsZN +
' return false;' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
'' + AQuebraLinhaJsZN +
' ZnAuxTamanho = ZnAuxTamanho + 1;' + AQuebraLinhaJsZN +
' ZnDigitos = ZnAuxCNPJ.substring(0,ZnAuxTamanho);' + AQuebraLinhaJsZN +
' ZnSum = 0;' + AQuebraLinhaJsZN +
' ZnPos = ZnAuxTamanho - 7;' + AQuebraLinhaJsZN +
' for (ZnCount = ZnAuxTamanho; ZnCount >= 1; ZnCount--){' + AQuebraLinhaJsZN +
' ZnSum += ZnDigitos.charAt(ZnAuxTamanho - ZnCount) * ZnPos--;' + AQuebraLinhaJsZN +
' if (ZnPos < 2)' + AQuebraLinhaJsZN +
' ZnPos = 9;}' + AQuebraLinhaJsZN +
'' + AQuebraLinhaJsZN +
' ZnResult = ZnSum % 11 < 2 ? 0 : 11 - ZnSum % 11;' + AQuebraLinhaJsZN +
' if (ZnResult != ZnDg.charAt(1)){' + AQuebraLinhaJsZN +
' ZNObjInput.focus();' + AQuebraLinhaJsZN +
' return false;}' + AQuebraLinhaJsZN +
' else {' + AQuebraLinhaJsZN +
' return true;' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN;


Dando continuidade, para usarmos o que acabamos de definir devemos usar as propriedades específicas dos componentes Intraweb destinadas a trabalhar com Javascript. Elas existem tanto no IWForm (Formulário Delphi para web), quanto nos controles, IWControls.


Evento OnCreate do IWFrom1:



procedure TIWForm1.IWAppFormCreate(Sender: TObject);
begin
(* Atribuindo a propriedade "JavaScript" do IWForm1 as
funções que serão processadas pelo browser*)
Self.JavaScript.Add('');
Self.JavaScript.Add(AFncCriticaCPF);
Self.JavaScript.Add('');
Self.JavaScript.Add(AFncCriticaCNPJ);
Self.JavaScript.Add('');
Self.JavaScript.Add(AFncCriticaCIC);
Self.JavaScript.Add('');
// O IWButton1 vai validar as duas opções CPF e CNPJ
IWButton1.Caption := 'Valida CPF e CNPJ';
IWButton1.Width := 200;
IWButton1.ExtraTagParams.Add(
Format('onClick=CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'true', 'true']));
//O IWButton2 vai validar apenas CPF
IWButton2.Caption := 'Valida CPF';
IWButton2.Width := 200;
IWButton2.ExtraTagParams.Add(
Format('onClick=CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'false', 'true']));
//O IWButton3 vai validar apenas CNPJ
IWButton3.Caption := 'Valida CNPJ';
IWButton3.Width := 200;
IWButton3.ExtraTagParams.Add(
Format('onClick=CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'true', 'false']));
end;


No trecho de código acima, podemos observar, comparando com os exemplos postados nos artigos anteriores, sobre Intraweb e Javascript, que o uso de parâmetros nas funções Javascript para referenciar os objetos do form (na página html), reduz sensivelmente a o número de linhas. Isso melhora a legibilidade do código, consequentimente aumenta a manutenibilidade do mesmo. Visto que, não precisamos usar o temperamental “document.all” (sensível a diversidade de navegadores). Também não precisamos mais do “document.forms[x]”, isso nos abstém da preocupação em referenciar o form específico (Lembra, no Intraweb 8, o framework pode criar vários forms na mesma página?). Obviamente, isso é possível porque a chamada a função esta sendo feita no mesmo form proprietário do objeto que está sendo passado como argumento. Em outras palavras: O objeto que está sendo passado como parâmetro na função critica CIC 2, está definido no mesmo form no qual a função esta sendo chamada.
Entretanto, infelizmente, essa abordagem pode encontrar limitações. Vejamos adiante ....

Sobre as funções de validação de CNPJ e CPF, não estou preocupado com a otimização da lógica que elas implementam. Basiei-me em alguns dos milhares de exemplos que podemos encontrar na web. Com certeza, fiz alguns ajustes. Mas nada que mereça grande atenção, embora elas funcionem corretamente, no sentido de serem eficientes em alcançarem o objetivo que se propõem. Reiterando, o propósito dessa parte do artigo é exemplificar como resolver via Javascript uma validação bastante necessária, uma situação comum, presumo, em muitos sistemas (desenvolvidos com Intraweb).


OnClick do IWButton chamar mais de uma função Javascript no evento “onSubmit” do form


Supondo que o IWButton, ou qualquer outro controle que seja, já possua uma chamada a uma função Javascript. Hipoteticamente, imagine um cenário onde o mesmo IWButton, que vai submeter o form da página web, precisa, no mesmo evento “OnClick”, validar o CIC e fazer qualquer outro tipo de validação.
Note que estou, propositalmente, construindo uma situação onde o click do botão está relacionado a ação de submeter o form da página web. Além disso, estamos trabalhando com um grau de complexidade onde você precisa (ou precisará) executar mais de um função em reposta ação do usuário clicar esse botão. O botão “Submit” (no caso, nosso IWButton1). Ora, grau de complexidade? Isso que você descreveu, Gerson, me parece tão comum! Concordo, é muito comum se você está trabalhando com outra tecnologia. No Intraweb, lamentavelmente isso não é trivial.
Então, prosseguindo, vejamos: Em primeiro lugar, vamos criar a segunda função (a qual será responsável por tornar o valor do IWEdit1 obrigatório). Ou seja, para submeter o form da página web, o usuário será obrigado a digitar algum valor no IWEdit1. Feito isso, teremos construído todos elementos necessários para a experiência que irá confirmar minha argumentação (assim espero ....). Portanto, na seção “const” (que definimos anteriormente) codificaremos, em forma de outra constante, a string com a função supracitada. Digite conforme ilustrado abaixo:




AFncValorRequerido =
' function ValorRequerido(){ ' + AQuebraLinhaJsZN +
' var ObjInput = document.getElementById("%s); ' + AQuebraLinhaJsZN +
' var AFriendlyName = "%s"; ' + AQuebraLinhaJsZN +
' if (ObjInput.value == ""){ ' + AQuebraLinhaJsZN +
' alert("É obrigatório o valor para o campo: " + AFriendlyName); ' + AQuebraLinhaJsZN +
' ObjInput.style.backgroundColor = "#FD88AA"; ' + AQuebraLinhaJsZN +
' ObjInput.focus(); ' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' else { ' + AQuebraLinhaJsZN +
' ObjInput.style.backgroundColor = "#FFFFFF"; ' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN;


Em seguida faremos uma pequena modificação na primeira função que criamos, “CriticaCIC”. No caso, ela é a segunda constante de definimos para o exemplo anterior, a “AFncCriticaCIC”. Espere, não é exatamente isso o que faremos. O que quero realmente fazer é copiar a constante “AFncCriticaCIC”, a partir disso, definir uma nova com o mesmo conteúdo. Porque, desta forma posso fazer as alterações que preciso, sem perder completamente o exemplo anterior. Logo, assim sendo, quem estiver acompanhando este artigo poderá facilmente testar e verificar a diferença entra as duas estratégias (“do grego, "Στρατηγικη"... ...no inglês, "strategy"... ...no francês, "stratégie"... ZzZzZzZzzzz...... ...Senhor leitor, o senhor está dormindo? Senhor leitor, tenha bondade..”. (Parafraseando Capitão Nascimento)

Prosseguindo (era brincadeira), retomemos: Criaremos então a nova constante a partir da cópia de “AFncCriticaCIC”:


AFncCriticaCIC2 =
' function CriticaCIC2(ZnCnpjBool, ZnCpfBool){ ' + AQuebraLinhaJsZN +
' var ZnNumCic = document.getElementById("%s); ' + AQuebraLinhaJsZN +
' alert("www.estacaozn.blogspot.com verifica CPF/CNPJ");' + AQuebraLinhaJsZN +
' var CicValidoZn = false; ' + AQuebraLinhaJsZN +
' ' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && !ZnCpfBool) { ' + AQuebraLinhaJsZN +
' if(!ZnVerificaCnpj(ZnNumCic)){ ' + AQuebraLinhaJsZN +
' alert("CNPJ Inválido"); ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' else if (!ZnCnpjBool && ZnCpfBool){ ' + AQuebraLinhaJsZN +
' if (!ZnVerificaCPF(ZnNumCic)){ ' + AQuebraLinhaJsZN +
' alert("CPF inválido"); ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' ;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' else { ' + AQuebraLinhaJsZN +
' CicValidoZn = ZnVerificaCnpj(ZnNumCic); ' + AQuebraLinhaJsZN +
' if(CicValidoZn){ ' + AQuebraLinhaJsZN +
' return true;} ' + AQuebraLinhaJsZN +
' else{ ' + AQuebraLinhaJsZN +
' CicValidoZn = ZnVerificaCPF(ZnNumCic); ' + AQuebraLinhaJsZN +
' if(!CicValidoZn){ ' + AQuebraLinhaJsZN +
' alert("CIC Inválido") ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' var ZnMsg = ""; ' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CPJ ou CNPJ"; }' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && !ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CNPJ"; }' + AQuebraLinhaJsZN +
' if (!ZnCnpjBool && ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CPF"; }' + AQuebraLinhaJsZN +
' alert("Valor Validado Ok, " +ZnMsg + ": " + ZnNumCic.value);' + AQuebraLinhaJsZN +
' return true;} ' + AQuebraLinhaJsZN;

Essa nova versão da crítica de “CIC” possui um parâmetro a menos. Eu retirei o argumento referente ao objeto do form (input que recebe o valor digitado do suposto CIC). Já que decidimos não perder o que foi feito no exemplo anterior, vamos adicionar mais um IWButton. O IWButton4, servirá, nessa segunda parte do artigo, para chamar a nova critica CIC (o conteúdo da AFncCriticaCIC2). Feito isso, vamos acrescentar mais umas linhas de código no evento “OnCreate” do IWForm1.



(* segunda parte do artigo:
OnClick do IWButton chamar mais de uma função Javascript *)
IWEdit1.FriendlyName := 'CIC: "CNPJ" ou "CPF"';
Self.JavaScript.Add('//**************************************');
Self.JavaScript.Add('//segunda parte do artigo:' + #13 +
'// OnClick do IWButton chamar mais de uma função Javascript');
Self.JavaScript.Add(Format(AFncCriticaCIC2, [UpperCase(IWEdit1.Name)]));
Self.JavaScript.Add('');

Self.JavaScript.Add('');
Self.JavaScript.Add(Format(AFncValorRequerido, [UpperCase(IWEdit1.Name),
IWEdit1.FriendlyName]));
Self.JavaScript.Add('//*******www.estacaozn.blogspot.com**********');

IWButton4.Caption := 'Valor Obrigatório & Valida CIC';
IWButton4.Width := 360;
IWButton4.ScriptEvents.Add('onClick').EventCode.Add(
'ValorRequerido() && CriticaCIC(true, true)');


No Intraweb, chamar, efetivamente, no evento “onClick”, mais de um função pode ser feito declarando o nome das funções, juntamente com o operador lógico adequado, ao caso específico, na propriedade “ScriptEvent” do componente escolhido (No nosso caso o escolhido foi o TIWButton). Provavelmente, essa não deve ser a única forma de se fazer isso, essa é apenas uma (suponho ;-)). Especificamente a que eu encontrei no momento para alcançar meu objetivo.

Cabe registrar que, como alternativa, para propriedade “ExtraTagParams” existe um restrição. Só funciona se a ação não envolver o submit do form. Como posso ter certeza do acabei de afirmar?
Para exemplificar, respondendo a pergunta anterior, vamos submeter o form. Contudo, para isso, precisamos pelo menos processar algo no servidor. Com essa finalidade, codificaremos qualquer coisa dummy no evento OnClick do componente Delphi/Intraweb TIWButton4. Adicione um novo componente, um IWLabel, em seguida, acompanhe trecho de código abaixo:


procedure TIWForm1.IWButton4Click(Sender: TObject);
begin
IWLabel1.Font.Size := 16;
IWLabel1.Caption := Format('Valor digitado válido: %s', [IWEdit1.Text]); ;
end;


Veja, como o Intraweb monta a função que submete o form:


var IWLABEL1IWCL = null;
var IWBUTTON1IWCL = null;
var IWEDIT1IWCL = null;
var IWBUTTON2IWCL = null;
var IWBUTTON3IWCL = null;
var IWBUTTON4IWCL = null;
function IWBUTTON4_onclick(event) {
return ValorRequerido() && CriticaCIC2(true, true)
}

function IWBUTTON4_onclick0(event) {
return SubmitClickConfirm('IWBUTTON4','', true, '');
}

Ok, finalizamos! Podemos testar, F9 .. e manda ver ...
Prova dos Nove

Considero que terminamos o assunto aqui. Se por acaso você inda quer conferir o que eu afirmei acima prossiga:
Agora vamos testar se realmente, de fato, quando esta situação acontece, não é possível ter sucesso usando a propriedade “ExtraTagParams”.
Adicionaremos mais um IWButton, no meu exemplo esse será o IWButton5. Retornaremos ao evento “OnCreate” do IWForm1 (Unit1) e codificaremos a chamada ao Javascript de crítica de valor requerido e validação de CIC, na propriedade ExtraTagParams do último IWButton adicionado. Veja abaixo como ficou:



procedure TIWForm1.IWAppFormCreate(Sender: TObject);
begin
Self.JavaScript.Add('');
Self.JavaScript.Add(AFncCriticaCPF);
Self.JavaScript.Add('');
Self.JavaScript.Add(AFncCriticaCNPJ);
Self.JavaScript.Add('');
Self.JavaScript.Add(AFncCriticaCIC);
Self.JavaScript.Add('');
// O IWButton1 vai validar as duas opções CPF e CNPJ
IWButton1.Caption := 'Valida CPF e CNPJ';
IWButton1.Width := 200;
IWButton1.ExtraTagParams.Add(
Format('onClick=CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'true', 'true']));
//O IWButton2 vai validar apenas CPF
IWButton2.Caption := 'Valida CPF';
IWButton2.Width := 200;
IWButton2.ExtraTagParams.Add(
Format('onClick=CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'false', 'true']));
//O IWButton3 vai validar apenas CNPJ
IWButton3.Caption := 'Valida CNPJ';
IWButton3.Width := 200;
IWButton3.ExtraTagParams.Add(
Format('onClick=CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'true', 'false']));

(* segunda parte do artigo:
OnClick do IWButton chamar mais de uma função Javascript *)
IWEdit1.FriendlyName := 'CIC: CNPJ ou CPF';
Self.JavaScript.Add('//**************************************');
Self.JavaScript.Add('//segunda parte do artigo:' + #13 +
'// OnClick do IWButton chamar mais de uma função Javascript');
Self.JavaScript.Add(Format(AFncCriticaCIC2, [UpperCase(IWEdit1.Name)]));
Self.JavaScript.Add('');

Self.JavaScript.Add('');
Self.JavaScript.Add(Format(AFncValorRequerido, [UpperCase(IWEdit1.Name),
IWEdit1.FriendlyName]));
Self.JavaScript.Add('//*******www.estacaozn.blogspot.com**********');

IWButton4.Caption := 'Valor Obrigatório & Valida CIC';
IWButton4.Width := 360;
IWButton4.ScriptEvents.Add('onClick').EventCode.Add(
'return ValorRequerido() && CriticaCIC2(true, true)');

(* testando chamar duas funções Javascript na propriedade ExtraTagParams *)

IWButton5.ExtraTagParams.Add(
Format('onClick=return ValorRequerido() && CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'true', 'true']));
end;


O trecho que acabamos de digitar inicia com o comentário da linha 48. Note que fizemos a chamada semelhante ao IWButton4. Da forma como está agora, funciona perfeitamente. Mesmo que eu faça a chamada, no IWButton5, igualzinho a do IWButton4, funciona.


IWButton5.ExtraTagParams.Add(
Format('onClick=return ValorRequerido() && CriticaCIC2(true, true)',
[UpperCase(IWEdit1.Name)]));


Todavia, se eu envolver o IWButton5 no submit do form teremos fracasso. Babau! A vaca vai pro brejo.
Para conferir basta codificar qualquer coisa no evento “OnClick” do IWButton5. Isso irá forçar um submit para que esse código seja processado no servidor. Vou colocar uma dummy aqui ... veja:


procedure TIWForm1.IWButton5Click(Sender: TObject);
begin
IWLabel1.Caption := IWEdit1.Text;
WebApplication.ShowMessage('Se você esta codificando esse exemplo corretamente, '+
'essa mensagem nunca não vai ser exibida. Jamais será! Garanto (heheh ..).');
end;


O Intraweb tenta ter controle total de alguns eventos do objeto form da página html. Isso acontece de forma mais rigorosa no evento “onLoad”. Eu até entendo a razão deles fazerem isso, mas não a considero justificável, e justamente por isso discordo desse tipo de controle. Acho isso extremamente prejudicial ao desenvolvimento de sites, sistemas, serviços, web com o Intraweb. Ao mesmo tempo isso demonstra de forma muito clara o quanto esse framework é frágil e imaturo.

Abaixo, o código integral da Unit1, seguido do código da página html gerado pelo Intraweb:


unit Unit1;

interface

uses
Classes, SysUtils, IWAppForm, IWApplication, IWColor, IWTypes, IWCompEdit,
Controls, IWVCLBaseControl, IWBaseControl, IWBaseHTMLControl, IWControl,
IWCompButton, IWCompLabel;

type
TIWForm1 = class(TIWAppForm)
IWButton1: TIWButton;
IWEdit1: TIWEdit;
IWButton2: TIWButton;
IWButton3: TIWButton;
IWButton4: TIWButton;
IWLabel1: TIWLabel;
IWButton5: TIWButton;
procedure IWButton5Click(Sender: TObject);
procedure IWButton4Click(Sender: TObject);
procedure IWAppFormCreate(Sender: TObject);
public
end;

implementation


{$R *.dfm}
const
AQuebraLinhaJsZN = #13;
AFncCriticaCIC =
' function CriticaCIC(ZnNumCic, ZnCnpjBool, ZnCpfBool){ ' + AQuebraLinhaJsZN +
' alert("www.estacaozn.blogspot.com verifica CPF/CNPJ");' + AQuebraLinhaJsZN +
' var CicValidoZn = false; ' + AQuebraLinhaJsZN +
' ' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && !ZnCpfBool) { ' + AQuebraLinhaJsZN +
' if(!ZnVerificaCnpj(ZnNumCic)){ ' + AQuebraLinhaJsZN +
' alert("CNPJ Inválido"); ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' else if (!ZnCnpjBool && ZnCpfBool){ ' + AQuebraLinhaJsZN +
' if (!ZnVerificaCPF(ZnNumCic)){ ' + AQuebraLinhaJsZN +
' alert("CPF inválido"); ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' ;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' else { ' + AQuebraLinhaJsZN +
' CicValidoZn = ZnVerificaCnpj(ZnNumCic); ' + AQuebraLinhaJsZN +
' if(CicValidoZn){ ' + AQuebraLinhaJsZN +
' return true;} ' + AQuebraLinhaJsZN +
' else{ ' + AQuebraLinhaJsZN +
' CicValidoZn = ZnVerificaCPF(ZnNumCic); ' + AQuebraLinhaJsZN +
' if(!CicValidoZn){ ' + AQuebraLinhaJsZN +
' alert("CIC Inválido") ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' var ZnMsg = ""; ' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CPJ ou CNPJ"; }' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && !ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CNPJ"; }' + AQuebraLinhaJsZN +
' if (!ZnCnpjBool && ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CPF"; }' + AQuebraLinhaJsZN +
' alert("Valor Validado Ok, " +ZnMsg + ": " + ZnNumCic.value);' + AQuebraLinhaJsZN +
' return true;} ' + AQuebraLinhaJsZN;

AFncCriticaCPF =
' function ZnVerificaCPF (ZnCpfObj){ ' + AQuebraLinhaJsZN +
' var gmSort = new Array(ZnCpfObj.value.length); ' + AQuebraLinhaJsZN +
' for (i=0; i< ZnCpfObj.value.length; i++){gmSort[i] = ZnCpfObj.value.charAt(i);} ' + AQuebraLinhaJsZN +
' gmSort.sort(); ' + AQuebraLinhaJsZN +
' if (gmSort[0] == gmSort[gmSort.length -1]){ ' + AQuebraLinhaJsZN +
' alert("www.estacaozn.blogspot.com: Os números são iguais: " + ZnCpfObj.value); ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' ZnAuxCal = 0; ' + AQuebraLinhaJsZN +
' for (ZnCont = 0; ZnCont < 9; ZnCont ++) ' + AQuebraLinhaJsZN +
' ZnAuxCal += parseInt(ZnCpfObj.value.charAt(ZnCont)) * (10 - ZnCont); ' + AQuebraLinhaJsZN +
' DgVZn = 11 - (ZnAuxCal % 11); ' + AQuebraLinhaJsZN +
' if (DgVZn == 10 || DgVZn == 11) ' + AQuebraLinhaJsZN +
' DgVZn = 0; ' + AQuebraLinhaJsZN +
' if (DgVZn != parseInt(ZnCpfObj.value.charAt(9))) ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' ZnAuxCal = 0; ' + AQuebraLinhaJsZN +
' for (ZnCont = 0; ZnCont < 10; ZnCont ++) ' + AQuebraLinhaJsZN +
' ZnAuxCal += parseInt(ZnCpfObj.value.charAt(ZnCont)) * (11 - ZnCont); ' + AQuebraLinhaJsZN +
' DgVZn = 11 - (ZnAuxCal % 11); ' + AQuebraLinhaJsZN +
' if (DgVZn == 10 || DgVZn == 11) ' + AQuebraLinhaJsZN +
' DgVZn = 0; ' + AQuebraLinhaJsZN +
' if (DgVZn != parseInt(ZnCpfObj.value.charAt(10))){ ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' //alert("O CPF INFORMADO É VÁLIDO."); ' + AQuebraLinhaJsZN +
' return true; ' + AQuebraLinhaJsZN +
'} ' + AQuebraLinhaJsZN;

AFncCriticaCNPJ =
' function ZnVerificaCnpj(ZNObjInput){' + AQuebraLinhaJsZN +
' var ZnDigitos, ZnDg, ZnSum, ZnCount;' + AQuebraLinhaJsZN +
' var ZnResult, ZnPos, tamanho;' + AQuebraLinhaJsZN +
' var ZnAuxCNPJ = ZNObjInput.value.replace(/\D+/g, "");' + AQuebraLinhaJsZN +
'' + AQuebraLinhaJsZN +
' if (ZnAuxCNPJ.length != 14){' + AQuebraLinhaJsZN +
' ZNObjInput.focus();' + AQuebraLinhaJsZN +
' return false;' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' var gmSort = new Array(ZNObjInput.value.length); ' + AQuebraLinhaJsZN +
' for (i=0; i< ZNObjInput.value.length; i++){gmSort[i] = ZNObjInput.value.charAt(i);} ' + AQuebraLinhaJsZN +
' gmSort.sort(); ' + AQuebraLinhaJsZN +
' if (gmSort[0] == gmSort[gmSort.length -1]){ ' + AQuebraLinhaJsZN +
' alert("www.estacaozn.blogspot.com: Os números são iguais: " + ZNObjInput.value); ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
'' + AQuebraLinhaJsZN +
' ZnAuxTamanho = ZnAuxCNPJ.length - 2' + AQuebraLinhaJsZN +
' ZnDigitos = ZnAuxCNPJ.substring(0,ZnAuxTamanho);' + AQuebraLinhaJsZN +
' ZnDg = ZnAuxCNPJ.substring(ZnAuxTamanho);' + AQuebraLinhaJsZN +
' ZnSum = 0;' + AQuebraLinhaJsZN +
' ZnPos = ZnAuxTamanho - 7;' + AQuebraLinhaJsZN +
' for (ZnCount = ZnAuxTamanho; ZnCount >= 1; ZnCount--){' + AQuebraLinhaJsZN +
' ZnSum += ZnDigitos.charAt(ZnAuxTamanho - ZnCount) * ZnPos--;' + AQuebraLinhaJsZN +
' if (ZnPos < 2)' + AQuebraLinhaJsZN +
' ZnPos = 9;' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' ZnResult = ZnSum % 11 < 2 ? 0 : 11 - ZnSum % 11;' + AQuebraLinhaJsZN +
' if (ZnResult != ZnDg.charAt(0)){' + AQuebraLinhaJsZN +
' ZNObjInput.focus();' + AQuebraLinhaJsZN +
' return false;' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
'' + AQuebraLinhaJsZN +
' ZnAuxTamanho = ZnAuxTamanho + 1;' + AQuebraLinhaJsZN +
' ZnDigitos = ZnAuxCNPJ.substring(0,ZnAuxTamanho);' + AQuebraLinhaJsZN +
' ZnSum = 0;' + AQuebraLinhaJsZN +
' ZnPos = ZnAuxTamanho - 7;' + AQuebraLinhaJsZN +
' for (ZnCount = ZnAuxTamanho; ZnCount >= 1; ZnCount--){' + AQuebraLinhaJsZN +
' ZnSum += ZnDigitos.charAt(ZnAuxTamanho - ZnCount) * ZnPos--;' + AQuebraLinhaJsZN +
' if (ZnPos < 2)' + AQuebraLinhaJsZN +
' ZnPos = 9;}' + AQuebraLinhaJsZN +
'' + AQuebraLinhaJsZN +
' ZnResult = ZnSum % 11 < 2 ? 0 : 11 - ZnSum % 11;' + AQuebraLinhaJsZN +
' if (ZnResult != ZnDg.charAt(1)){' + AQuebraLinhaJsZN +
' ZNObjInput.focus();' + AQuebraLinhaJsZN +
' return false;}' + AQuebraLinhaJsZN +
' else {' + AQuebraLinhaJsZN +
' return true;' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN;

AFncValorRequerido =
' function ValorRequerido(){ ' + AQuebraLinhaJsZN +
' var ObjInput = document.getElementById("%s"); ' + AQuebraLinhaJsZN +
' var AFriendlyName = "%s"; ' + AQuebraLinhaJsZN +
' if (ObjInput.value == ""){ ' + AQuebraLinhaJsZN +
' alert("É obrigatório o valor para o campo: " + AFriendlyName); ' + AQuebraLinhaJsZN +
' ObjInput.style.backgroundColor = "#FD88AA"; ' + AQuebraLinhaJsZN +
' ObjInput.focus(); ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' else { ' + AQuebraLinhaJsZN +
' ObjInput.style.backgroundColor = "#FFFFFF"; ' + AQuebraLinhaJsZN +
' }' + AQuebraLinhaJsZN +
' return true;}' + AQuebraLinhaJsZN;

AFncCriticaCIC2 =
' function CriticaCIC2(ZnCnpjBool, ZnCpfBool){ ' + AQuebraLinhaJsZN +
' var ZnNumCic = document.getElementById("%s"); ' + AQuebraLinhaJsZN +
' alert("www.estacaozn.blogspot.com verifica CPF/CNPJ");' + AQuebraLinhaJsZN +
' var CicValidoZn = false; ' + AQuebraLinhaJsZN +
' ' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && !ZnCpfBool) { ' + AQuebraLinhaJsZN +
' if(!ZnVerificaCnpj(ZnNumCic)){ ' + AQuebraLinhaJsZN +
' alert("CNPJ Inválido"); ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' else if (!ZnCnpjBool && ZnCpfBool){ ' + AQuebraLinhaJsZN +
' if (!ZnVerificaCPF(ZnNumCic)){ ' + AQuebraLinhaJsZN +
' alert("CPF inválido"); ' + AQuebraLinhaJsZN +
' return false; ' + AQuebraLinhaJsZN +
' ;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' else { ' + AQuebraLinhaJsZN +
' CicValidoZn = ZnVerificaCnpj(ZnNumCic); ' + AQuebraLinhaJsZN +
' if(CicValidoZn){ ' + AQuebraLinhaJsZN +
' return true;} ' + AQuebraLinhaJsZN +
' else{ ' + AQuebraLinhaJsZN +
' CicValidoZn = ZnVerificaCPF(ZnNumCic); ' + AQuebraLinhaJsZN +
' if(!CicValidoZn){ ' + AQuebraLinhaJsZN +
' alert("CIC Inválido") ' + AQuebraLinhaJsZN +
' return false;} ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' } ' + AQuebraLinhaJsZN +
' var ZnMsg = ""; ' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CPJ ou CNPJ"; }' + AQuebraLinhaJsZN +
' if (ZnCnpjBool && !ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CNPJ"; }' + AQuebraLinhaJsZN +
' if (!ZnCnpjBool && ZnCpfBool) { ' + AQuebraLinhaJsZN +
' ZnMsg = "CPF"; }' + AQuebraLinhaJsZN +
' alert("Valor Validado Ok, " +ZnMsg + ": " + ZnNumCic.value);' + AQuebraLinhaJsZN +
' return true;} ' + AQuebraLinhaJsZN;

procedure TIWForm1.IWAppFormCreate(Sender: TObject);
begin
Self.JavaScript.Add('');
Self.JavaScript.Add(AFncCriticaCPF);
Self.JavaScript.Add('');
Self.JavaScript.Add(AFncCriticaCNPJ);
Self.JavaScript.Add('');
Self.JavaScript.Add(AFncCriticaCIC);
Self.JavaScript.Add('');
// O IWButton1 vai validar as duas opções CPF e CNPJ
IWButton1.Caption := 'Valida CPF e CNPJ';
IWButton1.Width := 200;
IWButton1.ExtraTagParams.Add(
Format('onClick=CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'true', 'true']));
//O IWButton2 vai validar apenas CPF
IWButton2.Caption := 'Valida CPF';
IWButton2.Width := 200;
IWButton2.ExtraTagParams.Add(
Format('onClick=CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'false', 'true']));
//O IWButton3 vai validar apenas CNPJ
IWButton3.Caption := 'Valida CNPJ';
IWButton3.Width := 200;
IWButton3.ExtraTagParams.Add(
Format('onClick=CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'true', 'false']));

(* segunda parte do artigo:
OnClick do IWButton chamar mais de uma função Javascript *)
IWEdit1.FriendlyName := 'CIC: CNPJ ou CPF';
Self.JavaScript.Add('//**************************************');
Self.JavaScript.Add('//segunda parte do artigo:' + #13 +
'// OnClick do IWButton chamar mais de uma função Javascript');
Self.JavaScript.Add(Format(AFncCriticaCIC2, [UpperCase(IWEdit1.Name)]));
Self.JavaScript.Add('');

Self.JavaScript.Add('');
Self.JavaScript.Add(Format(AFncValorRequerido, [UpperCase(IWEdit1.Name),
IWEdit1.FriendlyName]));
Self.JavaScript.Add('//*******www.estacaozn.blogspot.com**********');

IWButton4.Caption := 'Valor Obrigatório & Valida CIC';
IWButton4.Width := 360;
IWButton4.ScriptEvents.Add('onClick').EventCode.Add(
'return ValorRequerido() && CriticaCIC2(true, true)');

(* testando chamar duas funções Javascript na propriedade ExtraTagParams *)

(* IWButton5.ExtraTagParams.Add(
Format('onClick=return ValorRequerido() && CriticaCIC(%s, %s, %s)', [UpperCase(IWEdit1.Name),
'true', 'true'])); *)

IWButton5.ExtraTagParams.Add(
Format('onClick=return ValorRequerido() && CriticaCIC2(true, true)',
[UpperCase(IWEdit1.Name)]));
end;

procedure TIWForm1.IWButton4Click(Sender: TObject);
begin
IWLabel1.Font.Size := 16;
IWLabel1.Caption := Format('Valor digitado válido: %s', [IWEdit1.Text]); ;
end;

procedure TIWForm1.IWButton5Click(Sender: TObject);
begin
IWLabel1.Caption := IWEdit1.Text;
WebApplication.ShowMessage('Se você esta codificando esse exemplo corretamente, '+
'essa mensagem nunca não vai ser exibida. Jamais será! Garanto (heheh ..).');
end;
(* esse trecho para Intrweb 8*)
initialization
TIWForm1.SetAsMainForm;


Abaixo, trecho código Javascript gerado pelo Intraweb como resultado do processamento do que implementamos em Delphi.



function ZnVerificaCPF (ZnCpfObj){
var gmSort = new Array(ZnCpfObj.value.length);
for (i=0; i< ZnCpfObj.value.length; i++){gmSort[i] = ZnCpfObj.value.charAt(i);}
gmSort.sort();
if (gmSort[0] == gmSort[gmSort.length -1]){
alert("www.estacaozn.blogspot.com: Os números são iguais: " + ZnCpfObj.value);
return false;
}
ZnAuxCal = 0;
for (ZnCont = 0; ZnCont < 9; ZnCont ++)
ZnAuxCal += parseInt(ZnCpfObj.value.charAt(ZnCont)) * (10 - ZnCont);
DgVZn = 11 - (ZnAuxCal % 11);
if (DgVZn == 10 || DgVZn == 11)
DgVZn = 0;
if (DgVZn != parseInt(ZnCpfObj.value.charAt(9)))
return false;
ZnAuxCal = 0;
for (ZnCont = 0; ZnCont < 10; ZnCont ++)
ZnAuxCal += parseInt(ZnCpfObj.value.charAt(ZnCont)) * (11 - ZnCont);
DgVZn = 11 - (ZnAuxCal % 11);
if (DgVZn == 10 || DgVZn == 11)
DgVZn = 0;
if (DgVZn != parseInt(ZnCpfObj.value.charAt(10))){
return false;}
//alert("O CPF INFORMADO É VÁLIDO.");
return true;
}


function ZnVerificaCnpj(ZNObjInput){
var ZnDigitos, ZnDg, ZnSum, ZnCount;
var ZnResult, ZnPos, tamanho;
var ZnAuxCNPJ = ZNObjInput.value.replace(/\D+/g, "");

if (ZnAuxCNPJ.length != 14){
ZNObjInput.focus();
return false;
}
var gmSort = new Array(ZNObjInput.value.length);
for (i=0; i< ZNObjInput.value.length; i++){gmSort[i] = ZNObjInput.value.charAt(i);}
gmSort.sort();
if (gmSort[0] == gmSort[gmSort.length -1]){
alert("www.estacaozn.blogspot.com: Os números são iguais: " + ZNObjInput.value);
return false;
}

ZnAuxTamanho = ZnAuxCNPJ.length - 2
ZnDigitos = ZnAuxCNPJ.substring(0,ZnAuxTamanho);
ZnDg = ZnAuxCNPJ.substring(ZnAuxTamanho);
ZnSum = 0;
ZnPos = ZnAuxTamanho - 7;
for (ZnCount = ZnAuxTamanho; ZnCount >= 1; ZnCount--){
ZnSum += ZnDigitos.charAt(ZnAuxTamanho - ZnCount) * ZnPos--;
if (ZnPos < 2)
ZnPos = 9;
}
ZnResult = ZnSum % 11 < 2 ? 0 : 11 - ZnSum % 11;
if (ZnResult != ZnDg.charAt(0)){
ZNObjInput.focus();
return false;
}

ZnAuxTamanho = ZnAuxTamanho + 1;
ZnDigitos = ZnAuxCNPJ.substring(0,ZnAuxTamanho);
ZnSum = 0;
ZnPos = ZnAuxTamanho - 7;
for (ZnCount = ZnAuxTamanho; ZnCount >= 1; ZnCount--){
ZnSum += ZnDigitos.charAt(ZnAuxTamanho - ZnCount) * ZnPos--;
if (ZnPos < 2)
ZnPos = 9;}

ZnResult = ZnSum % 11 < 2 ? 0 : 11 - ZnSum % 11;
if (ZnResult != ZnDg.charAt(1)){
ZNObjInput.focus();
return false;}
else {
return true;
}
}


function CriticaCIC(ZnNumCic, ZnCnpjBool, ZnCpfBool){
alert("www.estacaozn.blogspot.com verifica CPF/CNPJ");
var CicValidoZn = false;

if (ZnCnpjBool && !ZnCpfBool) {
if(!ZnVerificaCnpj(ZnNumCic)){
alert("CNPJ Inválido");
return false;}
}
else if (!ZnCnpjBool && ZnCpfBool){
if (!ZnVerificaCPF(ZnNumCic)){
alert("CPF inválido");
return false;
;}
}
else {
CicValidoZn = ZnVerificaCnpj(ZnNumCic);
if(CicValidoZn){
return true;}
else{
CicValidoZn = ZnVerificaCPF(ZnNumCic);
if(!CicValidoZn){
alert("CIC Inválido")
return false;}
}
}
var ZnMsg = "";
if (ZnCnpjBool && ZnCpfBool) {
ZnMsg = "CPJ ou CNPJ"; }
if (ZnCnpjBool && !ZnCpfBool) {
ZnMsg = "CNPJ"; }
if (!ZnCnpjBool && ZnCpfBool) {
ZnMsg = "CPF"; }
alert("Valor Validado Ok, " +ZnMsg + ": " + ZnNumCic.value);
return true;}


//**************************************
//segunda parte do artigo:
// OnClick do IWButton chamar mais de uma função Javascript
function CriticaCIC2(ZnCnpjBool, ZnCpfBool){
var ZnNumCic = document.getElementById("IWEDIT1");
alert("www.estacaozn.blogspot.com verifica CPF/CNPJ");
var CicValidoZn = false;

if (ZnCnpjBool && !ZnCpfBool) {
if(!ZnVerificaCnpj(ZnNumCic)){
alert("CNPJ Inválido");
return false;}
}
else if (!ZnCnpjBool && ZnCpfBool){
if (!ZnVerificaCPF(ZnNumCic)){
alert("CPF inválido");
return false;
;}
}
else {
CicValidoZn = ZnVerificaCnpj(ZnNumCic);
if(CicValidoZn){
return true;}
else{
CicValidoZn = ZnVerificaCPF(ZnNumCic);
if(!CicValidoZn){
alert("CIC Inválido")
return false;}
}
}
var ZnMsg = "";
if (ZnCnpjBool && ZnCpfBool) {
ZnMsg = "CPJ ou CNPJ"; }
if (ZnCnpjBool && !ZnCpfBool) {
ZnMsg = "CNPJ"; }
if (!ZnCnpjBool && ZnCpfBool) {
ZnMsg = "CPF"; }
alert("Valor Validado Ok, " +ZnMsg + ": " + ZnNumCic.value);
return true;}



function ValorRequerido(){
var ObjInput = document.getElementById("IWEDIT1");
var AFriendlyName = "CIC: CNPJ ou CPF";
if (ObjInput.value == ""){
alert("É obrigatório o valor para o campo: " + AFriendlyName);
ObjInput.style.backgroundColor = "#FD88AA";
ObjInput.focus();
return false;
}
else {
ObjInput.style.backgroundColor = "#FFFFFF";
}
return true;}

//*******www.estacaozn.blogspot.com**********

function Validate() {
return true;
}



Artigo completo (View Full Post)

segunda-feira, 15 de dezembro de 2008

Delphi Intraweb 8 – Acessando dados – BDS2006

Neste artigo pretendo demonstrar como usar os componentes dataware do framwork Intraweb 8.
Tenho observado muitos problemas com essa versão da Intraweb. Graças a Deus parece que ninguém ousou usar esse framework, com algumas raras exceções. Se você veio aqui procurando saber se deve ou não iniciar um projeto com essa tecnologia, minha sugestão é: Procure outra coisa, ou na falta de alternativa use Delphi 7 com a versão 5.o do Intraweb.

Vamos construir uma aplicação que vai acessar a base de dados Northwind do SQL Server. Northwind, é uma base criada por default no SQL server, na instalação, cujo objetivo é didático. Ela é usada nos treinamentos oficiais da Microsoft, e exemplifica integralmente um banco de dados usado em um cenário real, profissional



Explicando sobre a base de dados

OBS:
Caso você já conheça a base Northwind, pode pular essa parte indo direto para “Iniciando um projeto Intraweb”.


Vamos trabalhar com as tabelas Categories (Refere-se as categorias dos produtos) e Products (Produtos).
Com o botão direito do mouse sobre “Diagrams”, na tree view, dentro do nó “Northwind”, podemos criar um DER (Diagram Entidade Relacionamento) das tabelas e entender como os dados se relacionam neste data base.



Nosso exemplo estará restrito ao contexto demonstrado na figura abaixo:



O relacionamento demonstrado acima indica que uma “Categoria” pode classificar muitos produtos. Sendo que o “Produto” somente pode ser classificado por uma “Categoria”. Este tipo de relacionamento chama-se “Um para N” (1-N). No relacionamento “Um para N” a chave (campo de relacionamento) aponta para a tabela “N”, no caso “Produtos”.
Isso quer dizer que na tabela Producs, existe uma coluna que referencia a tabela “Categories”. Em outras palavras: A coluna “CategoryID”, de “Producs” aponta para a “CategoryID” de “Categories”.


Iniciando um projeto Intraweb

Inicie um novo projeto do DBS2006: No menu File ►New ► Other ►Intraweb, selecione “Intraweb Application Wizard”.



No diálogo seguinte, “Intraweb Application Wizard”, definiremos alguns parâmetros da nova aplicação que criaremos. Configure conforme ilustrado na imagem abaixo:



Adicione na Unit1 os seguintes componentes:

IWDBEdit1: TIWDBEdit
IWDBListbox1: TIWDBListbox
IWDBNavigator1: TIWDBNavigator
IWDBLookupComboBox1: TIWDBLookupComboBox
IWButton1: TIWButton
IWCheckBox1: TIWCheckBox
ADOConnection1: TADOConnection
ADODataSet: TADODataSet, altere a propriedade “Name” para: AdsCategotias.
DataSetProvider: TdataSetProvider , altere a propriedade “Name” para: DspCategotias
ClientDataSet: TClientDataSet, altere a propriedade “Name” para: CdsCategotias
DataSource: TDataSource, altere a propriedade “Name” para: DsCategotias
ADODataSet: TADODataSet, altere a propriedade “Name” para: AdsProdutos
DataSetProvider: TDataSetProvider, altere a propriedade “Name” para: DspProdutos
ClientDataSet: TClientDataSet, altere a propriedade “Name” para: CdsProdutos
DataSource: TDataSource, altere a propriedade “Name” para: DsProdutos
OBS: A partir do DBS 2005 foi inroduzido na IDE do Delphi um novo conceito para a “Tool Palette”. Para vizualizá-la acesse o menu Vew ► Tool Palette. Hot key “Ctrl + Alt + P” ou digite “Alt” seguido de “V” seguido de “L”.



Uma forma fácil de adicionar um novo componente ao seu projeto é clickar sobre o ícone de filtro na Tool Palette e digitar o nome do componente. Veja imagem abaixo:



Veja o meu Form como ficou em tempo de projeto:




Conecte os componentes de acesso a dados da seguinte forma:

Selecione o IWEdit1, acesse o Objetc Inspector (F11). Associe IWDbEdit1, através da propriedade DataSource, ao DsProdutos. Defina a coluna (campo) que será associada ao IWEdit na propriedade “DataField”. Selecione “ProductName”.

Selecione o DsProdutos, acesse o Objetc Inspector (F11). Associe DsProdutos, através da propriedade DataSet, ao CdsProdutos.

Selecione o CdsProdutos, acesse o Objetc Inspector (F11). Associe CdsProdutos, através da propriedade ProviderName, ao DspProdutos.

Selecione o DspProdutos, acesse o Objetc Inspector (F11). Associe DspProdutos, através da propriedade “DataSet”, ao AdsProdutos.

Selecione o AdsProdutos, acesse o Objetc Inspector (F11). Associe AdsProdutos, através da propriedade “Connection”, ao ADOConnction1.


Conectando o acesso a categoria de produtos:

Selecione o DsCategotias, acesse o Objetc Inspector (F11). Associe DsCategotias, através da propriedade DataSet, ao CdsCategotias.

Selecione o CdsCategotias, acesse o Objetc Inspector (F11). Associe CdsCategotias, através da propriedade ProviderName, ao DspCategotias.

Selecione o DspCategotias, acesse o Objetc Inspector (F11). Associe DspCategotias, através da propriedade “DataSet”, ao AdsCategotias.

Selecione o AdsCategotias, acesse o Objetc Inspector (F11). Associe AdsCategotias, através da propriedade “Connection”, ao ADOConnction1.


Conectando o IWDBLookupComboBox1:


Selecione o IWDBLookupComboBox1, acesse o Objetc Inspector (F11). Associe IWDBLookupComboBox1, através da propriedade DataSource, ao DsProdutos. Defina a coluna (campo) que será associada ao IWDBLookupComboBox1 na propriedade “DataField”. Selecione “CategoryID”. A associação ao CdsCategorias deve ser feita através das propriedades:

1 – “ListSource”, nela selecione “DsCategotias”.
2 - “KeyField”, nela selecione “CategoryID”.
3 - “ListField”, nela selecione “CategoryName”

Esses três campos são do CdsCategorias. Veja mais detalhes sobre a técnica de Lookup ...




Conectando o IWDBListbox1:

Selecione o IWDBListbox1, acesse o Objetc Inspector (F11). Associe IWDBListbox1, através da propriedade DataSource, ao DsProdutos. Defina a coluna (campo) que será associada ao IWDBListbox1 na propriedade “DataField”. Selecione “Discontinued”. Este campo indica se o produpo foi descontinuado ou não.


Definindo os valores no DBListBox:

Na propriedade “Items”, click para acessar o editor. Digite “True”, em seguida, na linha de baixo, digite “False”. Como o CdsProdutosDiscontinued é um “TbooleanField” isso vai funcionar.





Na propriedade ItemsHaveValues, Selecione “False”.

Para a propriedade Height digite 41.


Conectando o IWDBNavigator:


Selecione o IWDBNavigator1, acesse o Objetc Inspector (F11). Associe IWDBNavigator1, através da propriedade DataSource, ao DsProdutos.


String connection no ADOConnection


Provider=SQLOLEDB.1;Persist Security Info=True;User ID=sa;Initial Catalog=Northwind;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=Landjah;Use Encryption for Data=False;Tag with column collation when possible=False

Conectei no SQL Server, usarei as tabelas Categories e Products do banco “Northwind”. Ele é o banco padrão do SQL Server para exemplo e estudo.

Comando SQL nos Ads:
AdsCategorias
Propriedade CommandText:
select CategoryID, CategoryName from Categories

AdsProdutos
Propriedade CommandText:
select * from Products


Codificando o evento OnClick do IWButton1:
procedure TTADo.IWButton1Click(Sender: TObject);
begin
CdsCategotias.Open;
CdsProdutos.Open;
end;


Podemos também trabalhar com o evento OnCreate do Form.
procedure TTADo.IWAppFormCreate(Sender: TObject);
begin
IWButton1Click(IWButton1);
end;

Agora você pode executar a aplicação e testar, navegando, alterando, inserindo, ou excluindo dados.


Veja a imagem ilustrando as conexões data ware no Delphi:



Para rodar o exemplo pressione F9, quando aparecer o diálogo referente ao servidor, pressione F9 novamente.



No IWCheckBox1, defina para a propriedade Caption = 'Editar Produto'. No evento OnClick programe:
procedure TTADo.IWCheckBox1Click(Sender: TObject);
begin
if IWCheckBox1.Checked then
CdsProdutos.Edit;
end;


Agora no evento AfterPost do CdsProdutos sicronise o comportamento do IWCheckBox:
procedure TTADo.CdsProdutosAfterPost(DataSet: TDataSet);
begin
IWCheckBox1.Checked := False;
end;


Testando o comando do IWCheckBox



Salvando as alterações realizadas




Sucesso!

Artigo completo (View Full Post)

segunda-feira, 8 de setembro de 2008

Webservice no BDS2006

Observamos que o assunto "WebService em Delphi" tem tido muita procura aqui no blog. Por isso, pretendo produzir mais material sobre este tema. Contudo, o assunto é abrange um escopo bastante vasto, principalmente no que tange as questões práticas do desenvolvimento de serviços baseados em XML/SOAP. Podemos citar para exemplificar alguns temas sobre “WebService e Delphi”: Testar as versões mais recentes (inclusive o Tiburon – Delphi 2009), verificar incompatibilidades (se existirem), ou diferenças. Uma coisa interessante seria a integração com outras tecnologias (Java, C# e PHP, por exemplo). Outro ponto importante: Acesso e disponibilização de dados (um CRUD, talvez, usando como camada intermediária um aplicação servidora WS). Em fim, há bastante terreno para ser trabalhado.
Neste sentido, podemos eventualmente atender alguma questão pontual demandada pelos leitores. Coloque em forma de comentários sua demanda que na medida do possível teremos prazer em atendê-la. Algumas pessoas já solicitam nosso suporte, informalmente, via e-mail. Porém, seria melhor que além do e-mail o comentário sobre a demanda fosse registrado. Pois, dessa forma aproveitamos a resolução do seu problema para conteúdo do blog. Assim, outros que por ventura vierem até nós com problemas semelhantes possam compartilhar da solução sem gerar retrabalho para nós. Conseqüentemente, imagino que nosso conteúdo será mais aderente. Isso é o que de fato nos importa.

Iniciando um novo projeto

No BDS2006 no menu File ►New ► Other ► Delphi Projects ►WebServices, selecione “SOAP Server Application”. Em seguida uma série de configurações prévias serão feitas mediante alguns diálogos.



No diálogo seguinte selecione ISAPI/NSAPI Dynamic Link Library, e click em “OK”.



Click “Yes” para criar a interface do serviço (WSDL). Veja imagem abaixo:



No próximo diálogo definiremos o nome do serviço que estamos criando: “ZnShowMeTheMoney”, conforme ilustrado abaixo.



Pronto, temos um novo projeto! Estamos desenvolvendo uma aplicação servidora. Um WebService, veja as units que foram cridas na inicialização do nosso projeto:



A lógica sobre declarações nas units, num projeto WebService: Existe uma unit para declarações de interface e uma unit para as implementarmos o que declararemos na unit interface (neste caso temos: “ZnShowMeTheMoneyIntf”, interface. “ZnShowMeTheMoneyImpl”, implementação).

Na interface declararemos uma função. Digite conforme ilustrado abaixo:


(* Declarando uma funcionalidade no serviço que estamos criando *)
function ZnShowMeTheMoney: WideString; stdcall;

A seguir, veja como ficou a unit “ZnShowMeTheMoneyIntf”.

{ Invokable interface IZnShowMeTheMoney }

unit ZnShowMeTheMoneyIntf;

interface

uses InvokeRegistry, Types, XSBuiltIns;

type

{ Invokable interfaces must derive from IInvokable }
IZnShowMeTheMoney = interface(IInvokable)
['{F002F904-9FD7-401D-80E2-037DFFAA4590}']

{ Methods of Invokable interface must not use the default }
{ calling convention; stdcall is recommended }
(* Declarando uma funcionalidade no serviço que estamos criando *)
function ZnShowMeTheMoney: WideString; stdcall;
end;

implementation

initialization
{ Invokable interfaces must be registered }
InvRegistry.RegisterInterface(TypeInfo(IZnShowMeTheMoney));

end.


Agora para implementarmos iremos fazê-lo na unit “ZnShowMeTheMoneyImpl”. Digite conforme ilustrado no trecho de código asseguir:

type

{ TZnShowMeTheMoney }
TZnShowMeTheMoney = class(TInvokableClass, IZnShowMeTheMoney)
public
(* Na unit de implementação precisamos digitar novamente a assinatura do
método que declaramos na interface "ZnShowMeTheMoneyIntf" *)
function ZnShowMeTheMoney: WideString; stdcall;
end;

implementation


Declare uma seção “uses” após a palavra reservada “implementation” e declare as bibliotecas: Math e SysUtils.

OBS: No BDS temos code insight para declaração de bibliotecas!!!



Vamos implementar o método declarado na seção public de “TZnShowMeTheMoney”.

function TZnShowMeTheMoney.ZnShowMeTheMoney: WideString;
const
ZnMsgConst = 'Here is your Money, U$ %f! Do you can see him? look at the message ... ';
var
RandomValue: Double;
RandomDiv: Integer;
begin
RandomValue := RandomRange(1, 10000);
RandomDiv := RandomRange(1, 7);
RandomValue := (RandomValue / RandomDiv);

Result := Format(ZnMsgConst, [RandomValue]);
end


A função que acabamos de codificar, “ZnShowMeTheMoney”, é simplesmente um processamento dummy que retorna aleatoriamente dois valores, os quais são usados como operandos numa divisão cujo o resultado é formatado numa string e retornado na função.
Agora vamos salvar a aplicação, veja ilustração abaixo:




Para o nome do projeto vamos usar “PrjZNShowMoney.bdsproj”. A imagem seguinte mostra, o meu “Project Manager”, para que você possa compara a estrutura do seu projeto com o andamento do nosso exemplo.



Agora vamos publicar nosso serviço: Compile o projeto, em seguida faça o deploy da DLL, “PrjZNShowMoney.dll”, no IIS.

Criei um diretório virtual com alias de “WsShowMeTheMoneyZn”. Para testar, no browser digite: http://localhost/wsshowmethemoneyzn/

Click no link WSDL e você acessará a interface do serviço “IZnShowMeTheMoneyservice”, isso que você esta vendo é mais que uma página web comum.




Neste primeiro exemplo podemos concluir que o desenvolvimento em WS no BDS2006 é semelhante ao do Delphi 7.
É Muito rápido, intuitivo e amigável desenvolver serviços RPC baseados em SOAP/XML no DBS2006, desde que você conheça bem três conceitos:

1 - A estrutura de declarações no Delphi.

2 - Calling Conventions: Convenções de chamadas (traduziremos assim)- Quando declaramos procedimentos ou funções podemos definir, neste momento, a convenção de chamada através das diretivas: register, pascal, cdecl, stdcall, and safecall.
Por exemplo:

function ZNFuncao(const Xzn, Yzn: Double): Double; cdecl;

function ZNProcedimento(const Xzn, Yzn: Double; var AoutZn: Double); stdcall;

3- Sistemas distribuídos: Também chamado na literatura de objetos distribuídos.

Outros artigos sobre Webservice e Delphi

Artigo completo (View Full Post)

sábado, 28 de junho de 2008

BDS 2006 & Javascript - Intraweb 8.0

O Intraweb ainda continua presente nas versões mais recentes o Delphi. Ao que parece, a versão do framework que acompanha o no BDS 2006 apresenta alguma novidade. Contudo, muita coisa importante parece não ter mudado. Por exemplo, o fonte dos componentes ainda não é acessível aos desenvolvedores. Confesso que vejo com grande antipatia essa característica proprietária da Atozed. Postura incompatível com a demonstrada por grandes fornecedores de tecnologias que se destacam atualmente. Isso me remete ao sentimento de que ao usar um produto da Atozed o desenvolvedor está lhe dando com uma empresa cujo a mentalidade reflete uma postura feudal, própria da miserável e subdesenvolvida América latina.
Pretendo criar alguns exemplos (nandjares de mirolands) para experimentar como se comporta o Intraweb 8.0.1, que esta presente no DBS 2006. (Veja: Intraweb e Delphi 7)


Iniciando nosso primeiro exemplo

No BDS 2006, para iniciar um novo projeto selecione no menu: File ► New ► Other. Em
seguida, selecione no diálogo seguinte (caixa de dialogo) IntraWeb Application Wizard. A partir da Treeview (Item Categories) conforme ilustrado na figura abaixo:





No diálogo seguinte definiremos algumas configurações importantes para nossa aplicação web.



StandAlone Application: Essa opção permite desenvolver o aplicativo Intraweb sem a necessidade de deploy em servidor web (IIS por exemplo). Isso traz algum conforto, visto que, assim é dispensável configurações obrigatórias para desenvolvimento que exija deploy e sincronismo com o servidor. Outra vantagem é que essa opção oferece um recurso de “Debug” idêntico o experimentado pelo desenvolvedor quando trabalha na IDE do Delphi com aplicações desk top. A partir dessa configuração seu aplicativo Intraweb, quando o F9 é pressionado, é “executado” pelo Browser, contudo para debuggar basta marcar o brack point (F5) na linha desejada e prosseguir como se você estivesse desenvolvendo um aplicativo convencional.
Pool Data Connection: Como o próprio título indica, refere-se a pool de conexões. Bem, tenho que confiar no que está indicando essa propriedade pois no momento não tenho como testar quase nada sobre ela.
Create User Session: Cria uma declaração, automaticamente, no seu novo projeto, de um obejto da classe TUserSession. Esse objeto, também conhecido desde a versão 5.0, tem o objetivo de ser um gerenciador de seção.
Durante muito tempo o gerenciamento de seção sempre foi uma parte sensível, bastante trabalhosa, nos primórdios do desenvolvimento para web. Na época do Delphi 7, esta estratégia de gerenciamento de seção foi uma feature que fez o Intraweb dar coro em nas tecnologias web vigentes naquela época.
Project Name: Define o nome do projeto.

Project Directory: O Framework Intraweb tem a particularidade de solicitar o path do diretório onde ficará o projeto. No contexto web isso tem uma particular importância por causa de obrigatoriedade da dependência de um servidor web. Porque ele é responsável pela interpretação e disponibilização do seu programa em forma de serviço web. Você pode estar se perguntando: “Ora, definimos o exemplo como ‘Stand Alone Application’, logo não tem servidor web. Correto?”. Errado meu caro, o Intraweb no módulo Stand Alone Application possui uma funcionalidade que simula um servidor web. O simples fato desse detalhe ficar transparente para o desenvolvedor não é a prova de que não exista a necessidade do servidor web.
Outra coisa sobre “Project Directory” ele não usa a API do windows para selecionar um diretório, isso é tosco. Em compensação, você pode digitar um diretório que não exista ainda, ele cria pra você.

Main Form: Define se o aplicativo suportará tecnologia para dispositivos móveis

De cara já percebemos novidades, pretendo verificar até que ponto elas nos representarão vantagem efetivas ou não.

Após essas configurações iniciais, click no botão “OK” e o BDS vai criar pra você as seguintes Units:




Unit1: Este é o formulário Intraweb principal do seu projeto. Esta está nomeado de “IWForm1”.

DatamoduleUnit: Como o próprio nome indica, trata-se do Datamodule (TDatamodule).

unit DataModuleUnit;

interface

uses
{$IFDEF Linux}QForms, {$ELSE}Forms, {$ENDIF}
SysUtils, Classes;

type
TDataModule1 = class(TDataModule)
private
public
end;


implementation

{$R *.dfm}

end.

ServerController: Onde está definido a classe que faz a interface com o servidor web. TIWServerController (IWServerController). Esta classe é também onde definimos muitas propriedades importantes do aplicativo web que estamos construindo.




UserSessionUnit: Gerenciador de seções do Intraweb. Nas versões anteriores, o UserSession era uma classe definida na unit do ServerController.Veja um exemplo de uma Unit “ServerController” do Delphi 7 (Intraweb 5.0):

unit ServerController;
{PUBDIST}

interface

uses
Classes,
UDm,
IWServerControllerBase, IWAppForm, IWApplication,
SysUtils;

type
TIWServerController = class(TIWServerControllerBase)
procedure IWServerControllerBaseNewSession(ASession: TIWApplication;
var VMainForm: TIWAppForm);
private
public
end;

// This is a class which you can add variables to that are specific to the user. Add variables
// to this class instead of creating global variables. This object can references by using:
// UserSession
// So if a variable named UserName of type string is added, it can be referenced by using:
// UserSession.UserName
// Such variables are similar to globals in a normal application, however these variables are
// specific to each user.
//
// See the IntraWeb Manual for more details.
TUserSession = class(TComponent)
public
FrmDm: TFrmDm;
//
constructor Create(AOwner: TComponent); override;
end;

// Procs
function UserSession: TUserSession;

implementation
{$R *.dfm}

uses
IWInit;

function UserSession: TUserSession;
begin
Result := TUserSession(RWebApplication.Data);
end;

{ TUserSession }

constructor TUserSession.Create(AOwner: TComponent);
begin
inherited;
FrmDm := TFrmDm.Create(AOwner);
end;

procedure TIWServerController.IWServerControllerBaseNewSession(
ASession: TIWApplication; var VMainForm: TIWAppForm);
begin
ASession.Data := TUserSession.Create(ASession);
end;

end.

Dando uma olhada rápida nessas units em termos de arquitetura o Intraweb mudou um pouco a organização entre as classes TServerController e TUserSession, porém ainda continua trabalhando com serialização de objetos. Veja que neste trecho de código do ServerController as classes são acessadas não por uma variável mas por uma função:


function UserSession: TIWUserSession;
function IWServerController: TIWServerController;
function LockDataModule: TDataModule1;
procedure UnlockDataModule(ADataModule: TDataModule1);


Observamos também que TUserSession agora herda de “TIWUserSessionBase”. Mas isso nos deixa muito pouca informação porque não temos acesso a definição desse ancestral.
Javascript no Intraweb 8.0.1
Pretendo testar um pouco como um IWForm está se comportando quando usamos processamento do lado cliente.

Propriedade “HiddenFields”

Aqui podemos criar inputs hidden dinamicamente para nossas páginas (Isso é novidade). No String List Editor digite:

GMottaZn=VariaveisOuConstates_PraQuemGosta_do_InputHidden
CoisasLoucas=Bla




Propriedade “ExtraHeader” do IWForm1

Digite o código Javascript na propriedade do IWForm1 conforme ilustrado abaixo:

<SCRIPT LANGUAGE="JavaScript">
<!-- Exibindo informações sobre o browser ...
document.write("<HR>");
document.write("<H1><center><font color=#0080C0 size=5 face=Geneva,
Arial, Helvetica, sans-serif>Estação ZN - Client Side Scripting
</font></center></H1>");
document.write("<HR>");
document.write(" <br>A versão do browser: " + navigator.appVersion);
document.write(" <br>Marca: <B>" + navigator.appName +
"</B>.");
// end script hiding -->
</SCRIPT>




Propriedade JavaScript do IWForm1
Vou criar algumas funções JavaScript e veremos o que vai acontecer. A propriedade JavaScript declaramos apenas funções porque a tag “script type” é definida pelo framework. Diferente do que experimentamos da propriedade “ExtraHeader”.


// Percorre o objeto HTML "form". O Intraweb cria todos os objetos HTMLs
a partir do seu form "Delphi"
function ZnShowObjects(){
for (var j = 0; j < document.forms[0].elements.length; j++) {
alert("Loop volta = "+j);
alert(document.forms[0].elements[j].name + ": " +document.forms[0].elements[j].value);
ZnInput = document.forms[0].elements[j];
alert("Bla");
alert(ZnInput.getAttribute("type"));
if (ZnInput.getAttribute("type").toLowerCase() == "hidden"){
alert(ZnInput.getAttribute("type"));
}
}
};

//função para exibir o input hidden que criamos na propriedade "HiddenFields"

function ExibeHidden(){
MyZn = document.getElementById("GMottaZn");
alert(MyZn.type + "|" + MyZn.name + " = "+ MyZn.value);
};

//Exemplificando uma estrutura de repetição "while" em JavaScript
function ExibeEscondido(){
MyZn = document.getElementById("GMottaZn");
alert("Veja o input hidden que criamos:" + MyZn.value);
ZnInputs = document.forms[0].getElementsByTagName('input');
Achei = 0;
i = 0;
// exemplificando o método "getElementsByTagName", ele retorna uma lista de objetos HTML
while (AZnInput = ZnInputs[i]){
alert("while");
// Procurando o hidden na lista retornada pelo "getElementsByTagName"
if (AZnInput.getAttribute('type').toLowerCase() == 'hidden'){
alert("Achei um escondido!! :" + AZnInput.name + " - "+
AZnInput.value);
Achei = Achei++;
}
else {
// Não encontrou o hidden
alert("Não é hidden: " + AZnInput.name + " - "+
AZnInput.value);
};
i++;
};
if (Achei == 0) {
alert("Não encontra os escondidos, mas eles estão lá!!!");
}
else {
alert(Achei);
};
};


Agora vamos adiciona os controles no IWF3orm1:
Adicione da plaheta IWStandard um TIWEdit, e três TIWButtons.



Testei a propriedade “ExtraTagParams” dos controles, sem sucesso por enquanto. Vou tentar mais posteriormente.



Na propriedade “ScriptEvents” da cada um dos IWButtons fiz a chamada a cada uma das funções que definimos na propriedade “JavaScript” do IWForm1. Veja as imagens abaixo e codifique igual:


IWButton1 - OnClick


IWButton2 - OnClick


IWButton3 - OnClick


Para executar a aplicação pressione F9. Vai aparecer o diálogo do simulador de servidor web, pressione F9 novamente.








Artigo completo (View Full Post)

 
BlogBlogs.Com.Br