JQuery UI – Dialog (bug ou feature?)

Fala galera da Dev,

Passei um apuro com o JQuery Dialog recentemente e resolvi compartilhar o problema (ou talvez feature mal documentada) com vocês.

Eu tinha um HTML da seguinte maneira (simplificado):

<html>
<body>
<form> <div id=’dialog’> … </div></form>
</body>
</html>

E precisava usar uma função de validação que checaria todos os inputs dentro da tag FORM. Com a minha marcação acima, tudo perfeito, certo? A div ESTÁ dentro do formulário, quando eu for validar, tudo que estiver na dialog também será validado, correto?

Errado.

Quando chamamos a dialog, o conteúdo é extraído do seu container original (no caso, do form).

Quer confirmar? Veja o seguinte:

<!doctype html>
<html lang="us">
<head>
	<meta charset="utf-8">
	<title>Testes</title>
	<link href="css/ui-lightness/jquery-ui-1.10.3.custom.css" rel="stylesheet">
	<script src="js/jquery-1.9.1.js"></script>
	<script src="js/jquery-ui-1.10.3.custom.js"></script>
	<script>

		var modal = null;

		$(function(){

			$("#btnModal").click(function(){

				modal = $("#modal").dialog({
					modal: true
				});

			});

		});

	</script>
	<style>
		body
		{
			font-family: sans-serif;
		}

		#container h2
		{
			color: #467;
			font-size: 55px;
		}
	</style>
</head>
<body>
	<div id="container">
		<div id="modal">
			GIMME FIRE <br />
			GIMME THAT WHICH I <br />
			<h2>DESIRE</h2>
		</div>
	</div>

	<input type="button" id='btnModal' value='GIMME FUEL' />

</body>
</html>

Visualização:

a1Visualização com o Firebug:

a2

Até ai, tudo lindo. Contemplem como tudo fica após a invocação da dialog:

a3

Notaram que o html sumiu e foi para a dialog? Inclusive o “DESIRE” perdeu a formatação. Pois é… Não foi só isso que aconteceu nos bastidores:

a4

Nossa div foi movida para fora do “container”, causando a perda da formatação.

Soluções

  • Faça com que a div contenha tudo que você precisa
  • Chore no bugtracker do JQuery UI

No meu problema, a solução foi simples. Bastou colocar o form dentro da dialog, para que o formulário fosse transportado junto com a dialog no momento do chamado:

<html>
<body>
<div id=’dialog’><form>  … </form></div>
</body>
</html>

Não é bonito, mas resolve!

Dúvidas? Sugestões? Deixem nos comentários!

Javascript – Máscara para nono dígito de celular

Boa noite,

Recentemente enfrentei um problema interessante no trabalho. Foi necessário programar uma máscara com o nono dígito opcional para celulares de São Paulo que contivessem o dígito “9”.

Por exemplos, o campo deveria aceitar (e exibir com uma formatação agradável visualmente) os seguintes valores:

8391-7788

98391-7788

Foi necessário um pouco de javascript para atender a necessidade, deixo abaixo o código (usando JQuery e JQuery Masked Input) que usamos para resolver o problema:

		<script>

			//acrescenta à classe string um método necessário para facilitar
			String.prototype.splice = function( idx, rem, s ) {
				return (this.slice(0,idx) + s + this.slice(idx + Math.abs(rem)));
			};

			$(function(){

				//máscara inicial com o nono digito opcional
				$("#txtCel").mask('9999-9999?9');

				//ao sair do campo, vamos atualizar a máscara
				$("#txtCel").focusout(function(){

					//pegando apenas os digitos
					var cel = $("#txtCel").val().replace('-','').replace(/_/g,'');

					//se tiver 8 digitos
					if(cel.length == 8)
					{
						//vamos colocar o '-' no meio
						cel = cel.splice(4, 0, '-');
						//seta a máscara para aceitar o nono digito
						$("#txtCel").mask('9999-9999?9');
					}
					//caso contrário
					else if(cel.length == 9)
					{
						//deixamos 5 digitos na esquerda
						cel = cel.splice(5,0, '-');
						//seta a máscara para aceitar um digito a menos (caso tenha digitado errado)
						$("#txtCel").mask('99999-999?9');
					}

					//põem o valor no campo
					$(this).val(cel);

				});

			});
		</script>

Fecha a régua e passa a conta! (ou algo assim)

Comunicação e interação entre janelas com Javascript

Fala galera!

Sumi por uns tempos devido a provas na faculdade e um super projeto que demos o sangue pra terminar no prazo.

Some isso a mais algumas aulinhas de CFC (9, cada uma de 5 horas) e desconte o que sobrar do meu banco de horas como blogueiro. =D

Na execução do projeto, precisávamos fazer com que duas janelas de HTML comunicassem uma com a outra. Depois de pensar um pouco, arranjei uma solução.

É só fazer uma janela acessar a outra! Veja como fiz.

Calculadora em JavaScript – PT2

Se arrependimento matasse…

Parte 2 de 2;

Código bruto

Montada a GUI e engatilhados os eventos, agora ela tem de fazer algo. Com javascript, dedicação e um pouco de fé, vai funcionar.

Nosso objetivo final é algo assim: http://ddona.free0host.com/calcjs/

Parecia algo tão simples programar uma calculadora. Mas deu muitos problemas deixá-la como eu queria sem o uso de eval. Tudo começou pois a amiga de uma amiga tinha de fazer uma para a faculdade de castigo e eu acabei sendo escalado pra programar a desgrama.

Ela levou uma versão com cerca de 100 linhas e alguns bugs. A versão final está com 192 xD.

Sinceramente não sei se cometi uma “manuelzada” no algoritmo, mas não encontrei nenhuma outra para comparar.

A teoria é esta:

  • O usuário pode digitar qualquer número racional (inteiros, quebrados)
  • O usuário deve escolher uma única operação (se clicar na subtração e depois em multiplicação, prevalece sempre última)
  • O usuário deve digitar um novo número, se for o primeiro cálculo (12 * o quê?).
  • O botão de igual só vai dar resultados se tivermos uma operação válida a avaliar (12 * 2). Se tivermos (12 / 0) ou alguma coisa do gênero, o resultado sempre será um display limpo e o reinício do processo (como se voltassemos ao primeiro numero)
  • Ao pressionar um botão de operação pela segunda vez, o display já se atualiza com o valor da operação anterior

Segue o código fonte comentado e, até onde eu sei, funcionando!

var num2,resultado;
var vez=0;
var operacaoLocal,operacaoGlobal=null;
var statusOperacao=0;

/*******************

statusOperacao:
Verifica se estamos com alguma operação aritmética ativada,
evitando que o usuario faça N divisões antes de trocar o numero

----
vez:
Da vez "0" que fazemos uma operação, deixamos o valor como resultado

15 +... -> o 15 será nosso primeiro resultado

Da vez "1", pegamos o numero digitado

... + 25 -> 25 será o num2

Da vez "2", fazemos a conta, resultado + num2

Evitamos a volta a vez 0 pois o resultado com que lidaremos é sempre o que está no display
----

operacaoGlobal:
Detecta se o usuário está escolhendo operações diferentes em sequencia
operacaoLocal:
Serve para podermos atualizar o display com a operação anterior

*******************/

function display(numero)
{
	x = document.getElementById("display");

	//NaN = Not a Number (!NaN = é um número)
	//isFinite é para evitar divisão por 0
	if(!(isNaN(numero)) && isFinite(numero))
	{
		x.value = resultado.toString();
		statusOperacao = 1;
	}
	else
	{
		limpar();
	}
}

function executarCalc(op)
{
	switch (op)
	{
		case "+":
			//ADIÇÃO
			resultado = resultado + num2;
			break;

		case "-":
			//SUBTRAÇÃO
			resultado = resultado - num2;
			break;

		case "*":
			//MULTIPLICAÇÃO
			resultado = resultado * num2;
			break;

		case "/":
			//DIVISÃO
			resultado = resultado / num2;
			break;
	}
}

function acres(numero)
{
	var i,count=0;
	x = document.getElementById("display");

	//conta quantos pontos temos no display
	for(i in x.value)
	{
		if(x.value[i] == '.')
		{
			count++;
		}
	}

	if(numero == '.' && (count > 0 || x.value.length == 0))
	{
		return(0);
	}

	if(statusOperacao == 1)
	{
		statusOperacao =  0;
		//corrigimos a operação global para a última escolhida
		operacaoGlobal = operacaoLocal;
		x.value = "";
		vez = 1;
	}

	x.value = x.value + numero;	

}

function limpar()
{
	x = document.getElementById("display");

	x.value = "";
	resultado = 0;
	num2 = 0;
	vez=0;
	statusOperacao=0;
	operacaoGlobal = null;
	operacaoAux = null;
	operacaoLocal = null;
}

function calc(operacao)
{
	operacaoLocal = operacao;
	x = document.getElementById("display");
	valor = parseFloat(x.value);
	//alert("global: "+operacaoGlobal);
	//alert("op: "+operacao);

	if(statusOperacao == 1)
	{
		return(0);
	}

	if(vez == 0)
	{
		resultado = valor;
		vez=1;
		x.value = "";
		//alert("atribuindo "+resultado+" para resultado");
		statusOperacao = 1;
		operacaoGlobal = operacaoLocal;
		return(0);
	}

	if(vez == 1)
	{
		num2 = valor;

		//vemos se o usuário pressionou soma, digitou um valor
		//e depois mudou a operacão
		if(operacaoGlobal != operacaoLocal)
		{
			executarCalc(operacaoGlobal);
			//re-ajustamos o valor
			num2 = valor;
			//passamos pra próxima vez
			vez=2;
			//atualizamos o display
			display(resultado);
			//estamos numa operação...
			statusOperacao = 1;
			//igualamos a operação
			operacaoGlobal = operacaoLocal;
			//paramos a função, se não fará a próxima conta sem o input do usuário
			return(0);
		}
		else
		{
			vez = 2;
		}
	}

	if(vez == 2)
	{
		executarCalc(operacaoLocal);
		display(resultado);
		operacaoGlobal = operacaoLocal;
	}
}

function resFinal()
{
	x = document.getElementById("display");

	if(statusOperacao == 0)
	num2 = parseFloat(x.value);

	executarCalc(operacaoLocal);
	display(resultado);
	//re-inicia o ciclo
	vez=1;
	//demos o resultado, precisamos pedir que o usuário efetue uma nova operação
	statusOperacao = 1;
}

Qualquer coisa, basta entrar em contato.

cya!

Calculadora em JavaScript – PT1

Calculadora do Windows:

A melhor coisa do Sistema Operacional. :D

Parte 1 de 2;

Criação da interface e engatilhar eventos.

Este post é um tutorial mais simples e detalhista para a interface, se você já sabe como lidar com o DreamWeaver e algo de CSS, pode pular direto para a parte 2. Apenas dê uma olhada na parte final, pois vamos engatilhar os eventos nos botões e etc.

Nosso objetivo final é algo assim: http://ddona.free0host.com/calcjs/

Parte 2, da codificação, aqui.

Já tentou criar uma calculadora de verdade com programação? Existem muitos exemplos de calculadoras com 2 campos de valores, botões de operação e um campo de resultado.

Esse é um modelo que facilita muito a codificação, pois você deposita no usuário o problema de organização das operações.

O bixo pega quando você tenta fazer somente um campo, que abrigará N valores e compete com a mostra de resultados. Estilo uma calculadora de verdade.

Quando mexia com Delphi, fiz uma calculadora nesse estilo. Porém, após alguns testes, percebi que ela fazia apenas 2 termos e resultado (2+2 = 4, 2 / 2 = 1…), me enrolando muito para deixar no modelo de N termos.

O grande problema é o seguinte, em minha visão: Você precisa saber quando o que está no display é resultado ou um valor de operação.

Existem algumas calculadoras em JS na internet que usam a função eval. Basicamente, ela considera tudo que é digitado é faz as operações ou executa os códigos.

