quarta-feira, 29 de abril de 2009

Controle de Versão - "Seus problemas acabaram!"


Você é aquele cara que, pra controlar as versões do seu sistema, zipa os fontes e nomeia com o número da versão? Ou paga um software caríssimo de controle de versão? Ou toma uma coça pra instalar um controlador gratuito? SEUS PROBLEMAS ACABARAM!!!


Apresento-lhes os dois softwares que vão resolver todos os seus problemas: VisualSVN + TortoiseSVN.

O primeiro é um servidor Windows de Subversion, um controlador de versões gratuito muito bom. Muito simples de instalar, esquema Windows: next, next, next, finish.
Muito fácil também de manusear. Basta criar os repositórios e os usuários que acessam esses repositórios.
Então aqui vai o link do VisualSVN: http://www.visualsvn.com/server/
O segundo é um cliente de Subversion muito, muito bom mesmo. Integra-se ao Windows Explorer e é super simples de usar também. Basicamente, você deve criar uma pasta que apontará para o repositório do VisualSVN. Depois do TortoiseSVN instalado, quando você clicar com o botão direito sobre a pasta pelo Windows Explorer, vai aparecer uma opção chamada "SVN Checkout...".
Colocou arquivos/diretórios novos dentro da pasta, "Add". Quer subir os fontes? "Commit". Quer atualizar seus fontes? "Update".
No próximo post sobre o assunto, eu vou dar uma passada mais detalhada sobre esta ferramenta.
Chega de blá, blá, blá. Lá vai o link: http://tortoisesvn.net/

Então é isso. Abraço a todos e até o próximo post!

Artigo completo (View Full Post)

sábado, 25 de abril de 2009

Ajax/JSON & Delphi technologies– Webbrocker, Intraweb (ISAPI), IWTemplateProcessorHTML com CSS

Estou com muita pressa, portanto serei o mais sucinto o possível ...
O objetivo deste artigo é documentar uma solução desenvolvida para atender um cliente.
Vamos criar um serviço de consulta que deverá fornecer dados para um requisição Ajax. Para isso construiremos uma aplicação servidora (Delphi/Webbrocker) a qual acessará uma base de dados MS SQL Server (especificamente o banco de dados para exemplos “Northwind”), para executarmos uma consulta parametrizada (valor que virá na requisição cliente) cujo os dados retornados serão devidamente formatados para Json (Wik) (Não vou usar XML). Ou seja, como resposta a requisição mencionada, a aplicação servidora retornará os dado que serão consumidos pelo Ajax/Json.


Não sei, ou sei muito pouco sobre o que vc esta falando, Gerson. Então veja:
Pesquisa 1
Pesquisa 2
Marco Cantù AJax XML/DOM
Neste artigo o Cantù mostra como aproveitar o XMLData do TClientDataSet no DOM/XML (mto legal para delpheros).
Marco Cantù Artigo Ajax
Json

Em seguida, desenvolveremos o aplicativo cliente, a camada de interface, em Delphi/Intraweb, aonde implementaremos uma função Javascript. Nela usaremos o XMLHttpRequest do javascript de forma assíncrona.


Mãos à Obra, Estação ZN!


Server-Side development

Inicie um projeto Webbrocker no Delphi. Menu ►File ►New ►Other ► Web Server Application.





A tecnologia de service web que vamos usar será API do IIS (ISAPI). No WebModule1 adicione os componentes de acesso a dados: TADOConnetion, TADODataSet, TDataSetProvider, TClientDataSet. No editor de string de conexão (Edit Connection String) do ADOConnection, configure a conexão com o SQL Server e em seguida associe os Datasets (Como Associar? veja no Estação ZN). O Comando SQl que definiremos no ADODataSet1 será:



select * from Customers
where CompanyName like :CompanyName


Criando a Webbrocker Action (WebAction)

Selecione o WebModule1, de maneira que suas propriedades sejam listadas no Object Inspector. Crie uma Action e configure suas propriedades conforme ilustrado abaixo:




Evento OnAction da Action “ZnConsClientes”:



uses
Math, StrUtils;

procedure TWebModule1.WebModule1ZnConsClientesAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
const
ZnTag = '%s:%s';
var
StrStatment: String;
i, CodRetorno: Integer;
begin
with ClientDataSet1 do
begin
Params[0].AsString := '%' + Request.QueryFields.Values['znNomeCli']+ '%';
try
Open;
CodRetorno := IfThen(IsEmpty, -1, 1);
StrStatment := StrStatment +
Format(ZnTag, ['codretornoZn',
IntToStr(CodRetorno)]);

if CodRetorno = 0 then Exit;

for i := 0 to Pred(FieldCount) do
begin
StrStatment := StrStatment + ','+
Format(ZnTag, [LowerCase(ClientDataSet1.Fields[i].FieldName),
IfThen((ClientDataSet1.Fields[i].AsString = ''), QuotedStr('-'),
QuotedStr(ClientDataSet1.Fields[i].AsString))]);
end;

finally
Close;
Response.Content := Format('{%s}',[StrStatment]);
end;
end;
end;


Para usar as versões sobrecarregadas da função “IfTehn” precisamos, para este exemplo, declarar (fazer uses das ...) as units “Math” e “StrUtils” (observe na linha 2 do trecho acima).
Pronto, acabamos essa primeira parte! Antes de compilar, garanta que o ADOCOnnection esteja desconectado. Propriedade “Connected” igual a “false”. Agora sim!!! Compile a aplicação servidora para gerar a dll a qual faremos deploy no IIS (Deploy de uma dll ISAPI). Vou criar o diretório virtual no IIS com o nome de “ajaxjsonzn”.

Após ter tido sucesso em realizar o deploy, vamos testar.
Para isso digitar no browser "http://localhost/ajaxjsonzn/?znNomeCli=Cactus" para se emocionar ao ver o que acabamos de criar.


Veja a string retornada pela nossa aplicação servidora Webbrocker:

{codretornoZn:1,customerid:'CACTU',companyname:'Cactus Comidas para llevar',contactname:'Patricio Simpson',
contacttitle:'Sales Agent',address:'Cerrito 333',city:'Buenos Aires',region:'-',
postalcode:'1010',country:'Argentina',phone:'(1) 135-5555',fax:'(1) 135-4892'}



Cliente-Side development

Meu querido leitor do Estação ZN, neste momento vamos começar esta segunda parte do artigo construindo uma página html. Hum, ãhhh?!?!? Como?? Mas o assunto não é Delphi? Sim, o assunto gira em torno das tecnologias para web existentes no Delphi. O que nós vamos fazer agora é demonstrar também como o framework Intraweb pode interagir com projetos onde as páginas web são desenvolvidas a parte do Delphi. Existem várias situações onde isso poderá ser extremamente vantajoso. Por exemplo, imagine um projeto onde exista uma ênfase grande na parte de design e por isso as páginas do site são desenvolvidas especificamente pela equipe de designers e diante disto a equipe de desenvolvimento deve integrá-las a parte de lógica e persistência desenvolvida no Delphi. Este cenário no contexto Delphi é até bem comum, penso que sim.
Portanto, antes de qualquer coisa execute seu editor preferido de páginas htm e Javascript e bola pra frente. Abaixo, segue o código dá pagina que desenvolvi para este exemplo:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
<style type="text/css">
<!--
.AreaTexto {
font-family: "Comic Sans MS", "Courier New", Georgia;
width: 420px;
height:540px;
background-color:#FFFF38;
}
-->

</style>
<script type="text/javascript">

var ZnXmlAjaxHttpObj;

function ZnGetClienteWsAjx(ZnMyName) {

alert('estou na função!');
if (typeof XMLHttpRequest != "undefined"){ZnXmlAjaxHttpObj = new XMLHttpRequest();}
else{
ZnXmlAjaxHttpObj = new ActiveXObject('Msxml2.XMLHTTP');
if (!ZnXmlAjaxHttpObj){ZnXmlAjaxHttpObj = new ActiveXObject('Microsoft.XMLHTTP');}
}
alert(ZnMyName.value);
var ZnSpan = document.getElementById("IWLABEL1");

ZnSpan.innerHTML = "Estaçaõ Zn: Buscando dados do Cliente pelo nome fornecido: " + ZnMyName.value + " ....";

var url = "http://localhost/ajaxjsonzn/?znNomeCli="+ ZnMyName.value;
ZnXmlAjaxHttpObj.open("GET", url, true);
ZnXmlAjaxHttpObj.onreadystatechange = ZnDynProcessaReqBuscaCliente;
ZnXmlAjaxHttpObj.send(null);
}

