Expressão regular com javascript

Expressão regular é um conjunto de padrões que facilita muito o desenvolvimento de determinados sistemas. É um recurso que pouquíssimo explorado pelo que percebo, que muitas pessoas "tem medo" de estudar pela impressão de complexidade que uma expressão regular parece ter, por ser um "conjunto de caracteres sem sentido", como já vi definirem.

Para quem nunca viu, pode até parecer isso mesmo, por exemplo  (w[w|-]*)(.) ou ([a-Z]).

Escrevo para tentar acabar com esse preconceito sobre a complexibilidade das expressões regulares, neste caso especificamente do seu uso no Javascript.

Você não vai ver muito código neste post. Quando me interessei pelo assunto ganhei da Bia o livro Expressões Regulares – uma abordagem divertida e comecei a aplicar ER quando era necessário. Recomendo o livro pois ele é bastante útil como consulta (e ER realmente precisa de consultas recorrentes).

Para que serve uma Expressão Regular

Expressão Regular ou Regular Expression serve para identificar um determinado padrão de caracteres em um texto.

Exemplo de uso: você tem um documento de 500 páginas e quer encontrar preços em reais neste documento. Você cria uma expressão regular que vai encontar o seguinte: "R$ Y,XX"  onde Y pode ser qualquer número (positivo, negativo, com 1 ou infinitas dezenas) e X é uma número de 0 a 9. Simples assim, ao final deste post espero que você esteja apto a "pensar" expressões regulares!

 

Expressões Regulares no javascript

Bem, agora você sabe para que serve, agora vou apresentar as "regras" e significados de cada caracter dentro de uma expressão regular. Você não vai decorar ou aprender tudo, mas sabendo o que é possível e consultando as tabelas abaixo você poderá desenvolver muita coisa e economizar muitas linhas de código.

 

As tabelas abaixo foram traduzidas por Thiago Prado para o iMaster, e ajudam a entender um pouco melhor o significado de cada caracter em uma Expressão Regular.

 

Busca posicionada

Símbolo

Descrição

Exemplo

^

Busca somente no início da string

/^The/ encontra "The" em "The night" mas não em "In The Night"

$

Busca somente no fim da string

/and$/ encontra "and" em "Land" mas não em "landing"



Encontra em qualquer parte da string

/ly/ encontra "ly" em "This is really cool."

B

Encontra qualquer parte que não esteja limitada

/Bor/ encontra “or” em "normal" mas não em "origami."

Literais

Símbolo

Descrição

Alfanumerica

Todos os caracteres alfabéticos e numerais se encontram literalmente. Então /2 dias/ encontrarão "2 days" dentro da string

 

Encontra o caractere de nova linha

f

Encontra o caractere de nova página

 

Encontra o caractere de retorno de carro

 

Encontra o caractere de tabulação horizontal

v

Encontra o caractere de tabulação vertical

xxx

Encontra o caractere ASCII expresso por um número octal xxx.
"50" encontra o caractere parênteses esquerdo "("

xdd

Encontra o caractere ASCII expresso por um número hexadecimal dd.
"x28" encontra o caractere parênteses esquerdo "("

uxxxx

Encontra o caractere ASCII expresso por UNICODE xxxx.
"u00A3" encontra "£".

 

 

Classes de Caracteres

Símbolo

Descrição

Exemplo

[xyz]

Encontra qualquer caractere que estiver dentro do grupo. Você pode usar hífen para denotar escala. Por Exemplo. /[a-z]/ encontra qualquer letra do alfabeto alphabet, /[0-9]/ encontra qualquer dígito

/[AN]BC/ encontra "ABC" e "NBC" mas nao “BBC" desde que a letra “B” nao estao nogrupo.

[^xyz]

Encontra qualquer caractere que não estiver dentro do grupo. O circunflexo indica que nenhuma caractere deve estar na string.
NOTA: O circunflexo usado dentro da classe de caractere é diferente do que denota o início da string, não se confundam. A negação aqui só é permitida dentro dos sinais

/[^AN]BC/ encontra "BBC" mas nao "ABC" ou "NBC".

.