Se eu entrar com uma string “2*2 + 5 * 7”, o retorno será 39. O problema é que se o usuário conseguir entrar com algum código javascript, este também será executado.

So what?

Sentei e fiz uma sem eval. Me surpreendi pois foi um código bem extenso, lidando com alguns problemas que nunca havia notado. Por isso opto por dividir este artigo em 2 partes, esta para a criação da interface e “engatilhar” as funções e o próximo para codificar.

Componentes e estrutura

O layout de nossa calculadora será numa tabela.

Esboço

Esboço

A primeira linha será ocupada pelo visor, o campo de operações.

Nos campos cinza-claro, teremos os números, o botão de ponto e uma tecla de “clear”. Nos cinza-escuro, os botões de operação (adição, subtração…).

A última terá o botão de igual.

Se não sabe como montar essa tabela,

table_01Basta selecionar as linhas e clicar no botão indicado, para uni-las.

Coisa linda.

Estamos com a estrutura preparada.

Vá até a aba FORMS.

btnTxtClique na primeira linha de sua tabela e clique sobre o ícone do Textfield.

caixaInput

Se esta tela aparecer, maravilha.

Em ID, preencha com Display, é a identificação do objeto na sua página HTML. Na parte de style, marque a opção “No label tag”. A label tag serve para deixar um texto ao lado do objeto que você inseriu, sendo neste projeto inútil.

Pressione OK e mais uma tela surgirá:

caixaInput2

Geralmente quando usamos textfields, botões e outros objetos da aba Forms, o dreamweaver pensa que estamos criando um formulário. Não é o nosso caso, quantas vezes esta tela aparecer neste projeto, clique não.

Agora sua tabela deve estar assim:

table_02

Clique sobre a primeira célula cinza-claro e vamos inserir um botão.

btnTxt

As mesmas telas de antes surgirão. Dessa vez não é necessário preencher o ID, basta clicar em OK.

Agora uma jogadinha:

table_03

Clique sobre o botão que você acabou de inserir. Se a aba “Properties”(propriedades) não estiver aparecendo, pressione CTRL+F3. Em value, preencha com o número que estaria no botão.

Não se preocupe se ela ficar deformada, depois consertaremos a interface. Repita o processo do botão com todos os espaços.

Se lembre de adicionar os numeros de 0 a 9, o ponto, os sinais de operação e o botão de igual, que deve ficar na última linha.

Díca: Se você clicar sob um botão já inserido, der um CTRL+C e CTRL+V em outra célula, você só tem que editar o value dele.

No final, deve ser algo assim:

table_04

Próximo passo, clique no canto da tabela, selecionando-a:table_05

Primeiramente, clique sobre a ‘esponjinha’ para resetar o tamanho da tabela. Depois, na marcação verde (o campo de ‘id’), digite calc.

CSS e interface

Agora, vamos acertar a interface. Sabe o painel CSS Styles? Não? Pressione Shift+f11:

css_panel

Ele deve surgir na direita. Precisamos dele pois vamos estilizar nossa calculadora usando CSS.

CSS é um acrônimo para Cascading Style Sheet (Folhas de Estilo em Casca). Com essa tecnologia, é possível formatar com extrema precisão qualquer elemento de uma página web, um por um ou em lote.

Mais informações sobre CSS.

Após tomar coragem, clique sobre a pequena folha com um sinal de “+” (canto inferior direito).

table_06

Selector Type = Especifica o que vamos criar (uma classe, se vamos definir um id, se vamos mexer com uma tag específica…)

Selector Name = o nome que você dará a regra.

Rule Definition = Se criaremos no próprio documento ou num arquivo novo.

Defina o Type como TAG. Perceba que o campo de NAME já será preenchido com algo. Clicando na setinha do combo box, você verá uma lista de todos os elementos que você pode brincar. Digite td, que é o elemento correspondente a cada célula da tabela. Em Rule Definition, escolha new style sheet file. Pressione OK.

Um diálogo de salvar arquivo surgirá. Dê um nome e clique em salvar.

table_07

