quarta-feira, 18 de dezembro de 2013

Evitar duplo submit com jQuery

No trabalho hoje me deparei com a necessidade de impedir que se façam múltiplos submits em uma página Web.

Na empresa onde trabalho não usamos asp.net MVC ou Web Forms, mas sim um framework próprio da empresa, feito sobre asp.net, que lembra muito o asp clássico.

Independente do ambiente ou framework, de ser em php, .net etc, se não houver um recurso nativo para evitar isso então você deve se preocupar: lentidão para enviar a página e o usuário com "dedinho nervoso" clicando em enviar mil vezes por segundo, levando a múltiplos posts (submits) e a inserir mútiplos dados idênticos no seu banco de dados.

Além do trabalho server-side, de validação, prevenção de duplicidades na camada de persistência, redirect para uma página de sucesso etc, deve haver alguma coisa client-side para prevenir o submit duplo.

Com javascript é possível desabilitar o botão no momento do click, e evitar que ele seja pressionado novamente.
Se for um Button do tipo AspButton (System.Web.UI.WebControls.Button), da paleta Web do Visual Studio, num ambiente Web Forms, talvez você deseje adicionar o script como um atributo do botão, no evento load da página.

Com jQuery fica muito fácil, e funciona de uma vez para todas as forms e botões de uma página.

De todos os scripts que eu fucei o desse site http://thepugautomatic.com/2008/07/jquery-double-submission/ me pareceu o melhor. Ele praticamente cria uma função nova no jQuery, que você pode reusar em todas as páginas com uma linha de código.



//isso você coloca em um arquivo js externo, a ser chamado depois do jquery, ou na tag script de uma página
            jQuery.fn.preventDoubleSubmit = function() {
              jQuery(this).submit(function() {
                if (this.beenSubmitted)
                  return false;
                else
                  this.beenSubmitted = true;
              });
            };

//isso você coloca dentro do $(document).ready
    $(document).ready(function() 
    { 
      jQuery('form').preventDoubleSubmit(); 
    }


E está pronto: só de incluir essa pequena linha já resolve todos os problemas de dedo nervoso nas suas páginas.

Tentei também outros scripts, e o script abaixo também funcionou muito bem, embora peque quanto à elegância e ao reaproveitamento de código:

//esse embora diferente, faz a mesma coisa que o script acima: atua na interceptação do submit da form, mas desabilita os botões logo após o submit
$('form').submit(function() {
                if(typeof jQuery.data(this, "disabledOnSubmit") == 'undefined') {
                    jQuery.data(this, "disabledOnSubmit", { submited: true });
                    $('input[type=submit], input[type=button]', this).each(function() {
                        $(this).attr("disabled", "disabled");
                  });
                  //$('input[type=submit], input[type=button]', this).attr("disabled", "disabled");
                  return true;
            }
            else
            {
                return false;
            }
});

Esse terceiro script não funcionou muito bem, não sei explicar porque, mas ele deveria atuar no evento click, sumindo com o botão (ou desabilidando-o) logo o clique aconteça.

//esse atua de forma diferente: tenta interceptar o click
            $('input[type=submit], input[type=button]').live('click', function(){
               
                if(!$(this).prop("disabled"))
                {
                    $('input[type=submit], input[type=button]', this).each(function() {
                        $(this).attr("disabled", "disabled");
                    });
                    
                    //$('input[type=submit], input[type=button]', this).attr("disabled", "disabled");

                    return true;
                }
                else
                {
                    return false;
                }
            });

Uma coisa que  o primeiro script não faz é desabilitar ou esconder os botões, mas basta adicionar a linha $('input[type=submit], input[type=button]', this).attr("disabled", "disabled") para fazer isso. Detalhe que em ambos os scripts eu deixei essa linha comentada. É que as linhas acima já fazem isso varrendo todos os resultados do seletor com um .each(), onde eu posso aproveitar para colocar mais comportamento nesse código.

No seletor, estou passando  thi como contexto, como visto na linha acima. Não sei porque, se omitir isso, não conseguimos fazer sequer uma submissão.

Fique atento, no jQuery, à diferença entre .prop e .attr, explicarei isso num próximo post.

sábado, 7 de dezembro de 2013

Como usar a mesma dll em uma aplicação windows forms e web forms

Recentemente me deparei com a seguinte situação em uma aplicação legada: tinha uma dll com as classes de negócio / aplicação, mas essas dlls faziam, de vez em quando, uso do namespace system.web. 

Meu desafio era utilizar estas classes em uma versão windows forms da aplicação, mas isso era impossível, uma vez que com a presença do namespace system.web a aplicação não compilava, e não era permitido a adição da minha dll. 

Você pode estar pensando, e eu também pensei, que o problema se resolveria facilmente adicionando uma referência à dll system.web.dll, mas se fosse só isso o problema estaria resolvido.

O que realmente me causou esse problema era o fato de que quando você cria novas aplicações windows forms ou console, por padrão o visual studio 2010 usa a versão "client profile" do .net framework, uma versão mais magra que não tem toda aquela parafernalha server. No entanto, minha aplicação fazia muito uso de HttpContext.Current.Session.Add, dentro de system.web.dll, que é justamente uma parafernalha server. 
Consegui resolver esse prodblema trocando o framework para o framework "comum", com isso pude adicionar minha dll e a aplicação até compilava, o que não quer dizer que funcionava. 

Vá em project --> properties e na aba application, mude o target  framework de .net framework 4 client profile para .net framework 4, simplesmente.

Vá em project --> properties e na aba application, veja o target framework

Mude o target framework para .net framework 4


Corrigi o problema na aplicação legada separando em classes que implementam uma mesma interface as partes que usam e que não usam HttpContext, e usei o framework de injeção de dependência/ IoC Unity para instanciar a classe correta dependendo da aplicação ser web ou windows. Mas também dá para resolver sem isso, usando a dll legada mesmo.

Fiz 4 exemplos de minhas possíveis soluções usando workarounds:
Usando portable class library
Usando o class library comum
Usando diretivas de compilação (preprocessor directives)
meu preferido: usando reflection

para ver o meu post no msdn americano

segunda-feira, 2 de dezembro de 2013

Manter a imagem de background fixa

No css, para manter fixa a imagem de background enquanto o texto rola por cima você deve usar o código:

body {background-image: url('fundo.jpg'); background-repeat: no-repeat; background-attachment: fixed }

Caso deseje que a imagem role junto, use:

body {background-image: url('fundo.jpg'); background-repeat: no-repeat; background-attachment: scroll }

Veja o teste abaixo, coloquei o texto em amarelo para que pudesse ser melhor visualizado sobre a imagem:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vel consequat ligula, et facilisis lacus. Morbi quis auctor ante. Curabitur eros diam, faucibus ut fermentum a, euismod a libero. Duis sed faucibus est. Donec vel dui a dolor luctus luctus. Duis felis turpis, porta vitae nisi et, consequat consequat mi. Praesent enim enim, adipiscing vel dignissim id, adipiscing in neque. Suspendisse vitae lorem elit. Sed quis felis tempor, ornare ipsum id, suscipit justo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.

Morbi vitae luctus sapien, tincidunt porttitor tellus. Donec in fringilla dolor. Aliquam ut vulputate dui, id porta dolor. Nunc volutpat eleifend ornare. Integer metus orci, tristique vitae tellus non, euismod ornare orci. Donec dolor est, porta non vulputate nec, semper eget ligula. Duis non mi venenatis, malesuada lectus ut, faucibus massa. In hac habitasse platea dictumst. Integer lacinia auctor suscipit. Nam feugiat quam dui, gravida luctus neque porttitor sit amet. Donec malesuada ullamcorper velit et ultrices. Cras ultricies mollis vehicula.

Etiam a fringilla ante. Pellentesque non varius lectus. In interdum purus est, eget lobortis diam ornare ut. Praesent eget cursus ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec non purus porta, posuere elit a, convallis justo. Mauris non euismod risus. Nam sem dolor, tincidunt at mi eu, iaculis eleifend risus.

Fusce a bibendum eros. Suspendisse laoreet erat nec neque tristique, vitae viverra nibh imperdiet. Quisque porta mauris quis est porta tincidunt. Sed elementum leo tortor, ut dignissim nisi placerat ac. Aenean accumsan neque non sem tincidunt, ut aliquam enim tempus. Suspendisse sagittis fringilla elit in rhoncus. Aenean id risus justo. Nunc sit amet libero quam. Aenean facilisis metus nec tellus accumsan, in posuere velit egestas. Integer et mauris dignissim, sagittis nisi at, malesuada libero.

Donec at nunc risus. Nullam bibendum elementum interdum. Integer vulputate id nisi sit amet consectetur. Etiam vel lorem quis neque rutrum mollis. Aliquam a justo feugiat, imperdiet ipsum in, viverra est. Sed at aliquam sapien, in fermentum leo. Aenean ornare blandit urna. Suspendisse id nibh tristique, adipiscing libero eget, cursus nibh. Aenean quis diam in diam varius auctor. Nam ac augue quis enim convallis rhoncus vitae ac odio. Nam porta congue quam.

Nullam viverra mi nec fringilla tristique. Nunc et arcu vitae ante vehicula fringilla. Etiam sed leo vehicula, vulputate sem ut, viverra eros. In at aliquet enim. Mauris quis eros non sem mollis pharetra. Ut eu est quis velit eleifend consequat. Duis non hendrerit erat, eu fermentum metus. Morbi imperdiet mollis sollicitudin. Duis vel consequat turpis. Curabitur semper vel risus nec mollis. Quisque quis mi enim.

Pellentesque ultrices sit amet libero posuere posuere. Sed ullamcorper dolor id velit rutrum, ac pharetra lorem rhoncus. Ut vitae scelerisque dolor. Phasellus sit amet tincidunt diam. Nulla porttitor sem non libero pulvinar, eu adipiscing magna blandit. Sed pharetra placerat vehicula. Nullam suscipit felis ut leo suscipit condimentum. Mauris metus nibh, consectetur id iaculis ac, blandit vitae velit. In vel viverra dui. Suspendisse placerat massa eu nisi porta tempor. Vivamus suscipit eros eu tempus ultricies.

Integer vehicula nisl in metus porta viverra. Sed vulputate sodales ligula nec egestas. Sed at elementum dolor. Proin turpis odio, mollis ac bibendum sit amet, pulvinar in tortor. Praesent semper semper nisi, et tempor risus dapibus eget. Mauris placerat rhoncus metus, eu egestas lectus gravida ac. Suspendisse fermentum rutrum dictum. Nulla interdum mauris ac metus adipiscing, sed porttitor nisi aliquam. Pellentesque tempus, eros sit amet tempus laoreet, risus mauris laoreet mi, nec placerat risus quam sed dolor. Aenean pharetra tortor nec laoreet adipiscing. Aenean at tristique velit, vitae porttitor lacus. Curabitur laoreet tortor ac mauris vehicula, a vestibulum lacus vulputate. Aenean porttitor lobortis aliquet. In erat mi, adipiscing et tincidunt eu, venenatis sit amet justo. Nunc rutrum dapibus vehicula.

Quisque a sapien vel metus placerat laoreet. Morbi consectetur magna quam, et mollis nisl sodales ut. Maecenas nulla erat, viverra id erat et, auctor ultrices orci. Curabitur quis metus eros. Vivamus porttitor arcu ut placerat rutrum. Maecenas odio libero, pulvinar et varius ac, vulputate at urna. Integer volutpat, justo commodo luctus consequat, erat dolor volutpat dolor, nec vehicula nisl erat ut nisl. Vivamus auctor purus id enim interdum interdum ac non est. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

Nulla facilisi. Quisque pellentesque, leo eu luctus vehicula, leo quam mollis odio, sit amet varius nunc mi vitae tellus. Pellentesque vehicula luctus purus. Morbi sodales pellentesque mauris ut scelerisque. Aliquam fringilla tellus in justo accumsan egestas. Integer fringilla gravida tortor id viverra. Nam varius justo sed dignissim congue. Nulla et ornare purus. Fusce leo purus, porta fermentum egestas vitae, faucibus quis urna. Mauris enim ipsum, volutpat volutpat metus quis, sagittis vulputate ipsum. Suspendisse vulputate vel metus id mattis.

Phasellus risus velit, tempus ut pulvinar at, ultricies ac lacus. Duis elementum metus eu risus bibendum luctus. Mauris aliquet pretium nisl, id vehicula nibh feugiat non. Sed tristique turpis sit amet arcu molestie, eget rhoncus justo molestie. Morbi a orci quis erat fermentum tempor. Donec sed velit cursus, interdum nibh quis, feugiat enim. Quisque sed turpis vel odio vehicula commodo. Suspendisse congue eu risus sed tristique. Etiam ac mauris ut dolor tempus pretium. Pellentesque fermentum quam est, a mollis sem commodo ac. Duis id enim ac tortor iaculis varius. Cras feugiat, leo ac tempor sollicitudin, est libero ornare magna, vel venenatis magna turpis auctor odio. Proin turpis neque, posuere ut sodales aliquam, eleifend id ligula. Quisque mauris nulla, ultricies in mollis at, pharetra vel ligula.

Vestibulum ac felis et eros viverra congue. Duis varius lacinia magna sed tincidunt. Phasellus quis lectus eu diam mollis vulputate. Vivamus faucibus lectus vel nisi fermentum, ac cursus eros rutrum. Curabitur tellus eros, viverra nec nisl nec, aliquam vulputate urna. Nulla ultrices molestie magna ut dignissim. Pellentesque turpis eros, commodo sed convallis et, placerat eu urna. Sed posuere diam ut felis pharetra, at pharetra velit euismod. Vestibulum commodo neque justo, eleifend pharetra lorem lobortis at.

Duis convallis sem felis, vehicula sodales purus dignissim id. Cras sit amet placerat massa. Donec vestibulum vulputate sapien, vel iaculis arcu volutpat suscipit. Nam rhoncus ipsum vel nisl convallis tempus. Mauris rutrum nisl a enim aliquam tincidunt a nec sapien. Vivamus pharetra dui in felis posuere tempor. Mauris at mi non velit mattis tempor. Curabitur tincidunt lorem eros, id mattis augue venenatis id. Pellentesque in tempor turpis, vel posuere purus. Integer ullamcorper congue lorem, vitae imperdiet purus aliquet non. Vestibulum nec velit pellentesque odio interdum semper. Donec ac commodo augue, sit amet mollis elit.

Donec sit amet semper lorem. Nunc ac sem eu mi rutrum viverra ut eget magna. Curabitur tristique mollis mi, consectetur tincidunt orci consequat vitae. Aliquam in sem malesuada leo ornare commodo. Curabitur nec velit vitae ante tempor tincidunt a ac massa. Sed leo urna, pulvinar blandit leo sed, lobortis viverra turpis. Phasellus sagittis gravida ornare. Aenean at venenatis nibh. Donec mattis leo erat, in tincidunt dolor sollicitudin non. Curabitur suscipit vitae libero id ornare.

Proin elementum, metus ac tincidunt consequat, dui turpis vehicula nunc, et eleifend nulla metus sit amet nisl. Curabitur sem odio, mollis sit amet consectetur sit amet, faucibus vitae arcu. In eget imperdiet nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eu metus massa. Sed vulputate aliquam tellus, vel placerat massa porttitor vitae. Nam ultricies quis nibh vitae bibendum. Nullam tempor sed nisi a interdum. Aenean consectetur ornare dolor gravida tincidunt. Sed vel dignissim velit. Vivamus leo mauris, faucibus vulputate adipiscing et, laoreet quis risus. Nunc ullamcorper pulvinar est eleifend suscipit. Nullam varius interdum metus nec faucibus. Aliquam sed fringilla sapien, at rhoncus massa.

Curabitur eget velit ligula. Vivamus turpis erat, iaculis eget pulvinar et, rutrum ut diam. Mauris nulla magna, congue nec consequat eu, faucibus nec nisi. Cras in lacinia quam. Sed ut dolor vel risus sollicitudin iaculis. Vivamus porttitor in lacus vitae commodo. Nulla a risus eget nunc posuere egestas convallis in urna. Ut eget laoreet turpis. Fusce sagittis, urna quis tempor condimentum, magna turpis rutrum leo, vitae blandit mauris nulla ac leo. Cras tincidunt metus consequat, dictum nibh laoreet, feugiat nunc. Cras non imperdiet metus. Nunc facilisis lacus sit amet augue ultricies, id rhoncus tortor hendrerit. Integer gravida ut lorem quis luctus. Phasellus dapibus nunc tristique aliquet sodales. Fusce scelerisque tellus justo. Donec ultrices velit vel pellentesque blandit.

Nulla mattis nibh at metus sollicitudin, eu volutpat felis fringilla. Maecenas adipiscing feugiat molestie. Ut lobortis gravida tortor ac sagittis. Cras sed leo in orci ullamcorper convallis vitae ac massa. Donec suscipit egestas magna in consequat. Nam a sagittis mi. Donec in ultricies lacus.

Integer mattis tellus tellus, a mattis quam hendrerit sed. Vestibulum in lorem dui. Curabitur viverra, turpis ac iaculis pulvinar, diam neque sollicitudin nisl, condimentum mollis ligula odio et sapien. Cras id diam eget metus interdum consectetur eget id turpis. Suspendisse et turpis eu libero luctus iaculis. Maecenas id tempus nisl, quis vehicula lorem. Donec fermentum nisl a ante pretium faucibus.

Nunc ac turpis a nulla dignissim imperdiet quis sit amet eros. Nam lobortis risus vel urna pharetra egestas. Suspendisse aliquam vestibulum ullamcorper. Nam elementum mollis elit id luctus. Proin fringilla lorem id eleifend ultricies. Maecenas odio ipsum, congue eu egestas nec, tincidunt et ante. Fusce vel tincidunt turpis. Aenean facilisis felis a iaculis tempor. Nulla eu dui ut ipsum porta pulvinar. Morbi velit sem, ultricies quis sollicitudin malesuada, ullamcorper ut elit. Curabitur at nunc non ligula vehicula posuere sit amet nec augue. Donec ac fermentum purus, id molestie orci. Ut et suscipit tortor. Curabitur nec bibendum magna.

Sed tincidunt justo sed dolor vehicula pulvinar. Suspendisse potenti. Pellentesque vel ligula orci. Donec tincidunt, eros quis hendrerit elementum, turpis urna elementum magna, sit amet eleifend risus lacus quis metus. Nullam sit amet vestibulum dui. In hac habitasse platea dictumst. Maecenas vitae neque tellus. Aenean ante eros, tempus eu arcu ac, suscipit condimentum leo. Nunc quis dapibus libero. Sed justo mi, dapibus euismod justo vel, congue tincidunt eros.

Listar todas as culturas do .net e a configuração corrente

Lidar com culture sempre é um problema, e a conversão de datas e números para strings e vice-versa é pior ainda se o seu sistema permite que usuários de múltiplas culturas imputem a informação da maneira a que estão habituados, ou se você tem dados sensíveis à cultura gravados em campos verchar do banco de dados.
 É importante que as formatações de dados sejam aplicadas à cultura apenas na exibição do dado, mas nunca no seu processamento e armazenamento. Ao gravar no banco de dados, grave sempre o dado bruto em seu formato e tipo de dado padrão (double, integer, datetime etc) usando para isso parâmetros tipados ou o Entity Framework, ou ainda o nHibernate.
 Quando necessário armazenar, por exemplo, uma data como string, então opte por um formato reconhecido internacionalmente, como o padrão ODBC: yyyy-MM-dd (2013-12-02).
Abaixo um programinha console que lista todas as Cultures disponíveis e mostra qual é a corrente configurada no .net.

using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;

namespace CultureList
{
    class Program
    {
        static void Main(string[] args)
        {

            // get culture names
            List list = new List();
            foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.AllCultures))
            {
                string specName = "(none)";
                try { 
                    specName = CultureInfo.CreateSpecificCulture(ci.Name).Name;
                    list.Add(String.Format("{0,-12}\t{1,-12}\t{2,-40}\t{3}\t{4}\t{5}\t{6}", 
                        ci.Name, 
                        specName, 
                        ci.EnglishName, 
                        ci.NumberFormat.NumberGroupSeparator,
                        ci.NumberFormat.NumberDecimalSeparator, 
                        ci.NumberFormat.CurrencyGroupSeparator, 
                        ci.NumberFormat.CurrencyDecimalSeparator));
                }
                catch { }

                
            }

            list.Sort();  // sort by name

            // write to console
            Console.WriteLine("CULTURE\tSPEC.CULTURE\tENGLISH NAME\tN-GROUP\tN-DECIMAL\tM-GROUP\tM-DECIMAL");
            Console.WriteLine("--------------------------------------------------------------");
            foreach (string str in list)
                Console.WriteLine(str);

   Console.WriteLine("");  
   Console.WriteLine("");    
            Console.WriteLine("Informações de cultura corrente:");
            Console.WriteLine("--------------------------------------------------------------");    
            Console.WriteLine("System.Globalization.CultureInfo.CurrentCulture -->" + System.Globalization.CultureInfo.CurrentCulture);
            Console.WriteLine("System.Globalization.CultureInfo.CurrentUICulture -->" + System.Globalization.CultureInfo.CurrentUICulture);
            Console.WriteLine("System.Globalization.CultureInfo.InstalledUICulture -->" + System.Globalization.CultureInfo.InstalledUICulture);

            Console.ReadLine();

        }
    }
}

Código disponível aqui

Postagens populares

Marcadores

delphi (60) C# (31) poo (21) Lazarus (19) Site aos Pedaços (15) sql (13) Reflexões (10) .Net (9) Humor (9) javascript (9) ASp.Net (8) api (8) Básico (6) Programação (6) ms sql server (5) Web (4) banco de dados (4) HTML (3) PHP (3) Python (3) design patterns (3) jQuery (3) livros (3) metaprogramação (3) Ajax (2) Debug (2) Dicas Básicas Windows (2) Pascal (2) games (2) linguagem (2) música (2) singleton (2) tecnologia (2) Anime (1) Api do Windows (1) Assembly (1) Eventos (1) Experts (1) GNU (1) Inglês (1) JSON (1) SO (1) datas (1) developers (1) dicas (1) easter egg (1) firebird (1) interfaces (1) introspecção (1) memo (1) oracle (1) reflexão (1)