(Ponto). Encontra qualquer caractere exceto o caractere de nova linha ou terminador de linha Unicode

/b.t/ encontra "bat", "bit", "bet" e assim por diante

w

Enconta qualquer caractere alfanumérico incluindo underscore. Equivalente a [a-zA-Z0-9_]

/w/ encontra "200" em "200%"

W

Encontra qualquer caractere que não se encontra na classe dos alfanuméricos. Equivalente a [^a-zA-Z0-9_]

/W/ encontra "%" em "200%"

d

Encontra qualquer dígito. Equivalente a [0-9]

 

D

Encontra qualquer caractere que não seja um digito. Equivalente a [^0-9]

/D/ matches "No" in "No 342222"

s

Encontra qualquer caractere que equivale a um espaço. Equivalente a [ vf]

 

S

Encontra qualquer caractere que não equivale a um espaço. Equivalent to [^ vf]

 

Repetição

Símbolo

Descrição

Exemplo

{x}

Encontra exatamente x ocorrências na regular expression

/d{5}/ encontra 5 digitos

{x,}

Encontra x ou mais ocorrências na regular expression

/s{2,}/ encontra no minimo 2 caracteres de espaço em branco

{x,y}

Encontra x para y numero de ocorrências na regular expression

/d{2,4}/ encontra no minimo 2 mas nao mais que 4 digitos

?

Encontra zero ou nenhuma ocorrência. Equivalente a {0,1}

/as?b/ encontra "ab" ou "a b".

*

Encontra zero ou mais ocorrências. Equivalente a {0,}

/we*/ encontra "w" em "why" e "wee" em "between", mas nao em "bad"

+

Encontra uma ou mais ocorrências. Equivalente a {1,}

/fe+d/ encontra tanto em "fed" quanto em "feed"

Alternação & Agrupamento

Símbolo

Descrição

Exemplo

( )

Agrupamento de caracteres para criar uma cláusula de condição. Pode estar aninhado

/(abc)+(def)/ encontra um ou mais ocorrencias de "abc" seguido por uma ocorrencia de "def"

|

Combina cláusulas de condições dentro de uma regular expression e então encontra qualquer uma das cláusulas. Similar à expressão "OR"

/(ab)|(cd)|(ef)/ encontra "ab" ou "cd" ou "ef".

Backreferences

Símbolo

Descrição

Exemplo

( )

Encontra uma cláusula entre parênteses. n é o número de cláusulas para a esquerda da backreference

(w+)s+1 encontra quaisquer palavras que ocorra duas vezes na mesma linha, como "hubba hubba." O 1 denota que a primeria palavra depois do espaço deve encontrar a porção da string que foi encontrada no último commando dentro de parênteses. Se existisse mais de um comando dentro de parênteses, você deve usar 2 ou 3 para encontrar o apropriado agrupamento da esquerda da backreference. Até 9 backreferences podem ser usadas no padrão da string

 

Modificadores de padrão

 

Propriedade

Descrição

Exemplo

i

Ignora se é minúscula ou maiúscula

/The/i encontra "the" e "The" e "tHe"

g

Pesquisa Global para todas as ocorrências do padrão

/ain/g encontra os dois "ain" em "No pain no gain", ao inves de apenas o primeiro

gi

Pesquisa Global, e ignorar caso

/it/gi encontra todos "it" em "It is our IT department"
lastIndex

lastIndex

Armazena a posição da última pesquisa bem sucessida realizada na string. Se nada for encontrado, a propriedade lastIndex será colocada como –1

 

$n

n representa o numero de 1 a 9
Armazena os nove mais recentes pesquisa dentro de parênteses encontradas. Por exemplo, se o padrão usado por uma regular expression para a última pesquisa foi /(Hello)(s+)(world)/ e a string pesquisada foi “Hello world” o conteúdo de RegExp.$2 poderia ser qualquer caractere entro “Hello” e “world”

 

source

Armazena a copia do padrão da regular expression

 

Entendendo os métodos usados pelas expressões regulares

Método

Descrição

exec

Um método RegExp que executa pesquisas em uma string. O mesmo retorna um array das informações obtidas

test

Um método RegExp que testa uma pesquisa em uma string. O mesmo retorna true ou false

match

Um método de String que executa uma pesquisa em uma string. O mesmo retorna um array das informações obtidas ou nulo se nada for encontrado

search

Um método de String que testa uma pesquisa em uma string. O mesmo retorna o índice do resultado, ou -1 se a pesquisa falir

replace

Um método de String que executa uma pesquisa em uma string, e substitui o resultado encontrado por uma substring

split

Um método de String que usa uma regular expression ou uma string para quebrar uma string em uma array de substrings

 

 As tabelas são do iMaster (Thiado Prado) e são ótimas para referências – você não vai decorar tudo de uma vez, consultas são importantes. 🙂

 

.exec() – Testando se uma string casa com a ER

No javascript o comando .exec() testa uma string para verificar se ela casa com a sua expressão regular. Se casar, o retorno é a consulta, senão o retorno é  null.

Exemplo (da W3C):

<script type="text/javascript">

var str="Hello world!";
//look for "Hello"
var patt=/Hello/g;
var result=patt.exec(str);
document.write("Returned value: " + result);

//look for "W3Schools"
patt=/W3Schools/g;
result=patt.exec(str);
document.write("<br />Returned value: " + result);

</script>

 

Na primeira consulta teremos o retorno "Hello" printado na tela, na segunda teremos "null".

 

Finalizando, expressão regular pode parecer muito complicado quando você não sabe o que nada significa e tenta decifrar (adivinhar, né?) o significado de algo como:

(w[w|-]*)(.)*]/)

 

Gostaria de ter o costume de utilizar mais ER´s, a criação deste post foi uma forma de tentar me estimular ao uso, pois é um método bastante performático, com menos código e mais legível (depois que você compreende o funcionamento) de executar algumas funções avançadas que exigiriam infinitos alguns "loops e ifs" – a arte da gambiarra.

Em alguns posts mais pra frente vou postar alguns estudos que fiz e exemplos práticos do uso das ER´s.

Fica novamente a recomendação de um livro muito útil para consultar – Expressões Regulares, uma abordagem divertida.

Como ignorar o jQuery Validate

O jQuery validate é um plugin que facilita muito a validação de formulários, com poucas linhas você especifica exatamente o que deve ser validado, como e quais mensagens serão exibidas para cada validação.

Porém em alguns momentos ele pode ser um problema, estava fazendo uns testes e procurava uma solução para desabilitar o "Validate" de um form em uma situação específica.

No StackOverflow publicaram umas dúvidas bem parecidas com esta e aprendi uma coisa bacana com o jQuery, que é utilizar a ação direta no DOM, ignorando o javascript.

Supondo que eu tenha o seguinde formulário:

<form id="odesenvolvedor" action="action.php" method="post">
   <input name="blog" value="" class="required" type="text" />
   <input type="submit" value="Valide!" id="validateForm" />
   <input type="submit" value="Não valide!" id="skipValidateForm"  />
</form>

E na página deste form nós configuramos a seginte validação para este form, utilizando o jQuery Validate:

  <script type="text/javascript">
$(document).ready(function(){
$("#odesenvolvedor").validate();
});
</script>

O problema

Você quer que quando o usuário clicar no botão skipValidateForm o formulário seja enviado sem passar pela validação.

Isso pode acontecer devido a uma alteração nos campos do form, ou a seleção de um algum campo que torne a validação desnecessária, por exemplo.

 

Soluções

1. Submit direto pelo DOM (recomendado)

Esta foi a melhor solução que encontrei para o problema. No botão com id skipValidateForm você informa que o submit deve ser feito diretamente pelo DOM, ignorando qualquer evento relacionado ao submit.

Para fazer isto utilizando o jQuery:

$("#skipValidateForm").click(function(){    $("#odesenvolvedor")[0].submit(); });

Pronto, o evento "click" no botão vai disparar o submit do form pelo DOM – ignorando o Validate.

 

2. Remover os eventos do submit do form

Um método de dar submit no formulário e ignorar o Validate é removendo todos os eventos relacionados ao submit do form:

$("#odesenvolvedor").unbind("submit");

Qualquer submit após a linha acima não irá considerar o validate, pois o evento foi removido.

Esta não é a solução recomendada, pois uma vez removido o evento não vai mais funcionar (no outro botão, que deveria ter submit) – a não ser que novamente seja chamado o validate para o form – nada performático.

Adicionei esta segunda "solução" apenas para mostrar o funcionamento do unbind.

 

Críticas e dúvidas nos comentários! 🙂

Position absolute e conteúdo dinâmico (Ajax)

Esses dias tava com dando problema de posicionamento em um HTML no trabalho.

Uma div estava com posicionamento errado no Internet Explorer (6 e 7) e curiosamente isto só acontecia em uma das páginas, nas outras com html semelhante (e esta mesma div) o erro não acontecia.

O @tivasconcelos me alertou que aquele elemento tinha o position setado como absolute, estudando um pouco o html e js vi que o problema acontecia quando alguns elementos da página eram redimensionados devido ao carregamento de html com ajax.

O problema

No Internet Explorer o posicição quando é absoluta é calculada logo depois que a página é carregada e não é mais atualizada automaticamente.

Se algum elemento tiver as dimensões alteradas (normal quando o conteúdo é carregado dinamicamente por ajax) o elemento com posição absoluta vai ficar lá, estático.

A solução

Sabendo do que causa o problema a solução é simples: atualizar a posição do elemento.

Não é necessário calcular, basta setar novamente a posição como absoluta cada vez que as dimensões de algum elemento da página (que pode influenciar no posicionamento do elemento em questão) for alterado.

Segue o código em jQuery para a solução:

$(".posicao-absoluta").css({position:"absolute"});

 

No meu caso no success do carregamento em ajax eu adicionei esta linha, forçando o reposicionamento no IE.

Dúvidas, angústias, críticas e sugestões nos comentários. 😀

Carrinho de compras com javascript – SimpleCart

Fazia tempo que eu e a Bia planejávamos a Loja do Eu Compraria!, mas ficava apenas na idéia. Este ano começamos a nos mexer parar fazer a idéia virar projeto, e o TCC dela deu um empurrão para definição de prazo.

Um prazo curtíssimo, o desenvolvimento do back-end e a integração com front-end e PagSeguro foi feito em 4 dias (e suas devidas madrugadas) – e os bugs e funcionalidades foram sendo implementados posteriormente.

Para atender este prazo eu precisava de algumas ferramentas boas e fáceis de implementar:

  1. PagSeguro (fácil de implementar e seguro – ponto negativo é o atendimento, taxas e a impossibilidade de algumas alterações cadastrais básicas, como endereço de e-mail)
  2. SimpleCart – o motivo deste post, um carrinho de compras completo em javascript, gratuito e extremamente fácil de entender o código.

 

Feita esta introdução, vamos ao SimpleCart (trato do PagSeguro nos próximos posts sobre a ferramenta).

 

SimpleCart – Carrinho e compras em javascript

Uma ferramenta totalmente em javascript, gratuita e facilmente customizável (o código é bem fácil de entender) que permite o desenvolvimento fácil de um carrinho de compras.

Features:

  • Persistência das informações do carrinho (cookies)
  • Cálculo de frete (por item, por compra ou customizado)
  • Cálculo de taxas
  • Controle de quantidade de itens no carrinho
  • Soma do valor total (produtos, taxa e frete)

 

Configurando o SimpleCart

O primeiro passo é fazer o download do SimpleCart e adicionar o javascript necessário nas páginas que utilizarão o carrinho.

A ferramenta conta com algumas formas de check-out pré configuradas: Google Checkout, Paypal ou e-mail. Porém existe o checkout "custom", que permite que você desenvolva sua própria função para checkout.

O paypal é a função padrão (e a que vou exemplificar neste post), para isso precisamos apenas configurar nosso e-mail (o mesmo da conta no paypal) no SimpleCart.

Setando o e-mail que será usado:

<script type="text/javascript">
	simpleCart.email = "[email protected]";
</script>

 

Na variável cartHeaders você configura quais informações dos produtos serão exibidas quando este produto estiver dentro do carrinho:

simpleCart.cartHeaders = ["Name_noHeader", "Thumb_image_noHeader", "Description_noHeader", "increment_noHeader", "decrement_noHeader", "remove_noHeader", "Quantity_div_noHeader", "Price_noHeader", "Total_noHeader"];

Adicionando "_noHeader" ao final do elemento que será exibido você diz que aquele elemento não terá um "cabeçalho" no seu carrinho, no exemplo acima o carrinho não usa cabeçalho nenhum, portanto exibirá apenas as informações dos produtos adicionados ao carrinho.

Dica: os html de cada produto será montado na ordem que está confirguado por esta variável, então pense como será seu CSS para estipular a ordem correta dos elementos html do seu carrinho.

 

Html dos itens que podem ser adicionados ao carrinho

Antes de mostrar o código vamos entender o funcionamento do carrinho que você está criando. Todo o elemento (normalmente uma div) com a classe "simpleCart_shelfItem" é um produto da sua loja que pode ser adicionado ao carrinho.

Dentro dele você utiliza a classe (class) para definir o nome daquela variável do produto: preço, id, nome, descrição e qualquer outra coisa que você queira, nomeando a classe da seguinte forma: item_NomeVariavel.

Abaixo o exemplo do html de um produto, a nomenclatura das classes é auto-explicativa:

<div class="simpleCart_shelfItem">
  <h2 class="item_name">Awesome T-Shirt</h2>
  <span class="item_price">$35.95</span>
  <input class="item_quantity" value="1" type="text">
  <a href="javascript:;" class="item_add">Add to Cart</a>
</div>

Dica: você pode adicionar as classes em qualquer elemento, inclusive imagens (neste caso o valor será  o src da img). As informações dentro de alguma variável "item_var" podem ser recuperadas no seu script, use a criatividade 🙂

No local onde seu carrinho irão aparecer os produtos adicionados no carrinho você precisa do seguinte HTML:

<div class="simpleCart_items"></div>

Dentro da div acima será exibido cada produto do seu carrinho, conforme os dados informados na configuração "simpleCart.cartHeaders" e seguindo a ordem deles.

Algumas informações que podem ser exibidas, abaixo o nome da classe e a informação que ela representa:

  • simpleCart_quantity – Quantidade de itens no carrinho
  • simpleCart_total – Valor total do carrinho
  • simpleCart_finalTotal – Final total do seu carrinho
  • simpleCart_shippingCost – Valor do frete

Dica: qualquer variável do carrinho pode ser exibida usando este modelo – e você pode inserir novas variáveis caso necessite.

Pronto, com a implementação feita até aqui você consegue adicionar e remover produtos, e exibir informações de cálculo de preço e frete no seu carrinho!

 

Ações do carrinho

Agora você precisa adcionar o link para checkout, para isso também usaremos a classe:

<a href="javascript:;" class="simpleCart_checkout">Checkout</a>

E um link para limpar todos os itens do seu carrinho:

<a href="javascript:;" class="simpleCart_empty">Empty</a>

Com isso seu carrinho estará funcionando – no exemplo deste post com o checkout do Paypal (padrão).

Você pode ver o demo aqui e conferir ele funcionando com algumas implementações a mais no Eu Compraria! Shop.

Em breve eu faço mais posts exemplificando como customizar o checkout, integrar o carrinho com ferramentas de cálculo de frete ou pagamento.

 

Se tiver dúvidas, críticas ou sugestões utilize os comentários!

CSS3 – Background Gradient

Retomei meus estudos de HTML5, que eu gostaria de publicar por aqui mas sempre acabo apenas na leitura, mas resolvi utilizar CSS3 na versão nova do And After, deixando de lado preocupações visuais com o Internet Explorer.

Curvas arredondadas e backgrounds com gradientes funcionarão apenas em navegadores com suporte ao CSS3, porém posicionamento, tamanho, formatação de texto e funcionalidades funcionarão perfeitamente em qualquer navegador. Acho que esse é o método de desenvolvimento ideal – e mais rápido.

Vou abordar alguns temas relacionados ao CSS3 nos próximos posts, vamos ao background com degradê!

 