Nesta tela de cima, você pode colocar todas as definições de CSS que desejar. Todas estão divididas por categoria.

Escolha a categoria BOX. Vá até padding e digite 5 na caixa de texto. Aperte OK.

Perceba que sua tabela foi atualizada instantâneamente. E o painel de Css também:

table_08

Caso queira mudar o valor, basta clicar no número, apagar e digitar outro (mantendo o px no fim). Caso queira mudar outra coisa, clique no pequeno lápis (canto inferior direito, ao lado da folha com +).

Clique novamente na folha e crie uma nova regra, type tag e de name input. Vá até a categoria Positioning e defina width e height como 40 e 25, respectivamente.

table_09

Clique para criar uma nova regra CSS. Dessa vez o type será CLASS. Se é class, o nome deve sempre iniciar com um ponto. Ex:

.meuNome, .blabla, .asd

Sugestão: .display

Novamente clique na aba de positioning. Em width, digite 100. Note que a caixa ao lado está mostrando o valor em px, ou seja, pixels. Clique nela e escola a medida em porcentagem (%).

Clique sob o textbox de display.

table_10

Note que na barra de propriedades existe uma propriedade CLASS. Clique na caixa e veja que a sua classe recem criada está lá. Se você tivesse criado mais de uma, ela também estaria ali, podendo ser aplicada livremente.

Aplique a classe para o display e também no botão de =.

Opa, epa, ei! Chamamos a classe de .display e aplicamos num botão??

Classes podem ser aplicadas livremente em N objetos de N categorias. Obviamente, estamos cometendo um erro ao aplicar esta classe com este nome, isto pode nos confundir e é um mau-hábito.

Mudemos o nome da classe para… .areaMaior

table_11_1

table_11_2

table_11_3

Escolha Sim (ou Yes… ou Sí… Sei lá, qualquer coisa que signifique Sim)

Se o find e replace não mudar automaticamente a classe do seu display e botão, faça isso manualmente (clique sobre eles, escolha a classe com o novo nome).

Beleza! Acabamos a estrutura da interface gráfica. Com seus conhecimentos em CSS e um pouco de estudo, você pode enfeitá-la ainda mais, porém paro por aqui. Mexemos com uns 3% do que o CSS pode fazer. Pesquise, arrisque  e pergunte para descobrir mais!

Engatilhar eventos

Até agora tudo bonitinho, certo? Só mexemos com botões e interface. Agora vamos ver o código.

table_12

Repare que estamos em Design. Clique em Code.

Está vendo todo o código? O DreamWeaver gerou tudo por você. Clique novamente em Design. Clique sob um dos botões da interface e em seguida sobre code.

table_13A parte azul é a seleção direta do que você tinha clicado.

Posicione o cursor ao lado da segunda aspa de value e pressione espaço. Se uma lista não aparecer, tente ctrl+barra de espaço.

table_14Procure o “onclick” e dê um duplo clique. Ele vai gerar o evento de clique para você. Poderíamos ter digitado, mas achei conveniente mostrar essa funcionalidade.

Dentro das aspas criadas, digite acres(this.value);

Isto é uma chamada de função que será enviada ao nosso arquivo de código (aliás, ainda inexistente :)).

acres = nome da função

this.value = parâmetro, dado que estamos passando

Adianto que “acres” vai inserir um número no textbox de display.

“Ué, vai aparecer esse texto this.value então?”

Não. this.value é um comando javascript. Quem sabe inglês já deve ter matado: este.valor. Estamos passando o valor do objeto atual. Se estamos no botão 7, e ele tem o value como 7… Passamos 7 para a função.

Acrescente o onclick e a função acres em todos os numeros.

Nos botões de operação, faça exatamente o mesmo, mas ao invés de acres, digite calc(this.value);

No clear, limpar();

No igual, resFinal();

É isso ai. Engatilhamos todos os eventos necessários. No próximo artigo veremos como fazer essa bagaça funfar.

Qualquer erro, dúvida, basta entrar em contato.

Cya!

limitar caracteres em textarea

Iniciando a série “Diego e as madrugadas de ódio“:

Outro dia minha mãe precisava enviar um texto pelo site de sua faculdade, num campo textarea.

Do nada ela me chama e pergunta como ver a quantidade de caracteres “nesse maldito word novo”. Me aproximo e procuramos como fazer (acho essa nova disposição muito boa, mas ainda me perco). Foi uma caçada, mas achamos.

Por curiosidade, ela precisava contar os caracteres pois o site restringia a resposta a 2500 caracteres.

Espero, com muita fé, que existisse algum código server-side avisando o aluno que sua resposta estava grande de mais, pois a interface era simplesmente o textarea e um texto estático avisando do limite, mas sem informar o quanto já estava escrito.

Deveriam fazer alguma coisa que contasse direto no site!…  Será que é tão difícil?

Sexta Feira, meia noite…

Sem nada melhor para fazer Por vontade de resolver o problema, saquei o Google e meu pouco conhecimento de JavaScript e fui a batalha. O resultado, imagino eu, está legal e funcional.

Veja o exemplo do textarea restrito aqui

Quero programar!

Não vou explicar o CSS – Ele é perfumaria. Você pode vê-lo com um exibir-código fonte e colar num editor qualquer.

Lógica:

Quando a página for re-carregada com um F5, quando o usuário pressionar uma tecla e enquanto ela estiver pressionada precisamos atualizar o contador.

Vou usar uma função chamada contar, com dois parâmetros:

  1. oq estou contando?
  2. qual objeto devo atualizar?

Para acessar a função, usaremos eventos do javascript, que estão disponíveis nos ‘objetos’ do HTML.

Para cuidar do F5, agimos diretamente no body ONLOAD

<body onload=”contar(‘textarea‘,’texto’)”>

Para os outros 2 eventos (que são basicamente de teclado) vamos agir diretamente no textarea:

<textarea name=”textarea” cols=”45″ id=”textarea onkeypress=”contar(‘textarea‘,’texto’)” onkeyup=”contar(‘textarea‘,’texto’)”></textarea>

O keyup serve para contar o caractere final (quando soltamos a tecla) e o keypress o que digitarmos enquanto seguramos uma tecla.

Perceba que a função é preenchida com o ID do textarea. “texto” é uma div que temos abaixo do form:

<div id=”texto“>[ 0 / 2500 ]</div>

Disparamos os eventos para a função, vamos construí-la. Eu fiz no próprio HTML, logo abaixo do title, mas é recomendado que você use um arquivo externo .js.

<title>Untitled Document</title>

<script type=”text/javascript”>

function contar(oq,qual)
{
var num;

//abaixo: descobrimos quantos caracteres temos no “oq”

num = document.getElementById(oq).value.length;

if(num >= 2500)
{
//se for maior ou igual a 2500, apagamos o excesso (se houver)
//e avisamos o usuário

document.getElementById(oq).value = document.getElementById(oq).value.substring(0,2500);
//re ajusta a variável
num = document.getElementById(oq).value.length;
//avisa o usuário
document.getElementById(qual).innerHTML = ‘[ <strong>’+num+'</strong> / 2500 ] – <span class=”aviso”>PSIT! O limite de 2500 caracteres foi atingido.</span>’;
}

else
{
//apenas atualizamos o numero, ainda está no limite
document.getElementById(qual).innerHTML = ‘[ ‘+num+’ / 2500 ]’;
}
}

</script>

Oxi. Pequeno e funcional.

Bônus:

  • Get Element By Id é uma função do javascript que te fornece dados dos objetos HTML, sendo guiada por um ID.
  • sobre innerHTML: é uma maneira rápida de se re-escrever HTML. Não é o recomendado (pelo que vi na WEB) pois você perde algumas “camadas” de HTML. Mas como é uma simples DIV, sem nenhum elemento, não achei que arrancaria o braço de alguém se usada.

É issae. Qualquer coisa (código errado, sugestão de melhoria etc) basta dar um aviso.

Cya!

(btw: “madrugadas de ódio” pois rolaram alguns socos na parede e mordidas no dedo quando o código se comportou estranho :)