rinomina esercizi js

This commit is contained in:
2026-02-12 18:36:35 +01:00
parent f0b6b85b36
commit 60878cf770
150 changed files with 16 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<title>Manipolazione Dati</title>
</head>
<body>
<div class="controls">
<h1>Tutorial: Manipolazione Dati</h1>
<button id="btn-esegui">▶️ Esegui Codice</button>
<button id="btn-reset">🧹 Pulisci Console</button>
<a href="../index.html" style="position: absolute; top: 20px; left: 20px; text-decoration: none; color: #555; font-weight: bold;">← Dashboard</a>
</div>
<script>
function mostraOutput(stepNumero, messaggio) {
const elemento = document.getElementById(`output-${stepNumero}`);
if (elemento) {
messaggio = messaggio || "❌";
let isObject = (typeof messaggio === 'object' && messaggio !== null);
elemento.textContent = isObject ? JSON.stringify(messaggio, null, 2) : String(messaggio);
elemento.classList.remove("loading");
elemento.style.transition = "";
elemento.style.backgroundColor = "#666";
setTimeout(() => {
elemento.style.transition = "background-color 1s ease";
elemento.style.backgroundColor = "#2d3436";
}, 0);
}
}
[
{
title: "1. Normalizzazione Stringhe",
description: "Pulizia spazi (trim) e gestione Maiuscole/Minuscole.",
outputLabel: "Stringa pulita:"
},
{
title: "2. Analisi ed Estrazione",
description: "Cercare parole (includes) e dividere testi (split).",
outputLabel: "Risultati Analisi:"
},
{
title: "3. Parsing Prezzi",
description: "Da stringa a numero: replace, parseFloat e toFixed.",
outputLabel: "Prezzo formattato:"
},
{
title: "4. Arrotondamenti",
description: "Gestire i decimali: round, ceil (eccesso) e floor (difetto).",
outputLabel: "Peso arrotondato:"
},
{
title: "5. Numeri Casuali",
description: "Generare numeri random e scalarli.",
outputLabel: "Numero casuale:"
},
{
title: "6. Template Literals",
description: "Creare stringhe dinamiche con variabili e espressioni.",
outputLabel: "Card HTML:"
}
].forEach((step, i) => {
document.write(`
<div class="step-card">
<div class="step-header">
<div class="step-title">${step.title}</div>
</div>
<div class="step-desc">${step.description}</div>
<span class="label">${step.outputLabel}</span>
<div id="output-${i + 1}" class="output-box"></div>
</div>
`);
});
</script>
<script src="script.js"></script>
<script>
document.getElementById('btn-reset').addEventListener('click', () => {
localStorage.clear();
location.reload();
});
document.getElementById('btn-esegui').addEventListener('click', () => {
const el = document.querySelectorAll('[id^="output-"]');
el.forEach(box => box.className = "output-box loading");
eseguiTutorial();
});
</script>
</body>
</html>

View File

