HTML5 Selector API – querySelector querySelectorAll

 Quem acompanha O Desenvolvedor já deve ter percebido que eu sou um grande fã do framework jQuery, utilizo-o diariamente no trabalho e nos projetos pessoais.

Desenvolver utilizando jQuery é extremamente produtivo e fácil, visto o sucesso deste framework a W3C resolveu documentar oficialmente seletores no DOM de forma mais fácil: o  querySelector e querySelectorAll.

querySelector e querySelectorAll

O querySelector é uma API de seleção de elementos do DOM que está disponível diretamente no document, isso facilita os seletores tornando-os muito próximos da seleção do jQuery (a W3C assumiu que os seletores vieram da idéia do jQuery, que na verdade é uma biblioteca separada, chamada Sizzle).

A função é bastante simples e o seletor pode ser de classe (exatamente como no jQuery .nome-da-classe ou de elemento, por exemplo p). O resultado do querySelectAll é uma lista com os elementos que casam com o seu seletor e o do querySelector é apenas o primeiro elemento que casar com a seleção passada.

Exemplo

<style>
.zebraon{background:silver}
</style>
<script>
function zebrado(selector){
var zebrar=document.querySelectorAll(selector);
for(var i=0;i<zebrar.length;i+=2)
zebrar[i].className="zebraon"
}


window.onload=function(){
zebrado("p");
zebrado(".zebra tbody tr");
}
</script>

Fiz um teste criando uma função para "zebrar" qualquer elemento da página (tabelas, por exemplo), no exemplo abaixo zebrei todos os parágrafos da página e as linhas da tabela com a classe zebrado. Para isso criei uma função que recebe como parâmetro a seleção, faz a busca usando o querySelectorAll e adiciona a classe "zebraon" que criei.

 

Um exemplo simples mas que mostra um bom amadurecimento na parte de seletores DOM! Antes de levantar qualquer debate – acho que isso não vai acabar com o uso de frameworks, mas provavelmente vai melhorar a performance das bibliotecas como jQuery já que a seleção será nativa, reduzindo parte da magia negra usada atualmente para isso.

E aí, o que acharam?

ParseInt em Javascript

Pouco depois de aprender arredondamento de números com o PHP eu estava desenvolvendo um código em javascript que recebia algumas informações numéricas e precisava arredondar o número que vinha, a fim de comparar com outro número inteiro.

Usando o parseInt eu percebi umas "reações estranhas" quando eu passava uma string que tivesse zero a esquerda, por exemplo "0x" não retornava X como int, retornava um número estranho.

Fui pesquisar sobre o assunto e abaixo explico o motivo desse retorno estranho…

parseInt

Na documentação do javascript a sintaxe da função é a seguinte:

parseInt(string, radix)

O parâmetro "string" é obrigatório é a string que será convertida para int, o parâmetro radix é opcional – aí começa o problema. Quando este parâmetro não é passado o script vai deduzir qual é o tipo da string passada e transformará ela em int.

Quando o número a ser convertido começa com 0 o script utiliza a conversão para octal, e não decimal. O radix que deve ser passado quando quiser forçar o uso do sistema octal é 8.

Quando o número a ser convertido começa com 0x (exemplo: 0xF) é utilizado o sistema hexadecimal para a conversão. O radix que deve ser passado quando você quiser forçar o uso do sistema hexadecimal é 16.

Nos casos restantes a conversão será feita utilizando o sistema decimal, para forçar o uso do sistema decimal o radix a ser passado é 10.

 

Solução

Se você quer converter o número para int utilizando o sistema decimal sempre passe o segundo parâmetro (radix) como 10, esta é uma boa prática que poderá fazer você economizar tempo tentando descobri porque em alguns casos específicos os cálculos do seu script não saem como o esperado…

Dúvidas e sugestões nos comentários! 🙂

Recuperando senhas armazenadas no navegador com javascript

Buenas, dando continuidade as minhas experiências com javascript rodando através da url no navegador achei uma utilidade para alguns comandos, por exemplo recuperar senhas que estão salvas no navegador.

O código utiliza jQuery, portanto o site deve ter o jQuery carregado (ou você pode carregar pela url, como explicado neste post).

Recuperando senhas gravadas no navegador

Existem softwares para recuperação de senhas gravadas em inputs do tipo password, neste caso não vou utilizar nenhum programa externo, apenas javascript e um navegador (testado apenas no FF).

O primeiro passo é acessar o site e fazer com que a senha seja carregada no campo de password, em alguns casos é necessário digitar o usuário para que isto aconteça.

Feito isso, carregue o jQuery no site através do campo da url:

javascript:var%20script=document.createElement("script");script.type="text/javascript";script.src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js";document.getElementsByTagName("head")[0].appendChild(script);void(0);

via Como carregar javascript externo em qualquer site

Sabendo que agora você pode usar os recursos do jQuery, você precisa encontrar o input do tipo password  e exibir o atributo "value" dele, o código que faz isso:

javascript:alert($("input[type=password]").val())

Simples assim, este comando deve abrir um alert com a sua senha.

Paranóico que sou, fui fazer testes em sites bancários – que não armazenam a senha, porém queria testar se era possível visualizar uma senha já digitada.

O site do Banco do Brasil chama uma função a cada tecla pressionada, que criptografa o valor digitado na senha, a função se chama filtraPassa. Portanto, o alert exibe a senha, mas ela é "criptografa".

Maldade: destruir a função filtraPassa, para isso fui na url e…

javascript: function filtraPassa(){};void(0);

A cada tecla pressionada a função é chamada (e não faz nada), então utilizando o código anterior é possível dar um alert na senha.

Não vejo isso como nenhum risco a segurança, já que é necessário ter acesso ao computador para fazer isso tudo (e a página não pode ser recarregada), então o relato foi apenas para entender o funcionamento da segurança nestes site. 🙂

Carregando um JavaScript em qualquer site

Passei minhas últimas madrugadas fazendo testes de segurança com javascript, e descobri umas coisas que achei interessantes. Desde que mudei para São Paulo comecei a trabalhar apenas com interface, isso me fez aprender muito sobre javascript, tomar alguns cuidados com performance e agora resolvi dar uma olhada em "segurança no front-end", se é que isso existe.

Quando eu falo de "segurança no javascript" me refiro a possibilidade de manipular o script da página para fazer alguma coisa que ela não está aguardando que seja feita, por isso vale relembrar que todo o processo de segurança e validação deve ser feito no back-end.

Bem, você deve saber que é possível executar um código javascript em uma página através da URL, para isso você só precisa digitar no campo de URL do navegador o comando javascript antecedido por "javascript:".

Por exemplo, aqui mesmo no O Desenvolvedor, digite o seguinte na url do seu navegador:

javascript:alert("DONT PANIC!");

Qualqur código js será interpretado quando colocado na linha de url do site, seria como um link no site com o comando "javascript:". Sabendo disso você sabe que é possível:

  1. Chamar qualquer função do código do site
  2. Criar e manipular funções do js (validação,posts,etc.)
  3. Manipular o DOM (inputs,action,methods)

Aí entra a minha curiosidade: existem plataformas onde o javascript pode fazer requisições que executam funções no back-end (insert,delete,update) e se isso não for validado e o usuário tiver um pouco de conhecimento do sistema, poderá executar funções malignas, penso eu. Ainda não testei.

Mas o motivo do post não é mostrar que é possível executar comandos através da url do navegador, é mostrar que é possível carregar um javascript hospedado em qualquer lugar e fazer com que ele seja interpretado pelo site que você está navegando.

Carregando um javascript em qualquer site

Utilizando a url do navegador vamos manipular o <head> da página e fazer com que ela carregue o jQuery, por exemplo. Vou primeiro colocar o código do "load", depois transformar ele em uma única linha para que seja colocado no navegador.

//criamos um <script> e setamos o tipo e a url
var script=document.createElement("script");
script.type="text/javascript";
script.src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js";

//manipulamos o <head> do site para inserir o script
document.getElementsByTagName("head")[0].appendChild(script);

 

Simples, se você colocar isso em qualquer .js do seu site ele irá carregar o jQuery do Google libraries. Para fazer isso através em qualquer site que você esteja navegando é só digitar o seguinte no campo de url (com o site carregado no seu navegador):

javascript:var%20script=document.createElement("script");script.type="text/javascript";script.src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js";document.getElementsByTagName("head")[0].appendChild(script);void(0);

A única diferença do bloco de código anterior é o void(0);, que serve unicamente para o navegador não entender seu comando com uma chamada para uma url e tentar abrir uma nova página.

Pronto, agora o site que você está visualizando tem a biblioteca jQuery funcionando.

Algumas curiosidades que descobri:

  1. Se o caminho do javascript que você tentar carregar for no seu computador "///file…" OU em um localhost (rodando servidor na sua máquina) ele será carregado no DOM porém não será interpretado
  2. Para o problema anterior não adianta simular um domínio apontando para o localhost (através do hosts do Windows), ele vai continuar carregando o javascript no DOM mas não interpretando

Então o jeito para carregar um JS externo é hospedar em algum servidor e fazer a chamada para o arquivo hospedado. Todos os testes foram feitos no Windows Seven com Firefox 3.6.

 

Opinião

Agora eu quero a opinião dos leitores, o que vocês acham deste lance de segurança no front-end? Uma babaquice? Perigoso? É necessário se preocupar?

Comentem, estou curioso sobre estas coisas e queria saber até que ponto vocês acham que pode ser perigoso a manipulação de uma página por scripts externos…

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.