Background gradient com CSS

Fazer um background sem imagens tem diversas vantagens, entre as principais posso listar: menos kb para carregar, facilidade na manipulação por javascript, manutenção mais fácil.

Debatendo com o @MathieuRousseau sobre o uso ou não do CSS3, levantamos a questão da infelicidade que é não existir um padrão bem definido para o CSS3, mas a implementação não é tão dolorosa assim, apesar de ainda não funcionar corretamente uma forma cross-browser única.

Vamos a exemplos do código!

Gradiente vertical

.boxVertical {
background-color: #333; /* cor do bg caso tudo abaixo de errado */
background-image: url(images/linear_bg_2.png); /* imagem usada caso não exista suporte ao css3 (IE) */
background-image: -moz-linear-gradient(100% 100% 90deg, #333, #efefef);
/* para o mozzila */ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#efefef), to(#333)); /* para o webkit*/ }

 Gradiente horizontal

.boxHorizontal {
background-color: #333; /* cor do bg caso tudo abaixo de errado */
background-image: url(images/linear_bg_2.png); /* imagem usada caso não exista suporte ao css3 (IE) */
background-image: -moz-linear-gradient(100% 100% 180deg, #333, #efefef);
/* para o mozzila */ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#efefef), to(#333)); /* para o webkit*/
}

 

Como usar o -moz-linear-gradient

-moz-linear-gradient( [<point> || <angle>,]? <stop>, <stop> [, <stop>]* )

Point

Descrição: Interpretado como "background-position", define onde deve começar o gradiente.
Valores: porcentagem, pixels, "left", "center", or "right" para horizontal e "top", "center", ou "bottom" para vertical.

 

Angle

Descrição: ângulo da direção do gradiente.
Valores: degrees (90deg), grads (100grad), radians (1rad)

 

Stop

Descrição: valor composto de uma cor seguido por uma "parada" opcional (percentual ou px) que define a cor e a extensão dela no gradiente.
Valores: porcentam ou px (stop) e cor (hexadecimal, rgb…)

 

Para mais informações leia a documentação completa (em inglês)

 

Como usar o -webkit-gradient

 -webkit-gradient(<type>, <point> [, <radius>]?, <point> [, <radius>]? [, <stop>]*)

 

type

Descrição: define o tipo de gradiente
Valores: linear ou radial

 

point

Descrição: um par de valores separados, que definem de onde irá o gradiente. Os dois pares definem início e fim de X e Y do gradiente.
Valores: pixels, porcentagem ou top, bottom, left e right

 

radius

Descrição: define o raio do gradiente radial
Valores:

 

Stop

Descrição: valor composto de uma cor seguido por uma "parada" opcional (percentual ou px) que define a cor e a extensão dela no gradiente.
Valores: porcentam ou px (stop) e cor (hexadecimal, rgb…)

 

Curiosidades

O webkit, pelo menos até agora, continua carregando a imagem de background, mesmo que ela não seja exibida.

O Firefox (-moz) a partir da versão 3.6 não faz o download da imagem quando é utilizado o gradient, economia de uma requisição http!

 

Dicas Go Horse

  • O Internet Explorer sempre será um problema, porém ignorá-lo completamente não é uma solução boa. Mas se preocupar muito com ele é uma péssima idéia.
  • O site não precisa renderizar exatamente igual em todos os navegadores, deixe esta idéia de lado se preocupe apenas em fazê-lo funcionar em quase todos os navegadores.
  • Na nova versão do And After e no Eu Compraria! Shop resolvi ignorar o Internet Explorer quanto a border-radius e background-gradient. O usuário de IE poderá usar e navegar no site todo, sem problemas… porém a experiência visual (falei bonito, ein?) de quem utilizar um navegador decente será muito mais agradável: shadows, text-shadows,border-radius,background-gradient… não usei imagem de background no IE, apenas a cor de fundo, assim economizo requisições http.

 

Não achei muita coisa em português explicando sobre o background-gradient, então resolvi explicar um pouco mais ao invés de só publicar exemplos, espero que seja útil.

Duvidas e sugestões nos comentários!

 

Mais referências sobre background-gradient em: