Desenvolupament web dinàmic frontend amb javascript
Conceptes¶
Sessió 2: Dinamitzar continguts¶
Objectiu Sessió 2
L'objectiu d'aquesta segona sessió és treballar les estructures de control del llenguatge javascript i poder aplicar la lògica de les funcionalitats segons l'experiència de l'usuari.
Dinamitzar continguts¶
En una aplicació o web, normalment caldrà prendre decisions de contingut o format segons una condició dinàmica de valors que poden ser introduïts per l’usuari o venir per altres canals.
Exemple
Si volem saludar a la persona que interactua amb la interfície i segons l’hora prenem la decisió de dir bon dia o bona tarda.
La lògica que aplicariem seria
El llenguatge Javascript tindrà estructures de control que permetran dinamitzar el contingut seguint aquesta lògica.
Anem a veure-les:
- Si volem executar unes instruccions o mostrar unes etiquetes o aplicar un estil depenent d’una condició tenim les alternatives
- Si volem repetir unes instruccions o mostrar repetides etiquetes un número definit o indefinit de vegades, tenim els bucles
- Si volem agrupar conjunt de codi per una mateixa lògica, usarem funcions, que veurem més endavant.
Alternatives MDN ->¶
En JavaScript, una estructura if s'utilitza per a prendre decisions basades en condicions. La seva sintaxi bàsica és:
if
Afegint else:
let edat = 16;
if (edat >= 18) {
console.log("Ets major d'edat.");
} else {
console.log("Ets menor d'edat.");
}
Amb else if:
let nota = 85;
if (nota >= 90) {
console.log("Excel·lent!");
} else if (nota >= 70) {
console.log("Bé!");
} else {
console.log("Has de millorar.");
}
Operador ternari (alternativa compacta a if-else):
let edat = 20;
let missatge = (edat >= 18) ? "Ets major d'edat." : "Ets menor d'edat.";
console.log(missatge);
Important:
- Les condicions dins de l'
if
han de retornar un valor boolean (true
ofalse
). - Pots utilitzar operadors lògics com
&&
,||
i!
per combinar o negar condicions.
Exemple amb operadors lògics:
switch
També tenim l'estructura switch
s'utilitza per avaluar una expressió i executar blocs de codi segons el valor que retorni. És útil quan hi ha múltiples opcions possibles per a una mateixa variable o expressió.
Sintaxi bàsica:
switch (expressió) {
case valor1:
// Codi a executar si expressió === valor1
break;
case valor2:
// Codi a executar si expressió === valor2
break;
default:
// Codi a executar si cap cas coincideix
}
Exemple senzill:
let dia = 3;
switch (dia) {
case 1:
console.log("Dilluns");
break;
case 2:
console.log("Dimarts");
break;
case 3:
console.log("Dimecres");
break;
case 4:
console.log("Dijous");
break;
case 5:
console.log("Divendres");
break;
case 6:
case 7:
console.log("Cap de setmana");
break;
default:
console.log("Dia invàlid");
}
Explicació:
-
case
: Defineix un valor a comparar amb l'expressió del switch. Si coincideix, el bloc de codi dins del case s'executa. -
break
: Atura l'execució de més casos. Si no hi ha break, el programa continuarà executant els següents casos (efecte fall-through). -
default
: Opció per defecte si cap dels casos coincideix.
Consell:
Quan usar switch
vs if-else
:
Usa switch quan hi ha múltiples opcions basades en el valor exacte d'una variable.
Usa if-else quan cal avaluar condicions complexes o intervals.
Bucles MDN ->¶
Els bucles tracten de fer el mateix una vegada i una altra, repetidament segons una condició o bé un número definit de vegades. Sovint, el codi serà lleugerament diferent cada cop que duri el bucle, o s'executarà el mateix codi però amb diferents variables.
Primer mirem el bucle for
.
For
- El bucle
for
enJavaScript
s'utilitza per repetir un bloc de codi un nombre determinat de vegades. - És ideal quan coneixes el nombre d'iteracions per avançat.
Sintaxi:
Explicació:
- Inicialització: S'executa una sola vegada abans que comenci el bucle (ex.
let i = 0
). - Condició: Es comprova abans de cada iteració. Si és
true
, el bucle continua; si ésfalse
, s'atura. - Actualització: S'executa al final de cada iteració (ex.
i++
).
Exemple recorregut d'un array:
la variable i
permet accedir a les diferents posicions indexades de l’array
Nota:
El bucle for
és eficient per a iteracions controlades i es pot combinar amb altres estructures com condicions dins del seu cos.
While
El bucle while en JavaScript repeteix un bloc de codi mentre una condició sigui true. És útil quan no saps exactament quantes iteracions necessites però tens una condició per controlar-ho.
Sintaxi:
Exemple bàsic:
Explicació:
- Condició: Es comprova abans de cada iteració. Si és
true
, el codi dins el bucle s'executa; si ésfalse
, el bucle s'atura. - Si no s'actualitza la variable que afecta la condició, el bucle pot esdevenir infinit.
Quan usar while:
- Quan la repetició depèn d'una condició dinàmica que pot canviar dins del bucle.
- Quan no saps el nombre exacte d'iteracions.
- Si vols assegurar-te que el codi s'executi almenys una vegada, usa un
do...while
.
Conceptes per dinamitzar 💡¶
Concepte bàsic amb objectiu de començar a dinamitzar contingut.
Primer treballem què és el DOM?
Accedir al DOM¶
El DOM (Document Object Model) és un model d'objectes que representa les pàgines HTML en forma d'arbre amb diferents nodes.
El DOM defineix:
- cada element HTML com un objecte
- les propietats de cada element HTML
- els mètodes per accedir als elements HTML
- els esdeveniments de cada element HTML
A través del DOM es pot referenciar i manipular qualsevol element del document HTML:
- modificar els elements de la pàgina
- modificar els atributs i l'estil dels elements
- afegir i eliminar elements i atributs
- crear i modificar esdeveniments
Quan es carrega una pàgina HTML, el navegador crea l'arbre DOM de la pàgina.
Podem manipular qualsevol node del DOM utilitzant JavaScript i les alteracions es reflectiran immediatament a la pàgina HTML (i a la inversa passarà el mateix).
Important!
El DOM es crea en el moment en què la pàgina ha finalitzat de carregar tot el contingut, per tant hem d'assegurar-nos de no intentar accedir-hi abans.
L'objecte document representa tota la pàgina i és el propietari de tota la resta d'objectes.
Per accedir a objectes de la pàgina HTML sempre haurem de partir inicialment de l'objecte document.
A través dels seus mètodes associats podem:
Localitzar elements HTML¶
getElementById¶
Localitza un element pel seu id i el retorna si el troba. Altrament, retorna null.
getElementById
és un mètode d'ús exclusiu per l'objecte document
A diferencia d'altres mètodes del DOM, getElementById
només es pot invocar com a mètode de l'objecte global document, i donarà error si s'utilitza com a mètode d'un altre objecte del DOM. Això és així perquè els valors de id han de ser únics al document, i per tant no hi ha necessitat de buscar-los dins d'un element concret.
Atenció
Cal sempre evitar tenir elements amb el mateix id Si més d'un element de la pàgina té assignat el mateix id, se'ns retornarà el primer que localitzi en recórrer l'estructura del DOM.
getElementsByTagName¶
Localitza elements segons la seva etiqueta HTML. Retorna una llista de nodes en forma d'objecte HTMLCollection.
Atenció
El tipus de dades HTMLCollection és un un tipus viu, de manera que s'actualitza automàticament quan el document canvia.
// Cerquem tots els elements de tipus "div" del document
const llista = document.getElementsByTagName("div");
Podem recórrer una llista de nodes de la mateixa manera que ho fariem amb un array, utilitzant una iteració for:
o amb una iteració for...of, que ens retornarà els valors de la llista seqüencialment:
Podem cercar elements a una branca concreta del DOM enlloc de tot el document.
Per fer-ho, invoquem el mètode sobre l'element inicial de la cerca, i aquesta es farà només dins dels nodes que hi estiguin continguts.
// Cerquem els elements de tipus "div" que es troben dins de
// l'element amb id "inici", però no la resta de divs del document
const origen = document.getElementById("inici")
const llista = origen.getElementsByTagName("div")
// O bé sense variable auxiliar
const llista = document.getElementById("inici").getElementsByTagName("div")
getElementsByClassName¶
Localitza els elements segons seu nom de classe CSS, troba tots aquells que tinguin la classe indicada dins la seva llista de classes. Retorna una llista de nodes en forma d'objecte HTMLCollection.
Atenció
El tipus de dades HTMLCollection és un un tipus viu, de manera que s'actualitza automàticament quan el document canvia.
// Cerquem tots els elements HTML que tinguin la classe "e1",
// també si tenen altres classes simultàniament
const llista = document.getElementsByClassName("e1");
querySelector¶
Localitza un element segons els seus selectors amb sintaxi CSS.
Retorna el primer element dins del DOM que compleixi la condició, i si no en troba cap retorna null.
// Cerquem el primer element de tipus "p" que tingui la classe "titol"
const element = document.querySelector("p.titol");
querySelectorAll¶
Localitza llistes d'elements segons els seus selectors amb sintaxi CSS.
Retorna un objecte HTMLCollection amb la llista d'elements que compleixin la condició (tots els elements <p>
amb class="títol"
del document).
// Cerquem tots els elements del document que siguin
// de tipus "p" i que tinguin la classe "titol"
const element = document.querySelectorAll("p.titol");
Modificar elements HTML¶
Llegir i modificar el contingut¶
Podem consultar o modificar el contingut d'un element HTML a través de les propietats innerHTML
, innerText
i textContent
.
-
innerHTML
escriu i retorna el contingut mantenint les etiquetes HTML i les seqüències de caràcters especials (també les unicode). -
innerText
no fa cap conversió i escriu i retorna només el contingut de text de l'element HTML tal i com apareix després d'aplicar conversions HTML d'espais i salts de línia i els estils de l'element. -
textContent
escriu i retorna un resultat similar al deinnerText
però sense convertir els espais i salts de línia del text.
Escriptura
Resultat visible a la pàgina | |
---|---|
element.innerHTML = "<b>HOLA</b>" | HOLA |
element.innerText = "<b>HOLA</b>" | <b>HOLA</b> |
element.textContent = "<b>HOLA</b>" | <b>HOLA</b> |
Lectura
Valor retornat | |
---|---|
element.innerHTML | Text en <b>negreta</b> i <i>cursiva</i> |
element.innerText | Text en negreta i cursiva |
element.textContent | Text en negreta i cursiva |
Canviar el valor d'un atribut¶
Podem fer-ho assignant-li directament un valor al nom de l'atribut de l'element:
o amb el mètode setAttribute
, passant-li com a paràmetres el nom de l'atribut i el seu valor.
Un avantatge de fer-ho així és que el nom de l'atribut a modificar pot ser una variable:
document.getElementById( id ).setAttribute( "nom_atribut", "nou_valor" )
let atr = "nom_atribut"
document.getElementById( id ).setAttribute( atr, "nou_valor" )
Canviar el valor d'una propietat d'estil¶
Podem fer-ho assignant-li directament un valor al nom de la propietat CSS a través de l'atribut style de l'element:
Per utilitzar els noms de les propietats CSS amb JavaScript cal seguir aquestes regles:
- si la propietat conté més d'una paraula separades per guionets, es converteix a camelCase
- si la propietat és una sola paraula no es fa cap canvi
- excepció: la propietat float es converteix en
cssFloat
per ser paraula reservada
Exemples:
CSS | JavaScript |
---|---|
width | width |
height | height |
float | cssFloat |
background-color | backgroundColor |
border-bottom-width | borderBottomWidth |
z-index | zIndex |
document.getElementById( id ).style.border-color = "red" // ERROR
document.getElementById( id ).style.borderColor = "red" // Correcte
També podem assignar el nou valor de CSS a la propietat style amb la notació de claus ([ ]
).
Un avantatge de fer-ho així és que el nom de l'atribut CSS a modificar pot ser dinàmic:
document.getElementById( id ).style[ "nom_propietat" ] = nou_valor
let prop = "nom_propietat"
document.getElementById( id ).style[ prop ] = nou_valor
Si utilitzem aquesta sintaxi no cal fer cap conversió al nom de la propietat CSS i la podem utilitzar tal i com l'escriuriem en un full d'estils:
Operar sobre la llista de classes d'un element (classList)¶
Podem actuar sobre la llista de classes d'un element HTML de diferents formes i el resultat es reflectirà immediatament en pantalla.
Per fer-ho utilitzem mètodes de la propietat classList
.
add()
Afegeix una o diverses classes a l'element:
document.getElementById( id ).classList.add ( "nom_classe" )
document.getElementById( id ).classList.add ( "classe_1", "classe_2")
remove()
Elimina una o diverses classes de l'element:
document.getElementById( id ).classList.remove ( "nom_classe" )
document.getElementById( id ).classList.remove ( "classe_1", "classe_2")
Nota
Intentar eliminar una classe que no existeix o que l'element no té NO provoca un error.
toggle()
Alterna la presència d'una la classe dins de la llista de classes de l'element.
Si la classe existeix, s'elimina i retorna false
. Altrament s'afegeix i retorna true
.
document.getElementById( "boto" ).onclick = function ()
{
document.getElementById( "quadrat" ).classList.toggle( "vermell" )
}
exemple 1: Alternem la classe
<html>
<head>
<meta charset="UTF-8">
<title>Esdeveniments del ratolí</title>
<style>
body {
margin: 0;
}
button {
margin-left: 1em;
margin-top: 30px;
}
.zonaTest {
width: 80px;
height: 80px;
border: 1px solid black;
background-color: deepskyblue;
box-sizing: border-box;
float: left;
}
.vermell {
background-color: red;
}
</style>
</head>
<body>
<div class="zonaTest" id="zona1"></div>
<button id="boto">Fes clic per alternar la classe CSS</button>
<script>
document.getElementById("boto").onclick = function () {
document.getElementById("zona1").classList.toggle("vermell")
}
</script>
</body>
</html>
Tenim aquest resultat:
Tenim un div
amb la classe class="zonaTest"
i id = id="zona1"
.
Posem un botó <button id="boto">
, amb l'esdeveniment onclick
.
Cada vegada que fem click al botó s'executarà l'script següent:
<script>
document.getElementById("boto").onclick = function () {
document.getElementById("zona1").classList.toggle("vermell")
}
</script>
vermell
a zonaTest
i s'aplicarà background-color: red;
Si la classe no existeix a l'element, l'elimina.
Per tant e efectes pràctics es va alternant entre class="zonaTest"
i class="zonaTest vermell"
p2-s2-ex1-DomClasslist.html p2-s2-ex1-DomClasslist.html :fontawesome-solid-download:
contains()
Retorna un booleà indicant si la classe existeix o no dins de la llista de classes de l'element.
replace()
Substitueix una classe existent per una de nova.
Alguns extres més 💡¶
Assignar esdeveniments¶
Un esdeveniment és un mecanisme que desencadena l'execució de codi quan té lloc una acció determinada.
Podem fer-ho amb el nom de l'esdeveniment o amb addEventListener:
// En aquest primer cas, el que fem és indicar què farem quan fem clic a aquest element
document.getElementById("element").onclick = function() {
///
};
// En aquest segon cas, el que fem és afegir un control d'esdeveniment a l'element.
document.getElementById("element").addEventListener( "click", function() {
///
} );
Les dues maneres implementen el mateix esdeveniment a l'element HTML, però amb addEventListener
, ens permetrà implementar diversos esdeveniments alhora.
Random¶
Math.random()
retorna un nombre aleatori entre 0 (inclòs) i 1 (exclusiu):Math.random()
sempre retorna un nombre inferior a 1.
Nombres enters aleatoris de JavaScript
Math.random()
utilitzat amb Math.floor()
es pot utilitzar per retornar nombres enters aleatoris.
No existeixen els nombres enters de JavaScript. Recordem que hi havia només un tipus de número, amb o sense decimals. Tots es guarden amb coma flotant 64 bits.
Si volem nombres sense decimals, farem:
Mode estricte¶
El mode estricte provoca que es generin errors quan s'executa codi que considera una mala pràctica de programació i que altrament funcionaria sense donar cap error, possiblement ocasionant problemes difícils de detectar.
Aquesta directiva es va afegir al llenguatge partir de la versió 5 d'ECMAScript (2009).
El mode estricte de JavaScript es declara afegint la cadena "use strict";
a l'inici d'un bloc de codi o d'una funció.
Per exemple, si en JavaScript escrivim malament el nom d'una variable no es genera cap error, i es crea una nova variable global. En mode estricte això provocaria un error, en detectar que la variable no havia sigut declarada prèviament:
{
let variable = 5
varible = 4 // ERROR NO DETECTAT --> es crea una nova variable global
}
{
"use strict";
let variable = 5
varible = 4 // Uncaught ReferenceError: variable is not defined
}
Algunes funcions del mode estricte:
- no permet utilitzar variables que no s'hagin declarat prèviament
- no permet utilitzar objectes que no s'hagin declarat prèviament
- no permet esborrar variables, objectes ni funcions amb
delete
- restringeix l'ús de la funció
eval()
- canvia el comportament de la paraula reservada
this
Strict mode (MDN)
Exemples¶
Exemple Canvi Imatge
Tenim aquest resultat:
<script>
// Funció d'ajuda per seleccionar objectes
function $(e) { return document.getElementById(e) }
let estaPlovent = true
function canviaTemps() {
// Cada cop que invoquem la funció canviarem entre pluja o no
estaPlovent = !estaPlovent
if (estaPlovent) {
// Bloc d'estils per quan està plovent
$("imatge").src = "media/weather/10d.png"
$("titol").style.color = "white"
// Fons de pantalla que combina un GIF animat transparent (pluja) amb un fons de color
$("temps").style.background = "url('media/rain.gif') 0px -4px, darkblue"
}
else {
// Bloc d'estils per quan no plou
$("imatge").src = "media/weather/02d.png"
$("titol").style.color = "black"
$("temps").style.background = "linear-gradient(to bottom, white, lightblue, deepskyblue)"
}
// Mostrem els estils per pantalla
escriuValors()
}
function escriuValors() {
// Per simplificar, només voldrem mostrar la part final del path de les imatges
let path = $("imatge").src.split('/')
// Amb el delimitador ` podem crear strings de múltiples línies
$("codiJS").innerHTML = `
<p>text.<b>style</b>.<b>color</b> = "${$("titol").style.color}"</p>
<p>fons.<b>style</b>.<b>background</b> = "${$("temps").style.background}"</p>
<p>imatge.<b>src</b> = "media/weather/${path[path.length-1]}"</p>
`
}
canviaTemps()
escriuValors()
</script>
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvi de propietats d'elements</title>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
margin: 2em;
font-size: 0.7em;
}
li {
font-size: 1.5em;
margin-top: 0.5em;
}
#codiJS {
font-family: 'Courier New', Courier, monospace;
}
#msgClic {
color: grey;
font-size: 0.65em;
position: relative;
top: -3em;
left: 7.5em;
}
#temps {
width: 200px;
padding: 1em 2em;
color: black;
border-radius: 1em;
border: 4px solid grey;
background-position: 0 -20px;
text-align: center;
cursor: pointer;
margin: 2em 0;
}
</style>
</head>
<body>
<h1>Amb JavaScript podem canviar propietats</h1>
<li>dels elements HTML</li>
<li>dels seus estils</li>
<div id="temps" onclick="canviaTemps()">
<h3 id="titol">Previsió del temps</h3>
<img id="imatge">
</div>
<span id="msgClic">Clica la imatge per canviar</span>
<p id="codiJS"></p>
<script>
// Funció d'ajuda per seleccionar objectes
function $(e) { return document.getElementById(e) }
let estaPlovent = true
function canviaTemps() {
// Cada cop que invoquem la funció canviarem entre pluja o no
estaPlovent = !estaPlovent
if (estaPlovent) {
// Bloc d'estils per quan està plovent
$("imatge").src = "media/weather/10d.png"
$("titol").style.color = "white"
// Fons de pantalla que combina un GIF animat transparent (pluja) amb un fons de color
$("temps").style.background = "url('media/rain.gif') 0px -4px, darkblue"
}
else {
// Bloc d'estils per quan no plou
$("imatge").src = "media/weather/02d.png"
$("titol").style.color = "black"
$("temps").style.background = "linear-gradient(to bottom, white, lightblue, deepskyblue)"
}
// Mostrem els estils per pantalla
escriuValors()
}
function escriuValors() {
// Per simplificar, només voldrem mostrar la part final del path de les imatges
let path = $("imatge").src.split('/')
// Amb el delimitador ` podem crear strings de múltiples línies
$("codiJS").innerHTML = `
<p>text.<b>style</b>.<b>color</b> = "${$("titol").style.color}"</p>
<p>fons.<b>style</b>.<b>background</b> = "${$("temps").style.background}"</p>
<p>imatge.<b>src</b> = "media/weather/${path[path.length-1]}"</p>
`
}
canviaTemps()
escriuValors()
</script>
</body>
</html>
Tenim un codi HTML
amb text i una imatge a dins d'un `<div id="Temps">
amb programació de l'esdeveniment onclick="canviaTemps()"
Llavors tenim un script
amb el codi JS d'aquesta funció canviaTemps()
Tenim una variable estaPlovent
que hi canviem el valor de cert a falç o de falç a cert.
I depenent de si indica si plou o no amb el valor booleà fa una lògica o altra
if (estaPlovent) {
// Bloc d'estils per quan està plovent
$("imatge").src = "media/weather/10d.png"
$("titol").style.color = "white"
// Fons de pantalla que combina un GIF animat transparent (pluja) amb un fons de color
$("temps").style.background = "url('media/rain.gif') 0px -4px, darkblue"
}
else {
// Bloc d'estils per quan no plou
$("imatge").src = "media/weather/02d.png"
$("titol").style.color = "black"
$("temps").style.background = "linear-gradient(to bottom, white, lightblue, deepskyblue)"
}
- canviar la imatge entre 10d.png o 02d.png
- canviar l'estil entre blanc o negre
- canviar el fons entre una imatge gif o un gradient de colors
Finalment tenim una altra funció per mostrar els valors que tenim assignats escriuValors()
function escriuValors() {
// Per simplificar, només voldrem mostrar la part final del path de les imatges
let path = $("imatge").src.split('/')
// Amb el delimitador ` podem crear strings de múltiples línies
$("codiJS").innerHTML = `
<p>text.<b>style</b>.<b>color</b> = "${$("titol").style.color}"</p>
<p>fons.<b>style</b>.<b>background</b> = "${$("temps").style.background}"</p>
<p>imatge.<b>src</b> = "media/weather/${path[path.length-1]}"</p>
`
}
Info
Més endavant aprofundirem amb les funcions !
p2-s2-ex2-CanviImatge.html p2-s2-ex2-CanviImatge.html :fontawesome-solid-download:
Exemple Calculadora
Tenim aquest resultat:
<script>
function $(e) { return document.getElementById(e) }
// Esborrem la pantalla
$("pantalla").value = "0"
// Desactivem els botons [MC] i [MR]
$("MC").disabled = true;
$("MR").disabled = true;
// Valor inicial de la memòria
let memoria = 0
function clicBoto(boto) {
// Botó [MS] (Memory Set)
if (boto == "MS") {
// Guardem el valor a la memòria
memoria = $("pantalla").value
// Activem els botons [MC] i [MR]
$("MC").disabled = false;
$("MR").disabled = false;
}
else
// Botó [MC] (Memory Clear)
if (boto == "MC") {
// Buidem la memòria i esborrem pantalla
memoria = 0
$("pantalla").value = "0"
// Desactivem els botons [MC] i [MR]
$("MC").disabled = true;
$("MR").disabled = true;
}
else
// Botó [MR] (Memory Recall)
if (boto == "MR") {
// Recuperem el valor guardat a memòria
$("pantalla").value = memoria
}
else
// Botó fletxa (esborrar una posició)
if (boto == "E") {
// Eliminem el darrer caràcter de la cadena
$("pantalla").value = $("pantalla").value.slice(0, -1)
// Si era l'últim caràcter, mostrem un 0 enlloc de deixar-ho en blanc
if ($("pantalla").value.length == 0) {
$("pantalla").value = "0"
}
}
else
// Botó [AC] (All Clear)
if (boto == "AC") {
// Esborrem la pantalla
$("pantalla").value = "0"
}
else {
// Botó [=]
if (boto == "=") {
// Com que l'eval pot donar error, posem un bloc try..catch
try {
// Amb la funció eval avaluem l'expressió de la pantalla
$("pantalla").value = eval($("pantalla").value)
}
catch {
// En cas d'expressió no vàlida, mostrem un missatge d'error
$("pantalla").value = "ERROR"
}
}
else {
// Per qualsevol altre botó (operacions o números)...
// si hi havia un 0 al davant, el traiem per no arrossegar-lo...
if ($("pantalla").value == "0") {
$("pantalla").value = ""
}
// i finalment l'escrivim directament afegint-lo al final de la cadena
$("pantalla").value += boto
}
}
}
</script>
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calculadora v2</title>
<style>
#calculadora {
width: 470px;
background-color: rgb(0, 196, 0);
padding: 24px;
margin: 100px auto;
box-sizing: border-box;
}
#pantalla {
text-align: right;
font-size: 32px;
font-family: 'Courier New', Courier, monospace;
font-weight: bold;
padding: 10px;
width: 400px;
border: none;
}
#botons {
text-align: center;
}
button {
width: 80px;
height: 40px;
margin: 16px 10px;
border: none;
background-color: rgb(0, 128, 0);
color: white;
font-size: 24px;
cursor: pointer;
}
button[disabled] {
color: grey;
cursor: default;
}
</style>
</head>
<body>
<div id="calculadora">
<input type="text" id="pantalla" readonly>
<div id="botons">
<button onclick="clicBoto('MS')">MS</button>
<button onclick="clicBoto('MC')" id="MC">MC</button>
<button onclick="clicBoto('MR')" id="MR">MR</button>
<button onclick="clicBoto('AC')">AC</button>
<button onclick="clicBoto(7)">7</button>
<button onclick="clicBoto(8)">8</button>
<button onclick="clicBoto(9)">9</button>
<button onclick="clicBoto('/')">/</button>
<button onclick="clicBoto(4)">4</button>
<button onclick="clicBoto(5)">5</button>
<button onclick="clicBoto(6)">6</button>
<button onclick="clicBoto('*')">X</button>
<button onclick="clicBoto(1)">1</button>
<button onclick="clicBoto(2)">2</button>
<button onclick="clicBoto(3)">3</button>
<button onclick="clicBoto('-')">-</button>
<button onclick="clicBoto(0)">0</button>
<button onclick="clicBoto('.')">.</button>
<button onclick="clicBoto('%')">mod</button>
<button onclick="clicBoto('+')">+</button>
<button onclick="clicBoto('(')">(</button>
<button onclick="clicBoto(')')">)</button>
<button onclick="clicBoto('E')">←</button>
<button onclick="clicBoto('=')">=</button>
</div>
</div>
<script>
function $(e) { return document.getElementById(e) }
// Esborrem la pantalla
$("pantalla").value = "0"
// Desactivem els botons [MC] i [MR]
$("MC").disabled = true;
$("MR").disabled = true;
// Valor inicial de la memòria
let memoria = 0
function clicBoto(boto) {
// Botó [MS] (Memory Set)
if (boto == "MS") {
// Guardem el valor a la memòria
memoria = $("pantalla").value
// Activem els botons [MC] i [MR]
$("MC").disabled = false;
$("MR").disabled = false;
}
else
// Botó [MC] (Memory Clear)
if (boto == "MC") {
// Buidem la memòria i esborrem pantalla
memoria = 0
$("pantalla").value = "0"
// Desactivem els botons [MC] i [MR]
$("MC").disabled = true;
$("MR").disabled = true;
}
else
// Botó [MR] (Memory Recall)
if (boto == "MR") {
// Recuperem el valor guardat a memòria
$("pantalla").value = memoria
}
else
// Botó fletxa (esborrar una posició)
if (boto == "E") {
// Eliminem el darrer caràcter de la cadena
$("pantalla").value = $("pantalla").value.slice(0, -1)
// Si era l'últim caràcter, mostrem un 0 enlloc de deixar-ho en blanc
if ($("pantalla").value.length == 0) {
$("pantalla").value = "0"
}
}
else
// Botó [AC] (All Clear)
if (boto == "AC") {
// Esborrem la pantalla
$("pantalla").value = "0"
}
else {
// Botó [=]
if (boto == "=") {
// Com que l'eval pot donar error, posem un bloc try..catch
try {
// Amb la funció eval avaluem l'expressió de la pantalla
$("pantalla").value = eval($("pantalla").value)
}
catch {
// En cas d'expressió no vàlida, mostrem un missatge d'error
$("pantalla").value = "ERROR"
}
}
else {
// Per qualsevol altre botó (operacions o números)...
// si hi havia un 0 al davant, el traiem per no arrossegar-lo...
if ($("pantalla").value == "0") {
$("pantalla").value = ""
}
// i finalment l'escrivim directament afegint-lo al final de la cadena
$("pantalla").value += boto
}
}
}
</script>
</body>
</html>
Tenim un codi HTML
amb divs i botons per dibuixar una calculadora.
Llavors tenim un script
amb una funció clickBoto(ele)
de JS associada a onclick
de cada botó, passant com a paràmetre el botó.
<button onclick="clicBoto('MS')">MS</button>
<button onclick="clicBoto('MC')" id="MC">MC</button>
...
A la funció hi apliquem la lògica corresponent
function clicBoto(boto) {
// Botó [MS] (Memory Set)
if (boto == "MS") {
// Guardem el valor a la memòria
memoria = $("pantalla").value
...
}
}
Info
Més endavant aprofundirem amb les funcions !
p2-s2-ex3-Calculadora.html p2-s2-ex3-Calculadora.html :fontawesome-solid-download: