Olá a todos :)
Este artigo apenas transcreve uma tarefa que tive nesse semestre, criar uma calculadora orientada a objetos.
Olá a todos :)
Este artigo apenas transcreve uma tarefa que tive nesse semestre, criar uma calculadora orientada a objetos.
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:
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!
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.
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.
O layout de nossa calculadora será numa tabela.
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,
Estamos com a estrutura preparada.
Vá até a aba FORMS.
Clique na primeira linha de sua tabela e clique sobre o ícone do Textfield.
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á:
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:
Clique sobre a primeira célula cinza-claro e vamos inserir um botão.
As mesmas telas de antes surgirão. Dessa vez não é necessário preencher o ID, basta clicar em OK.
Agora uma jogadinha:
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:
Próximo passo, clique no canto da tabela, selecionando-a:
Primeiramente, clique sobre a ‘esponjinha’ para resetar o tamanho da tabela. Depois, na marcação verde (o campo de ‘id’), digite calc.
Agora, vamos acertar a interface. Sabe o painel CSS Styles? Não? Pressione Shift+f11:
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.
Após tomar coragem, clique sobre a pequena folha com um sinal de “+” (canto inferior direito).
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.
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:
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.
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.
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
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!
Até agora tudo bonitinho, certo? Só mexemos com botões e interface. Agora vamos ver o código.
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.
A 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.
Procure 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!