TagriaLib (Biblioteca visual para java)

Olá a todos ,

Pra quem desenvolve em java web gostaria de lhes apresentar o mais novo produto de minha empresa , que vem a ajudar a resolver um problema muito comum na camada view quando se trata de frameworks action based (struts,spring,vraptor,mentawai,etc) que é encontrar algo pronto e de qualidade .

O que é TagriaLib ?

 Tagria Lib (TagLib Rich Internet Application) é uma poderosa biblioteca visual escrita especificamente para rodar em JAVA no ambiente WEB , tem como principal atrativo a facilidade  na criação , manutenção e desenvolvimento de softwares de alta qualidade na camada de apresentação/visualização . TagriaLib é a única biblioteca na internet que é compatível com os principais frameworks MVC (Action Based) do mercado (Struts 2,Vraptor 3,Mentawai 2,Spring MVC,Http Servlet) ou qualquer outro framework que aceite jsp + jstl em sua camada de visualização .

Quais suas características ?

Conjunto de componentes ricos (HtmlEditor, Dialog, AutoComplete, Buttons, Forms, Grids e muito mais).
Suporte a ajax.
Levíssimo , facil instalação e quase zero configuração
Suporte a tematização e internacionalização
100% W3C (HTML,CSS) compatível.
Garantia de compatibilidade com os maiores navegadores do mercado.
100% Javascript compatível com (JQuery + JQueryUI).

Tagria Lib tem como objetivo substituir o JSP puro + HTML + Javascript + CSS, seus diversos problemas e má práticas que acarretam [b]quando usados incorretamentes[/b] no ambiente de desenvolvimento como por exemplo:

Incompatibilidade de layout entre browsers (cada browser renderiza de um modo dependendo de como o html + CSS são escritos).
Despadronização de objetos (desenvolvedores diferentes, constroem objeto de modo diferente com funcionalidades diferentes, com cores diferentes, etc..).
Problemas com javascripts incompatíveis entre browsers.

No site : http://tagrialib.com é possível visualizar todos os detalhes do projeto.
No site : http://jslsolucoes-tagria-doc.appspot.com/ é possível ver todos os objetos existentes,documentação , funcionamento e códigos fontes de exemplos.

Qualquer dúvida entre em contato . Abraços a todos.

Boa iniciativa! Alguns pontos que não gostei:

  • O form é baseado em table, ou seja, nada de tableless.
  • A configuração dos componentes fica mais chata do que usando um jQueryUI da vida. Tudo bem que é uma taglib, mas os nomes dos parâmetros ficaram muito grandes, na minha opinião.
  • O código de exemplo na demo do detail table não me pareceu ser o que aparece na demo. Se for, ficou com um aspecto de muita mágica num componente visual.

“O form é baseado em table, ou seja, nada de tableless.”
R:. Form ser baseado em tabela é bastante discutivel , até mesmo o tabless que acabou virando a div mania , alias web semantica é muito discutível , pois vários ótimos frameworks vide os componentes JSF (Primefaces),GWT , e muitos outros visuais utilizam table para formatar formulário , eu creio , que quando se usa algo que abstrai o objetivo final , sendo w3c compativel , está ótimo , pois se fosse um crime tão grande , quando marcações do tipo <td><input></td> nao deveria ser w3c compativel. Voce esta pensando em formulario linear é tranquilo , agora o problema é utilizar varios campos numa mesma linha e conseguir ser compativel com vários browsers apenas utilizando css e nao estou falando de css 3 nao , estou falando ser compativel com as primeiras versoes de navegadores .

“A configuração dos componentes fica mais chata do que usando um jQueryUI da vida. Tudo bem que é uma taglib, mas os nomes dos parâmetros ficaram muito grandes, na minha opinião.”
R:. Quanto a configuração eu já vejo o contrario , ja que pra mim o problema maior é erro humano em digitação e erro de javascript alem de outros varios tipos de problema quando se faz na mao coisas corriqueiras , concordo que voce fica mais livre pra programar mas ai depende do tamanho da liberdade que voce precisa , depois que passei a utilizar a biblioteca faz tempo que não sei o que é entrar no site do jquery ui e olhar documentação pra um parametro ou outro que preciso. Ganha se muito em produtividade , e outros aspectos , alem de garantia que vai rodar em qualquer navegador sem quebrar . Ex : coisas bobas como esquecer uma virgula num javascript no firefox roda normal , agora esquece uma virgula solta no Ie pra voce ver o que acontece.
Quanto aos nomes eu tentei ser o mais claro possível quanto ao que o atributo faz , é algo que pode ser melhorado é lógico , mas como sempre falo um bom nome de atributo mesmo sendo grande tem varias vantagens , mais facil de recordar , é intuitivo , além do que qualquer ide com autocomplete de taglib ja disponibiliza tudo pronto pra voce.

“O código de exemplo na demo do detail table não me pareceu ser o que aparece na demo. Se for, ficou com um aspecto de muita mágica num componente visual”
R:. É assim mesmo facil do jeito que está , Rich Internet Application , assim como todos os outros componentes , nem tem muita magica esse componente , é o objeto que trata listas em formulários, ou seja , o famoso “nomedocampo[]” , em que muita gente , principalmente iniciante quebra a cabeça pra resolver .

Essa é outra vantagem de se usar uma abstração para fazer algo , não precisa se ater a detalhes de como funciona ou como faz , assim como eu acho magica o que hibernate,vraptor,engine de jogos ou qualquer outro framework ótimos realizam . São algumas perguntas simples que devem ser feitas antes de adotar : É facil de usar ? Tem boa documentação ? Roda bem não importando o ambiente ? Se as respostas são sim , não me agrega no momento saber como funciona , pois outra pessoa ja quebrou a cabeça por mim de como fazer , só sei que roda bem , escala e atende bem o que preciso. O mesmo princípio vale pra tudo qualquer outra ferramente , seja software ou não , saber como o telefone funciona por dentro e como faz a magica , ou como o microondas esquenta e como faz a magica não é interessante , voce sabe que disca e consegue falar e ouvir outra pessoa do outro lado da linha , ou que voce coloca o tempo e a comida esquenta.

gostei

[quote=boneazul]“O código de exemplo na demo do detail table não me pareceu ser o que aparece na demo. Se for, ficou com um aspecto de muita mágica num componente visual”
R:. É assim mesmo facil do jeito que está , Rich Internet Application , assim como todos os outros componentes , nem tem muita magica esse componente , é o objeto que trata listas em formulários, ou seja , o famoso “nomedocampo[]” , em que muita gente , principalmente iniciante quebra a cabeça pra resolver .

Essa é outra vantagem de se usar uma abstração para fazer algo , não precisa se ater a detalhes de como funciona ou como faz , assim como eu acho magica o que hibernate,vraptor,engine de jogos ou qualquer outro framework ótimos realizam . São algumas perguntas simples que devem ser feitas antes de adotar : É facil de usar ? Tem boa documentação ? Roda bem não importando o ambiente ? Se as respostas são sim , não me agrega no momento saber como funciona , pois outra pessoa ja quebrou a cabeça por mim de como fazer , só sei que roda bem , escala e atende bem o que preciso. O mesmo princípio vale pra tudo qualquer outra ferramente , seja software ou não , saber como o telefone funciona por dentro e como faz a magica , ou como o microondas esquenta e como faz a magica não é interessante , voce sabe que disca e consegue falar e ouvir outra pessoa do outro lado da linha , ou que voce coloca o tempo e a comida esquenta.

[/quote]

Me referia aos botões de remover e submeter o formulário. Acho completamente estranho não ter referência alguma de onde ele vai executar as coisas.

[quote=Ataxexe][quote=boneazul]“O código de exemplo na demo do detail table não me pareceu ser o que aparece na demo. Se for, ficou com um aspecto de muita mágica num componente visual”
R:. É assim mesmo facil do jeito que está , Rich Internet Application , assim como todos os outros componentes , nem tem muita magica esse componente , é o objeto que trata listas em formulários, ou seja , o famoso “nomedocampo[]” , em que muita gente , principalmente iniciante quebra a cabeça pra resolver .

Essa é outra vantagem de se usar uma abstração para fazer algo , não precisa se ater a detalhes de como funciona ou como faz , assim como eu acho magica o que hibernate,vraptor,engine de jogos ou qualquer outro framework ótimos realizam . São algumas perguntas simples que devem ser feitas antes de adotar : É facil de usar ? Tem boa documentação ? Roda bem não importando o ambiente ? Se as respostas são sim , não me agrega no momento saber como funciona , pois outra pessoa ja quebrou a cabeça por mim de como fazer , só sei que roda bem , escala e atende bem o que preciso. O mesmo princípio vale pra tudo qualquer outra ferramente , seja software ou não , saber como o telefone funciona por dentro e como faz a magica , ou como o microondas esquenta e como faz a magica não é interessante , voce sabe que disca e consegue falar e ouvir outra pessoa do outro lado da linha , ou que voce coloca o tempo e a comida esquenta.

[/quote]

Me referia aos botões de remover e submeter o formulário. Acho completamente estranho não ter referência alguma de onde ele vai executar as coisas.[/quote]

Bom acho que não entendi direito seu questionamento nessa parte , mas vamos lá. Abaixo segue o fonte que voce viu :

    <html:form action="/sua/url/que/trata/os/dados" label="Tabela detalhe">  
        <html:detailTable  id="pessoas" label="Pessoas listadas" list="${pessoaList}"   
     var="pessoa">  
            <html:detailTableColumn label="Nome da pessoa">  
                <html:input help="oi" name="pessoas[].nome" size="20" value="${pessoa.nome}"/>  
            </html:detailTableColumn>  
            <html:detailTableColumn label="Data de nascimento" mandatory="true">  
                <html:input name="pessoas[].dataNascimento" mask="99/99/9999" value="${pessoa.dataNascimento}"/>  
            </html:detailTableColumn>  
            <html:detailTableColumn label="Salário" mandatory="true">  
                <html:input name="pessoas[].salario" moneyMask="true" value="1000" size="6"/>  
            </html:detailTableColumn>  
            <html:detailTableColumn label="Gosta de chocolate" mandatory="true">  
                <html:input type="checkbox" name="pessoas[].gostaChocolate" value="S"   
     checked="${pessoa.gostaChocolate}"/>  
            </html:detailTableColumn>  
            <html:detailTableHidden name="pessoas[].id" value="${pessoa.id}"></html:detailTableHidden>  
        </html:detailTable>  
    </html:form>  

Na primeira linha action="/sua/url/que/trata/os/dados":

<html:form action="/sua/url/que/trata/os/dados"...

voce fala que url trata os dados depois da submissao , no mais é tudo em tempo de pagina , e nao ha dados trafegando , é tudo javascript , simples .

Entao no seu vraptor,spring,servlet,struts ou sei la o que voce vai ter disponivel depois da submissao no request os campos com os names em forma de lista que voce mesmo definiu, isso é padrao , serve pra php , jsp , etc ,

Entao pro exemplo acima vamos supor que voce preencha 3 linhas da tabela detalhe , na sua url ou metodo que trata os dados voce vai ter disponivel no request.

pessoas[0].nome = dadolinha1
pessoas[0].dataNascimento = dadolinha1
pessoas[0].salario = dadolinha1
pessoas[0].gostaChocolate = dadolinha1

pessoas[1].nome = dadolinha2
pessoas[1].dataNascimento = dadolinha2
pessoas[1].salario = dadolinha2
pessoas[1].gostaChocolate = dadolinha2

pessoas[2].nome = dadolinha3
pessoas[2].dataNascimento = dadolinha3
pessoas[2].salario = dadolinha3
pessoas[2].gostaChocolate = dadolinha3

esse indice o proprio objeto que preenche pra voce na sequencia entao ja chega pronto pra voce utilizar, vou adicionar na documentação um exemplo tambem do código java que recebe os dados em cada framework para melhorar o entendimento do objeto e como os dados chegam , talvez seja isso sua dúvida e ja sana a duvida de outros também.

ja aproveitando o gancho se fosse vraptor por exemplo e sua convencao voce faria :

 @Resource
 public class PessoaController{
     
      //Voce definiu na action de seu form
     @Path("/sua/url/que/trata/os/dados")
     public void trataLista(List><Pessoa> /*Voce definiu no name do objeto*/pessoas){
            for(Pessoa pessoa:pessoas){
                   System.out.println(pessoa.getNome());
            }
     }
}

Simples assim.

É impossível fazer um formulário igual aos com table usando tags bonitinhas, pelo menos desconheço como. Quando digo igual digo igual no sentido de que o tamanho dos labels deve crescer de acordo com o tamanho do texto, fazer com tamanho fixo é fácil

No caso a única maneira q sei de imitar table com div seria trocar cada

e
por divs e usar display: table, display: table-row e display: table-cell neles