@@ -0,0 +1,164 @@
// TUTORIAL INTERATTIVO: Manipolazione Dati
// Funzione pricipale del tutorial
function eseguiTutorial() {
/**
* ======================================================
* LIVELLO 1: Normalizzazione (Stringhe Base)
* Spesso i dati arrivano "sporchi" o scritti male.
* Dobbiamo standardizzarli per poterli usare correttamente.
* ======================================================
*/
let nomeProdotto = " MacBook Pro M3 ";
// TODO 1: Rimuovi gli spazi iniziali e finali (trim)
let nomePulito = "";
// TODO 2: Converti tutto in MAIUSCOLO per il codice magazzino (toUpperCase)
let perMagazzino = "";
// TODO 3: Converti tutto in minuscolo per la ricerca (toLowerCase)
let perRicerca = "";
mostraOutput(1, {
originale: nomeProdotto,
trim: nomePulito,
upper: perMagazzino,
lower: perRicerca
});
/**
* ======================================================
* LIVELLO 2: Estrazione Dati (Stringhe Avanzate)
* Analizziamo una stringa complessa che contiene più informazioni.
* Stringa: "LAPTOP GAMING | 16GB RAM | SSD"
* ======================================================
*/
let descrizione = "LAPTOP GAMING | 16GB RAM | SSD";
// TODO 1: Controlla se la descrizione contiene la parola "SSD" (includes)
// Restituisce true o false
let haSSD = false;
// TODO 2: Spezza la stringa in un array usando il separatore "|" (split)
// Otterrai: ["LAPTOP GAMING ", " 16GB RAM ", " SSD"]
let caratteristiche = [];
mostraOutput(2, {
contiene_ssd: haSSD,
lista_parti: caratteristiche
});
/**
* ======================================================
* LIVELLO 3: Pulizia Prezzi (Parsing Numeri)
* Trasformiamo una stringa di valuta in un numero matematico.
* ======================================================
*/
let prezzoCartellino = "1499.95€";
// TODO 1: Rimuovi il simbolo "€" sostituendolo con niente "" (replace)
let prezzoSenzaSimbolo = prezzoCartellino;
// TODO 2: Converti la stringa rimasta in un numero decimale (parseFloat)
let prezzoNumero = 0;
// TODO 3: Formatta il numero come stringa con 1 solo decimale (toFixed)
// Nota: toFixed restituisce una STRINGA, non un numero!
let prezzoFormat = ""; // ... usa .toFixed(1)
mostraOutput(3, {
stringa_pulita: prezzoSenzaSimbolo,
numero_vero: prezzoNumero,
formattato: prezzoFormat
});
/**
* ======================================================
* LIVELLO 4: Arrotondamenti (Matematica)
* Gestiamo un peso per la spedizione. Spesso i corrieri arrotondano.
* Peso: 1.256 kg
* ======================================================
*/
let peso = 1.256;
// TODO 1: Arrotondamento classico (Math.round)
// 1.2 -> 1, 1.5 -> 2, 1.8 -> 2
let arrotondato = 0;
// TODO 2: Arrotondamento per ECCESSO (Math.ceil - "Soffitto")
// Utile per calcolare quanti pacchi servono (1.1 diventa 2)
let perEccesso = 0;
// TODO 3: Arrotondamento per DIFETTO (Math.floor - "Pavimento")
// 1.9 diventa 1
let perDifetto = 0;
mostraOutput(4, {
originale: peso,
round: arrotondato,
ceil: perEccesso,
floor: perDifetto
});
/**
* ======================================================
* LIVELLO 5: Il dado della fortuna (Random)
* Generiamo uno sconto casuale tra 0 e 100.
* ======================================================
*/
// TODO 1: Genera un numero casuale tra 0 e 1 (Math.random())
let randomBase = 0;
// TODO 2: Trasformalo in un numero tra 0 e 100
// Moltiplica randomBase * 100
let randomCento = 0;
// TODO 3: Rimuovi i decimali per avere un intero (Math.floor)
let scontoFinale = 0;
mostraOutput(5, {
random_puro: randomBase.toFixed(4), // Mostro solo 4 decimali per pulizia
scala_100: randomCento.toFixed(2),
sconto_intero: scontoFinale
});
/**
* ======================================================
* LIVELLO 6: Creazione Card Utente (Template Literals)
* Crea una card HTML usando i template literals (backticks)
* ======================================================
*/
const utente = {
nome: "Mario",
cognome: "Rossi",
email: "mario.rossi@esempio.com",
avatar: "https://randomuser.me/api/portraits/men/75.jpg"
};
// TODO: Crea una card HTML usando i dati dell'utente e i template literals
// Per fare i backticks usa ALT + 96 sulla tastiera
// La card dovrebbe avere questa struttura:
/*
<div class="user-card">
<img src="avatar_url" alt="Avatar" class="user-avatar">
<div class="user-info">
<h3>Nome Cognome</h3>
<p class="user-email">📧 email</p>
</div>
</div>
*/
let cardHTML = null;
mostraOutput(6, {});
let output = document.getElementById('output-6');
output.className = '';
output.innerHTML = cardHTML;
}

View File

@@ -0,0 +1,146 @@
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f0f2f5;
color: #333;
margin: 0 auto;
}
h1 {
text-align: center;
color: #1a73e8;
margin-top: 0px;
}
.controls {
text-align: center;
margin-bottom: 30px;
position: sticky;
top: 0px;
z-index: 100;
background-color: white;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
padding-top: 50px;
}
button {
padding: 12px 24px;
font-size: 16px;
cursor: pointer;
background-color: #1a73e8;
color: white;
border: none;
border-radius: 10px;
margin: 5px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: transform 0.1s;
}
button:hover {
transform: scale(1.05);
}
button:active {
transform: scale(0.95);
}
button#btn-reset {
background-color: #ea4335;
}
.step-card {
background: white;
border-radius: 12px;
padding: 20px;
margin-bottom: 25px;
max-width: 800px;
margin: 0 auto 25px auto;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border-left: 6px solid #1a73e8;
}
.step-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.step-title {
font-weight: bold;
font-size: 1.2em;
color: #1557b0;
}
.step-desc {
font-size: 0.95em;
color: #5f6368;
margin-bottom: 15px;
line-height: 1.5;
}
.output-box {
background: #2d3436;
color: #00c900;
padding: 10px;
font-family: 'Courier New', monospace;
border-radius: 6px;
min-height: 20px;
white-space: pre-wrap;
overflow-x: auto;
position: relative;
}
.output-box.loading::after {
content: "⏳ Attesa server...";
position: absolute;
top: 5px;
right: 5px;
font-size: 0.8em;
color: #e5c07b;
}
.output-box.error {
border: 2px solid #e06c75;
color: #e06c75;
}
.output-box.success {
border-left: 4px solid #98c379;
}
.label {
font-size: 0.8em;
color: #bbbbbb;
margin-bottom: 5px;
display: block;
font-weight: bold;
letter-spacing: 0.5px;
}
.user-card {
background: #f5f5f5;
border-radius: 10px;
padding: 15px;
display: flex;
align-items: center;
gap: 15px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.user-avatar {
width: 100px;
height: 100px;
border-radius: 50%;
object-fit: cover;
}
.user-info {
display: flex;
flex-direction: column;
}
.user-name {
font-weight: bold;
color: #333;
}
.user-email {
font-size: 0.9em;
color: #777;
}