function ZnDynProcessaReqBuscaCliente() {
var ZnSpan2 = document.getElementById("IWLABEL2");
var ZnElement = document.getElementById("IWEDIT1");
ZnSpan2.innerHTML = 'Processando ..................';
if (ZnSpan2.innerHTML.indexOf("buscando dados",0) >= 0){ZnSpan2.innerHTML = "Processando ...";}
else {ZnSpan2.innerHTML = "<b>buscando dados do Cliente: </b>" + ZnElement.value + " ....";}

if (ZnXmlAjaxHttpObj.readyState == 4) {
if (ZnXmlAjaxHttpObj.status == 200) {
processJsonEstacaoZn(ZnXmlAjaxHttpObj.responseText);
}
}
else return false;
}

function processJsonEstacaoZn(obj1) {

var ObjLandjah;
eval('ObjLandjah = ' + obj1);
var Aux =
" <br /> customerid: "+ ObjLandjah.customerid +
" <br /> contactname: "+ ObjLandjah.contactname +
" <br /> contacttitle: "+ ObjLandjah.contacttitle +
" <br /> companyname: "+ ObjLandjah.companyname +
" <br /> country: "+ ObjLandjah.country +
" <br /> CEP/postal code: " + ObjLandjah.postalcode +
"<br /> Região: " + ObjLandjah.region +
"<br /> Cidade: " + ObjLandjah.city +
"<br />Logradouro: " + ObjLandjah.address +
" <br /> fax: " + ObjLandjah.fax +
" <br /> phone: "+ ObjLandjah.phone;
alert(Aux);
document.getElementById("cj").innerHTML += '- <b>Ninguém vai subir #@#@%#@%#%@ ... vai ficar todo mundo quietinho ae.</b>';
document.getElementById("cj").innerHTML += Aux;
document.getElementById("IWMEMO1").innerHTML += ' \n <b>100% Quatorze? </b>';
document.getElementById("IWMEMO1").innerHTML += ' \n ************************************';
//****************************************************

var insertData = "<b> Resultado Consulta www.estacaozn.blogspot.com:</b>";
try {
//alert('Cod Retorno: ' + ObjLandjah.codretornoZn);
switch (ObjLandjah.codretornoZn * 1) {
case 1:
document.getElementById("IWMEMO1").innerHTML += ' \n - Cavera meu Capitão. ';
document.getElementById("IWMEMO1").innerHTML += ' \n ************************************';
insertData += " <br /> customerid: "+ ObjLandjah.customerid +
" <br /> contactname: "+ ObjLandjah.contactname +
" <br /> contacttitle: "+ ObjLandjah.contacttitle +
" <br /> companyname: "+ ObjLandjah.companyname +
" <br /> country: "+ ObjLandjah.country +
" <br /> CEP/postal code: " + ObjLandjah.postalcode +
"<br /> Região: " + ObjLandjah.region +
"<br /> Cidade: " + ObjLandjah.city +
"<br />Logradouro: " + ObjLandjah.address +
" <br /> fax: " + ObjLandjah.fax +
" <br /> phone: " + ObjLandjah.phone;
//alert("Case, estou aqui");
// Abaixo, veja como atribuir valor do JavaScript Object Notation ao IWMemo e aos IWEdits
document.getElementById("IWMEMO1").innerHTML += ' \n ************************************';
document.getElementById("CEP").value = ObjLandjah.postalcode;
document.getElementById("CEP").disabled = true;
document.getElementById("IWMEMO1").innerHTML += " \n CEP: " + ObjLandjah.postalcode;
document.getElementById("CONTACTNAME").value = ObjLandjah.contactname;
document.getElementById("CONTACTNAME").disabled = true;
document.getElementById("IWMEMO1").innerHTML += " \n Contato: " + ObjLandjah.contactname;
document.getElementById("CONTACTTITLE").value = ObjLandjah.contacttitle;
document.getElementById("CONTACTTITLE").disabled = true;
document.getElementById("IWMEMO1").innerHTML += " \n Contato: " + ObjLandjah.contacttitle;
document.getElementById("CIDADE").value = ObjLandjah.city;
document.getElementById("CIDADE").disabled = true;
document.getElementById("IWMEMO1").innerHTML += " \n Cidade: " + ObjLandjah.city;
document.getElementById("BAIRRO").value = "Bla!";
document.getElementById("BAIRRO").disabled = true;
document.getElementById("FAX").value = ObjLandjah.fax;
document.getElementById("FAX").disabled = true;
document.getElementById("IWMEMO1").innerHTML += "\n Fax: " + ObjLandjah.fax;
document.getElementById("LOGRADOURO").value = ObjLandjah.address;
document.getElementById("LOGRADOURO").disabled = true;
document.getElementById("IWMEMO1").innerHTML += "\n Logradouro:" + ObjLandjah.address;
document.getElementById("COMPANYNAME").value = ObjLandjah.companyname;
document.getElementById("COMPANYNAME").disabled = true;
document.getElementById("IWMEMO1").innerHTML += "\n Nome da Empresa:" + ObjLandjah.companyname;
document.getElementById("COUNTRY").value = ObjLandjah.country;
document.getElementById("COUNTRY").disabled = true;
document.getElementById("IWMEMO1").innerHTML += "\n Pais:" + ObjLandjah.country;
document.getElementById("UF").value = ObjLandjah.region;
document.getElementById("UF").disabled = true;
document.getElementById("IWMEMO1").innerHTML += " \n Região: " + ObjLandjah.region;
document.getElementById("PHONE").value = ObjLandjah.phone;
document.getElementById("PHONE").disabled = true;
document.getElementById("IWMEMO1").innerHTML += " \n Tel: " + ObjLandjah.phone;
document.getElementById("IWMEMO1").innerHTML += '\n ************************************';
break;
case -1: insertData += "Cliente não encontrado!"; break;
case -2: insertData += "Valor digitado inválido!"; break;
case -3: insertData += "Ta com nojinho 02?."; break;
case -4: insertData += "AH ESSA ALTURA DO CAMPEONATO VC TA SEM AH BANDOLEIRA ??!"; break;
default: "PEDE PRA SAIR 01. Pede pra sair.";
}
}
catch(Error) {
insertData = "<br> <font color=#FF0000> eRrO. TIRA ESSA ROUPA PRETA QUE VC NÃO É CAVEIRA. </font> As Landjhas de mirandjas!!!"
}

document.getElementById("IWLABEL2").innerHTML += insertData;
document.getElementById("IWLABEL1").innerHTML += " <br /><b> Os senhores estão bem? Os senhores estão feridos? Algum dos senhores estão baleados? " +
" Então, no próximo post vcs vão aprender a carregar corpos!!! </b>"
document.getElementById("IWMEMO1").innerHTML += ' \n ';
}



</script>

</head>

<body>
<form id="form1" name="form1" method="post" action="">
<div id="PosControles" style="position: absolute; top: 32px; left: 12px; width: 887px; height: 92px; background-color: #3399CC;
font-size:16px; font-weight:400" align="justify"><br />Digite o Nome do Cliente: {%IWEdit1%} | {%IWButton1%}
<br>
{%Logradouro%}{%Bairro%}{%Cidade%} {%UF%}{%CEP%} {%CompanyName%}
{%ContactName%}
{%ContactTitle%}
{%Phone%}
{%Fax%}
{%Country%}
{%IWLink1%} <a href="http://localhost/estacaozncliente">Reload Page</a></div>
<div id="PosSpan" style="position: absolute; top: 128px; left: 12px; width: 440px; height: 580px; background-color: #99FF99;">
{%IWLabel1%} {%IWLabel2%}
<span id="cj">
</span>
</div>
<div id="PosMemo" style="position: absolute; top: 128px; left: 458px; width: 440px; height: 580px; background-color: #99FF99;"
align="center"><p>
{%IWMEMO1%}
testando!!
</div>


</form>
</body>
</html>


Salve a página html (o arquivo html, referente a página que acabamos de criar) com o nome de “ZnPageAjaxJsonIntraweb.html”.




O próximo passo, será criar a aplicação cliente intraweb. Retornemos ao Delphi então, para iniciarmos um projeto Intraweb ISAPI. No menu File ► New ►Other ►Intraweb ►ISAPI Application.

Adicione no IWForm1 os seguintes componentes:


IWTemplateProcessorHTML1: TIWTemplateProcessorHTML;
IWLabel1: TIWLabel;
IWEdit1: TIWEdit;
IWButton1: TIWButton;
IWMemo1: TIWMemo;
CEP: TIWEdit;
UF: TIWEdit;
Bairro: TIWEdit;
Logradouro: TIWEdit;
Cidade: TIWEdit;
IWLabel2: TIWLabel;
CompanyName: TIWEdit;
ContactName: TIWEdit;
ContactTitle: TIWEdit;
Phone: TIWEdit;
Fax: TIWEdit;
Country: TIWEdit;


No evento OnCreate do IWForm1 codifique conforme ilustrado abaixo:

procedure TformMain.IWAppFormCreate(Sender: TObject);
begin
Self.TemplateProcessor := IWTemplateProcessorHTML1;
IWTemplateProcessorHTML1.Templates.default := 'ZnPageAjaxJsonIntraweb.html';
IWLabel1.Caption := ' ';
IWMemo1.Font.Enabled := False;
IWMemo1.Font.CSSStyle := 'AreaTexto';
CEP.Width := 80;
UF.Width := 40;
Cidade.Width := 120;
Logradouro.Width := 180;
Bairro.Width := 90;
IWButton1.ExtraTagParams.Add('onClick=ZnGetCLienteWsAjax(IWEDIT1)');
IWMemo1.Lines.Add(' ');
IWEdit1.Text := 'Cactus Comidas para llevar';
end;


Observe na linha 7, estou atribuindo dinamicamente ao IWMemo1 uma classe CSS (“'AreaTexto'”) a qual está definida na página HTML que criamos anteriormente.

Ok, muito bem, meus amigos e minhas amigas, a parte referente a aplicação cliente termina aqui!! Isso é mto bom! Agora, é chegado o momento do bom e velho amigo deploy. Para isso, um “build all” na aplicação Intraweb (alt, p, b) é bem vindo, ela será compilada e a dll para deploy será gerada. So .. next step ... enjoy yourself ...
O nome do diretório virtual que vou criar será “estacaozncliente”.


No mesmo diretório onde está a dll gerada pelo Delphi na compilação deste projeto Intraweb, crie um diretório onde ficará a pagina html que o IWTemplateProcessorHTML1 vai trabalhar. Me refiro ao arquivo da página que criamos anteriormente, “ZnPageAjaxJsonIntraweb.html”. Esse diretório tem que se chamar “Templates”, desta forma não precisamos definir nenhuma configuração para TemplateProcessorHTML encontrar o arquivo.


Testando Aplicação cliente IntraWeb/ISAPI.



O link “Reload Page” coloquei para facilitar o desenvolvimento da aplicação cliente. Assim evito de ficar digitandoa url do serviço toda vez que houver alguma alteração, seja na aplicação servidora, seja na aplicação cliente, ou na página html.

Conclusão
A partir da experiência realizada e documentada neste artigo, destaco as seguintes observações:
Usar a tecnologia Ajax nos seus sistemas web, sites, ou serviços traz, além de um ganho de performance, escalabilidade e interoperabilidade. Isso porque a solução Ajax é independente da tecnologia que esteja sendo utilizada no client-side. Pretendo, para o próximo post documentar um exemplo da mesma solução desenvolvida neste arquivo, sendo que a camada cliente desenvolverei em Java com o Netbeans.
O uso do JavaScript Object Notation (Json) descomplica muito a desenvolvimento de uma solução baseada em Ájax.
Um ponto muito importante neste artigo é o emprego do componente processador de “templates” o IWTemplateProcessorHTML. Ele permite que seu form Intraweb seja construído em cima de um arquivo HTML criado separadamente. Dessa forma um leque de possibilidades se abre. No momento a que eu mais quero destacar é que com isso é possível modularizar seu projeto colocando toda a parte de layout, disign, bem como o processamento client-side. Com isso, todo o Javascript que trabalhamos nos artigos anteriores pode ser definido na página web. Igualzinho é feito por webmasters, inclusive usando a tag “src” para códigos Javascript que ficam em arquivos separados.
Javascript placement: o Código JavaScript pode estar fisicamente disposto em um diretório específico para este fim, num arquivo “.js” separado da página HTML. Isso melhora inda mais a modularização do seu sistema, site, portal, etc...
O arquivo fonte do Javascript em questão é referenciado na página HTML usando a tag “script” o atributo "src" com o nome do arquivo e o path definidos como valor.