Detail Table, o que acontece com o objeto depois que clico em remover?!?!
E nao vou recebê-lo no Controller né!!!..
Como vou saber os registros q o cara deletou? E se tiver paginação?
Como fazer a paginação?
E Atributos com relacionamento N-N, como q fica?

No Grid pq tem:

<html:grid id="pessoas" label="Listagem de pessoas"   
    totalResults="${fn:length(pessoaList)}" var="pessoa" list="${ pessoaList }"  
        url="/grid/index"  print="true">  

o atributo “totalResults”? pq ele nao pega esse dado na propria lista, dentro do componente?

[quote=d34d_d3v1l]Detail Table, o que acontece com o objeto depois que clico em remover?!?!
E nao vou recebê-lo no Controller né!!!..
Como vou saber os registros q o cara deletou? E se tiver paginação?
Como fazer a paginação?
E Atributos com relacionamento N-N, como q fica?
[/quote]

“Detail Table, o que acontece com o objeto depois que clico em remover!!!E nao vou recebê-lo no Controller né!!!..”
Nao se o usuario remover ou adicionar linhas seu controller nem vai saber ainda , ele só vai saber isso quando houver a submissao , a vantagem é que voce nao consome recurso de servidor toda hora , e so recebe a versao final que o cara realmente precisa.

"Como vou saber os registros q o cara deletou? E se tiver paginação? Como fazer a paginação? "
Tem varias abordagens nesse sentido . se voce usa hibernate por exemplo ao mandar fazer merge nas coleções ele ja deleta pra voce no banco se voce utiliza deleteOrphan = true no mapeamento, ou se voce preferir voce pode comparar suas listas que esta recebendo com a que esta no banco e realizar as operações voce mesmo .
Não há suporte ainda a paginação para a tabela detalhe , seria algo a implementar ainda e seria apenas visual para ficar mais agradavel ao usuario , mas no fim seu post seria unico com todos os objetos .

“E Atributos com relacionamento N-N, como q fica?”
Normal , abaixo um exemplo de código com mapeamento N:N usando uma view com detail .
Vamos supor que uma pessoa pode utilizar varios carros e que um carro pode ser utilizado por varias pessoas , entao espera 3 interfaces , uma para cadastra a pessoa , outra para cadastrar o carro , e uma que junta os dois certo ?

public class Pessoa {
           private Long id;
           private Long nome;
           private List<Carro> carros;
           //getters and setters
}

public class Carro {
          private Long id;
          private Long modelo;
          private List<Pessoa> pessoas;
          //getters and setters
}
<html:form action="/sua/url/que/trata/os/dados" label="N:N">
       <html:formHidden name="pessoa.id" value="${pessoa.id}"/>
      <html:formRow label="Pessoa">
             ${pessoa.nome}
      </html:formRow>
      <html:detailTable  label="Exemplo N:N com carros" list="${pessoa.carros}" var="carros">
        <html:detailTableColumn label="Carro que utiliza" mandatory="true">
            <html:select name="pessoa.carros[].id" list="${carroList}" var="carro" value="${carros.id}">
                      <html:option value="${carro.id}">${carro.modelo}</html:option>
            </html:select>
        </html:detailTableColumn>
    </html:detailTable>
</html:form>

Legal o merge :wink:

seria bom vcs implementarem a detailed com paginação né? :smiley:
só uma dica…

muito legal
parabens a vc e sua empresa.

[quote=d34d_d3v1l]No Grid pq tem:

<html:grid id="pessoas" label="Listagem de pessoas"   
    totalResults="${fn:length(pessoaList)}" var="pessoa" list="${ pessoaList }"  
        url="/grid/index"  print="true">  

o atributo “totalResults”? pq ele nao pega esse dado na propria lista, dentro do componente?[/quote]

É que no caso desse exemplo é para paginacao sob demanda , mas na pratica ${pessoaList} vai vir apenas parte dos dados que veio do seu banco , entao por isso o componente espera o total de linhas que a grid pode ter para saber paginar , entendeu ?

Em resumo vamos supor que voce tem 1000 registros e quer paginar de 200 em 200

Voce tem de utilizar duas queries : uma que faz contagem total dos registros (1000) que vai no totalResults e outra apenas com parte dos dados que vai no list conforme vai requisitando e processando no servidor . Entao na pratica

Quando abrir a grid eu entendo que se o atributo do request page = null e resultsPerPage = null ta começando do zero a paginação entao se meu padrao é de 200 registros por pagina offset começa em 0 com limite de 200 no meu banco se o usuario clica no botao pra avancar pagina a url enviada ja vai com parametros

http://grid/index?page=2&resultsPerPage=200 entao com esse dados que agora nao veio mais null voce sabe que o cara ta pedindo a pagina 2 que seria offset 200*(page-1) com limite de 200

No mais se nao precisa de paginacao e todos os dados ja serao exibidos é so colocar paginate=“false” , e nem precisa definir esse atributo totalResults .

[quote=d34d_d3v1l]Legal o merge :wink:

seria bom vcs implementarem a detailed com paginação né? :smiley:
só uma dica…

muito legal
parabens a vc e sua empresa.
[/quote]

Anotado para o próximo release

Boa caraaa!!
Abraços!

[quote=boneazul][quote=Ataxexe][quote=boneazul]“O código de exemplo na demo do detail table não me pareceu ser o que aparece na demo. Se for, ficou com um aspecto de muita mágica num componente visual”
R:. É assim mesmo facil do jeito que está , Rich Internet Application , assim como todos os outros componentes , nem tem muita magica esse componente , é o objeto que trata listas em formulários, ou seja , o famoso “nomedocampo[]” , em que muita gente , principalmente iniciante quebra a cabeça pra resolver .

Essa é outra vantagem de se usar uma abstração para fazer algo , não precisa se ater a detalhes de como funciona ou como faz , assim como eu acho magica o que hibernate,vraptor,engine de jogos ou qualquer outro framework ótimos realizam . São algumas perguntas simples que devem ser feitas antes de adotar : É facil de usar ? Tem boa documentação ? Roda bem não importando o ambiente ? Se as respostas são sim , não me agrega no momento saber como funciona , pois outra pessoa ja quebrou a cabeça por mim de como fazer , só sei que roda bem , escala e atende bem o que preciso. O mesmo princípio vale pra tudo qualquer outra ferramente , seja software ou não , saber como o telefone funciona por dentro e como faz a magica , ou como o microondas esquenta e como faz a magica não é interessante , voce sabe que disca e consegue falar e ouvir outra pessoa do outro lado da linha , ou que voce coloca o tempo e a comida esquenta.

[/quote]

Me referia aos botões de remover e submeter o formulário. Acho completamente estranho não ter referência alguma de onde ele vai executar as coisas.[/quote]

Bom acho que não entendi direito seu questionamento nessa parte , mas vamos lá. Abaixo segue o fonte que voce viu :

    <html:form action="/sua/url/que/trata/os/dados" label="Tabela detalhe">  
        <html:detailTable  id="pessoas" label="Pessoas listadas" list="${pessoaList}"   
     var="pessoa">  
            <html:detailTableColumn label="Nome da pessoa">  
                <html:input help="oi" name="pessoas[].nome" size="20" value="${pessoa.nome}"/>  
            </html:detailTableColumn>  
            <html:detailTableColumn label="Data de nascimento" mandatory="true">  
                <html:input name="pessoas[].dataNascimento" mask="99/99/9999" value="${pessoa.dataNascimento}"/>  
            </html:detailTableColumn>  
            <html:detailTableColumn label="Salário" mandatory="true">  
                <html:input name="pessoas[].salario" moneyMask="true" value="1000" size="6"/>  
            </html:detailTableColumn>  
            <html:detailTableColumn label="Gosta de chocolate" mandatory="true">  
                <html:input type="checkbox" name="pessoas[].gostaChocolate" value="S"   
     checked="${pessoa.gostaChocolate}"/>  
            </html:detailTableColumn>  
            <html:detailTableHidden name="pessoas[].id" value="${pessoa.id}"></html:detailTableHidden>  
        </html:detailTable>  
    </html:form>  

Na primeira linha action="/sua/url/que/trata/os/dados":

<html:form action="/sua/url/que/trata/os/dados"...

voce fala que url trata os dados depois da submissao , no mais é tudo em tempo de pagina , e nao ha dados trafegando , é tudo javascript , simples .

Entao no seu vraptor,spring,servlet,struts ou sei la o que voce vai ter disponivel depois da submissao no request os campos com os names em forma de lista que voce mesmo definiu, isso é padrao , serve pra php , jsp , etc ,

Entao pro exemplo acima vamos supor que voce preencha 3 linhas da tabela detalhe , na sua url ou metodo que trata os dados voce vai ter disponivel no request.

pessoas[0].nome = dadolinha1
pessoas[0].dataNascimento = dadolinha1
pessoas[0].salario = dadolinha1
pessoas[0].gostaChocolate = dadolinha1

pessoas[1].nome = dadolinha2
pessoas[1].dataNascimento = dadolinha2
pessoas[1].salario = dadolinha2
pessoas[1].gostaChocolate = dadolinha2

pessoas[2].nome = dadolinha3
pessoas[2].dataNascimento = dadolinha3
pessoas[2].salario = dadolinha3
pessoas[2].gostaChocolate = dadolinha3

esse indice o proprio objeto que preenche pra voce na sequencia entao ja chega pronto pra voce utilizar, vou adicionar na documentação um exemplo tambem do código java que recebe os dados em cada framework para melhorar o entendimento do objeto e como os dados chegam , talvez seja isso sua dúvida e ja sana a duvida de outros também.

ja aproveitando o gancho se fosse vraptor por exemplo e sua convencao voce faria :

 @Resource
 public class PessoaController{
     
      //Voce definiu na action de seu form
     @Path("/sua/url/que/trata/os/dados")
     public void trataLista(List><Pessoa> /*Voce definiu no name do objeto*/pessoas){
            for(Pessoa pessoa:pessoas){
                   System.out.println(pessoa.getNome());
            }
     }
}

Simples assim.

[/quote]

Não era bem isso que eu estava me referindo…bom…deixa pra lá…

Sucesso com sua taglib :thumbup:

Achei bem legal., parabens

Podria ter um plugin para o Grails neh ?

[quote=boneazul]Olá a todos ,

Pra quem desenvolve em java web gostaria de lhes apresentar o mais novo produto de minha empresa , que vem a ajudar a resolver um problema muito comum na camada view quando se trata de frameworks action based (struts,spring,vraptor,mentawai,etc) que é encontrar algo pronto e de qualidade .

O que é TagriaLib ?

 Tagria Lib (TagLib Rich Internet Application) é uma poderosa biblioteca visual escrita especificamente para rodar em JAVA no ambiente WEB ,

[/quote]

Vc esqueceu de referir que não é free e tem uma licença horrivel

A ideia é boa, é de fato ncessário ter um ferramental como este, mas não podemos cair num novo displaytag da vida.
Por exemplo, como eu modifico a renderização ? tem templating ? Não me refiro às cores, me refiro a onde-vai-o-quê.
Internacionalização. Diz que suporta. Como ? todos os exemplos são hardcoded.

Sem ser free não vai se popularizar o suficiente para justificar o custo de treinar as pessoas nisso, e ainda significa vendor-lock in.

Por outro lado, a atitude de responder às criticas é extremamente defensiva. Se vc vende um produto, vc tem que entender o que está sendo dito antes de responder.
Vc citou que o form é gerado com table porque tem que ser compativel com browsers antigos. Antigos é uma coisa , antiquados é outra. A solução é deixar o cara criar a sua propria renderização. Quem sabe fazer fará tableless. Primeira regra de frameworks : não atrapalhe o que o cara quer fazer.

A ideia é boa. Poderiam ganhar mais fazendo-a open source e free. Sem isso, vcs tão na roça.

Pow cara… eu já estava aqui “todo” pra usar a sua solução, quando esbarrei na licença.

Sei que deu trabalho pacas e que ganhar grana com isso tem mesmo que ser o foco. Mas pensa em uma outra estratégia como liberar a tag e cobrar suporte.

Enfim, pense bem em sua estratégia financeira, pois o que o Sérgio falou, será realmente um empecilho ao futuro de seu projeto.

No mais, parabéns pela iniciativa.

Abs []

Bem legal seu trabalho!
vc tá fazendo tudo sozinho?
Sucesso!

[quote=adriano_si]Pow cara… eu já estava aqui “todo” pra usar a sua solução, quando esbarrei na licença.

Sei que deu trabalho pacas e que ganhar grana com isso tem mesmo que ser o foco. Mas pensa em uma outra estratégia como liberar a tag e cobrar suporte.

Enfim, pense bem em sua estratégia financeira, pois o que o Sérgio falou, será realmente um empecilho ao futuro de seu projeto.

No mais, parabéns pela iniciativa.

Abs [][/quote]

são dois pq eu ja estava ate pensando quando vi a licença.