<head>
<script language="JavaScript" src="ZnJavaScriptFile.js"></script>
</head>

Estive conversando com o Felipe e com o Malta sobre os exemplos anteriores que estive postando. Onde demonstrei o código Javascript definido como string no meio do código Delphi. Essa forma de implementar é um metodologia que condeno enfaticamente nos meus projetos. Inclusive, todos dois, tanto o Felipe, quanto o Malta, concordam e estavam me chamando a atenção sobre isso. Que o Javascript no meio do código Delphi, mesmo eu “organizando”, através de constantes o caos, é uma solução macarrônica, feia, nojenta, asquerosa. Entretanto, eu fiz dessa forma nos exemplos anteriores porque acredito que assim o artigo que estou escrevendo para o Estação ZN fica menor, menos complexo, mais didático, na medida em que eu procuro estar focado nos assuntos que pretendo falar naquele momento. Quando estou postando aqui minha ênfase é totalmente didática. Entendo que para passar um conhecimento complexo ele deve ser simplificado, de maneira que seja reduzida toda complexidade inerente ao problema em questão.
Portanto, de agora em diante, sugiro que você cuide para que, imperativamente, o Javascript fique separado da aplicação Delphi. Para isso temos basicamente dois caminhos a tomar: O primeiro seria usar o “IWTemplateProcessorHTML”. Uma segunda opção seria usar um “LoadFromFile”, ou seja ler dinamicamente arquivos com as funções Javascript. Se você optar por usar o IwTemplateProcesso, implementar desta forma, o “js” na página HTML, é uma ação intuitiva. Como fazer isso está demostrado neste artigo. Caso negativo, uma idéia, proposta pelo Malta, que eu gostei bastante, seria do Delphi, fazer um “LoadFromFile” de um arquivo, onde estaria com código JavaScript parametrizado (semelhante a um parâmetro de um comando SQL). A idéia é usar, ao invés de parâmetros de “FormatString (%s)” uma sintaxe como nome de parâmetros (:nome) e fazer substituição por pares (nome, valor). Deixe-me explicar melhor:
Veja num dos artigos anteriores: O Código Javascript que defini não tem “%s” para usar na função Format? Então, substitua todos o “%s” por uma sintaxe própria, que estaríamos criando, que represente o nome de um parâmetro. Por exemplo: ..... :par1 ... :idade ... :cidade... :idade. A exemplo de um comando SQL num TSQLQurey. Para trabalhar em conjunto, criaríamos uma função para substituir os parâmetros por valores em runtime, por exemplo: “function ZnReplaceParams(const znParmName, znParamValue: String)”. A chamada seria: “ReplaceParams('idade', '18');”. De cara podemos citar como vantagens melhor legibilidade do código Javascript, além de não fica dependente de posição (como é o caso do “Format(%s)”). Dentro da função caixa preta “ZnReplaceParams”, um StringReplace pode dar conta do recado, com rfReplaceAll e rfIgnoreCase. O que inclusive facilita quando você precisa repetir o mesmo valor várias vezes no mesmo script bastaria repetir o nome da "macro" ou parâmetro. Boa Malta, Estação Zn agradece! Tks!!
Uma outra abordagem seria usar argumentos na própria função Javascript, a qual vai estar definida num arquivo “.txt”, ou “.js”, que seja, e no Delphi atribuir as definições das chamadas a essas funções nos eventos “Javascript”, nas propriedades “ExtragParams”, ou “ScriptEvent”. Como exemplifiquei no artigo sobre validação de CIC.


Falar sobre modularização é muito simples. Mas demonstrar, é no mínimo trabalhoso. Eu prefiro inclusive demonstrar o “como não fazer”, para melhorar, aumentar a aderência da explicação do sobre “como fazer”.

Aconselho ao desenvolvedor que decidir usar o Delphi/Intraweb ter muita atenção na hora de referenciar os objetos, inputs, submits, selects, criados pelo Intraweb, no que tange a caixa do nome dos controles definidos no Delphi. Isso pq o Delphi não é case sensitive, conseqüentemente o desenvolvedor delphi não deverá, a pricípio, estar acostumado com essa restrição. Portanto, cuidado com comandos do tipo “document.getElementById("IWMEMO1")”, porque todo componente Intraweb é criado na página html com o nome em CAIXA ALTA. A função “getElementById” é sensível a caixa.
Programar em Javascript exige muita atenção a questões extra-intelectuais, pois você não vai poder contar com code insight, nem auto-complemento de código (code complete) e ainda existe o overhead de atenção na questão do case sensitive sem contar que as mensagens de erro não são tão amigáveis. Uma ferramenta que pode ajudar neste sentido são os plugins para desenvolvimento web do Fire Fox.
Outro ponto adverso é desenvolver um script client-side compatível com todos os browsers. Isso exige bastante de quem está desenvolvendo. Entretanto os bônus adquiridos em usar enfaticamente Javascript acaba compensando todos os ônus listados. Além disso, com o tempo o desenvolvedor ganha prática nesta abordagem e esses fatores negativos acabam perdendo sua força.
A tecnologia Json ainda é bem nova, nas minhas pesquisas encontrei muito pouca gente usando. Mas pra minha surpresa um número razoável de pessoas, blogs, falando sobre. Dei uma pesquisada no google trends http://www.google.com/trends sobre as buscas sobre Json.





Abaixo, código completo das units Delphi:

Aplicação Cliente Intraweb


unit IWUnit1;
{PUBDIST}

interface

uses
IWAppForm, IWApplication, IWTypes, IWCompMemo, IWCompButton, IWCompEdit,
Controls, IWControl, IWCompLabel, Classes, IWLayoutMgr,
IWTemplateProcessorHTML, IWHTMLControls;

type
TformMain = class(TIWAppForm)
IWTemplateProcessorHTML1: TIWTemplateProcessorHTML;
IWLabel1: TIWLabel;
IWEdit1: TIWEdit;
IWButton1: TIWButton;
IWMemo1: TIWMemo;
CEP: TIWEdit;
UF: TIWEdit;
Bairro: TIWEdit;
Logradouro: TIWEdit;
Cidade: TIWEdit;
IWLabel2: TIWLabel;
CompanyName: TIWEdit;
ContactName: TIWEdit;
ContactTitle: TIWEdit;
Phone: TIWEdit;
Fax: TIWEdit;
Country: TIWEdit;
procedure IWAppFormCreate(Sender: TObject);
public
end;

implementation
{$R *.dfm}

uses
ServerController, IWForm;

//ajaxconcorretor

procedure TformMain.IWAppFormCreate(Sender: TObject);
begin
Self.TemplateProcessor := IWTemplateProcessorHTML1;
IWLabel1.Caption := ' ';
IWMemo1.Font.Enabled := False;
IWMemo1.Font.CSSStyle := 'AreaTexto';
CEP.Width := 80;
UF.Width := 40;
Cidade.Width := 120;
Logradouro.Width := 180;
Bairro.Width := 90;
IWButton1.ExtraTagParams.Add('onClick=return ZnGetClienteWsAjx(IWEDIT1);');
IWMemo1.RawText := True;
IWMemo1.Lines.Add(' ');
IWEdit1.Text := 'Cactus Comidas para llevar';
end;

end.



Aplicação Servidora Webbrocker



unit Unit1;

interface

uses
SysUtils, Classes, HTTPApp, DBClient, Provider, DB, ADODB;

type
TWebModule1 = class(TWebModule)
ADOConnection: TADOConnection;
ADODataSet1: TADODataSet;
DataSetProvider1: TDataSetProvider;
ClientDataSet1: TClientDataSet;
ClientDataSet1CustomerID: TWideStringField;
ClientDataSet1CompanyName: TWideStringField;
ClientDataSet1ContactName: TWideStringField;
ClientDataSet1ContactTitle: TWideStringField;
ClientDataSet1Address: TWideStringField;
ClientDataSet1City: TWideStringField;
ClientDataSet1Region: TWideStringField;
ClientDataSet1PostalCode: TWideStringField;
ClientDataSet1Country: TWideStringField;
ClientDataSet1Phone: TWideStringField;
ClientDataSet1Fax: TWideStringField;
procedure WebModule1ZnConsClientesAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;

var
WebModule1: TWebModule1;

implementation

{$R *.dfm}

uses
Math, StrUtils;

procedure TWebModule1.WebModule1ZnConsClientesAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
const
ZnTag = '%s:%s';
var
StrStatment: String;
i, CodRetorno: Integer;
begin
with ClientDataSet1 do
begin
Params[0].AsString := '%' + Request.QueryFields.Values['znNomeCli']+ '%';
try
Open;
CodRetorno := IfThen(IsEmpty, -1, 1);
StrStatment := StrStatment +
Format(ZnTag, ['codretornoZn',
IntToStr(CodRetorno)]);

if CodRetorno = 0 then Exit;

for i := 0 to Pred(FieldCount) do
begin
StrStatment := StrStatment + ','+
Format(ZnTag, [LowerCase(ClientDataSet1.Fields[i].FieldName),
IfThen((ClientDataSet1.Fields[i].AsString = ''), QuotedStr('-'),
QuotedStr(ClientDataSet1.Fields[i].AsString))]);
end;

finally
Close;
Response.Content := Format('{%s}',[StrStatment]);
end;
end;
end;


end.


Artigo completo (View Full Post)

quarta-feira, 22 de abril de 2009

Navegar? Pois é, eu preciso ...

Opera

Faz tempo que eu não usava o Opera (Opera Software). Acho que a última vez foi por volta de 1999. Volta e meia, navegando, vejo alguém falando bem da nova versão. Prontamente, instalei e gostei muito! Realmente é bem rápido. Imediatamente você percebe isso. Mas o melhor vem depois, se você gosta de ficar antenado, e conhecer coisas que te tragam vantagens vale a pena experimentar e conferir o que ele tem de bom.



Artigo completo (View Full Post)

O Cara é o Kutiman

É impressionantemente, surpreendente, sensacional, criativo, positivo, sadio, anárquico, idoneamente geek, inteligentemente livre e devastadoramente afinado a nova mídia.

Mother of All Funk Chords - E9


Nada mais a dizer ... estou sem palavras!!!! :-)
Thru-you Aperte o play ...

I'm New
Destaque para ElexisTrinity, para o rapper HE 513knect e também para segunda cantora (Misteriosa Mandy).


Se você ja assistiu o video, prossiga: O que ele fez do Noturno de Chopin foi magnífico, acho pouco provável que isso seja percebido facilmente, mas basta conferir no video original - Chopin Nocturne Number 13 in C-Minor Op.48 No.1 . Eu percebi de cara pq cresci ouvindo minha mãe tocar Chopin de forma maravilhosa, sempre.

Wait For Me



OBS: pOR fAvoR, Não deixe de conferir na totalidade as informações sobre o video que ele escreve.

Artigo completo (View Full Post)

domingo, 19 de abril de 2009

Mídias na Web - A questão de propriedade intelectual

Encontrei no IDG Now uma entrevista interessante com dicas de como fazer uso de imagens baixadas da web.
Embora o assunto principal da entrevista seja sobre “como usar imagens da web”, vale dar uma olhada porque são dadas dicas que servem para qualquer tipo de mídia produzida e publicada na web.

Baixei o áudio da entrevista.









OBS, Importante visitar:
Creative Commons Barsil
Creative Commons org/
Muita coisa interessante lá ...

Artigo completo (View Full Post)

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)

 
BlogBlogs.Com.Br