MediaWiki:Gadget-course.js
Pagina dell'interfaccia di MediaWiki
Altre azioni
Nota: dopo aver pubblicato, potrebbe essere necessario pulire la cache del proprio browser per vedere i cambiamenti.
- Firefox / Safari: tieni premuto il tasto delle maiuscole Shift e fai clic su Ricarica, oppure premi Ctrl-F5 o Ctrl-R (⌘-R su Mac)
- Google Chrome: premi Ctrl-Shift-R (⌘-Shift-R su un Mac)
- Edge: tieni premuto il tasto Ctrl e fai clic su Aggiorna, oppure premi Ctrl-F5.
/* Gadget "course": rende interattivi blocchi MakeCode, quiz e griglie LED.
Port di assets/blocks.js + assets/quiz.js + assets/led-grid.js
per MediaWiki. Scoped: agisce solo sugli elementi con le classi attese.
Tecnologia: legge la classe blk-<tech> sul blocco per scegliere la palette;
fallback: classe course-<tech> sul wrapper. */
(function () {
"use strict";
var PALETTES = {
microbit: {
basic: "#1e90ff", // Base
input: "#d400d4", // Input
music: "#e63022", // Musica
led: "#5c2d91", // Led
radio: "#e3008c", // Radio
loops: "#00aa00", // Cicli
logic: "#00a4a6", // Logica
variables: "#dc143c", // Variabili
math: "#9400d3", // Matematica
game: "#007a4b", // Gioco
pin: "#b22222", // Pin
images: "#b8860b", // Immagini
text: "#b8860b", // Testo (stringhe)
serial: "#002050", // Seriale
control: "#333333", // Controllo
functions: "#3455db", // Funzioni
arrays: "#e65722", // Array (elenchi)
bluetooth: "#0082fb" // Bluetooth (non fornito, valore indicativo)
}
};
var FONT = "700 13px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif";
var H = 26, PAD = 9, uid = 0;
function measure(text) {
try {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
if (!ctx) throw new Error("no canvas");
ctx.font = FONT;
return ctx.measureText(text).width;
} catch (e) {
return text.length * 7.5;
}
}
function escapeHtml(s) {
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
}
function classList(el) {
return (el.className || "").split(/\s+/).filter(Boolean);
}
function kindOf(el) {
var c = classList(el);
if (c.indexOf("blk-hat") >= 0) return "hat";
if (c.indexOf("blk-val") >= 0) return "val";
if (c.indexOf("blk-bool") >= 0) return "bool";
return "stmt";
}
function techOf(el, root) {
var c = classList(el);
var tech = null;
for (var key in PALETTES) {
if (c.indexOf("blk-" + key) >= 0) tech = key;
}
if (!tech) {
var w = root && root.className || document.body.className || "";
for (var k2 in PALETTES) {
if (w.indexOf("course-" + k2) >= 0) tech = k2;
}
}
return tech || Object.keys(PALETTES)[0];
}
function colorOf(el, root) {
var palette = PALETTES[techOf(el, root)];
var c = classList(el);
for (var key in palette) {
if (c.indexOf("blk-" + key) >= 0) return palette[key];
}
return palette.basic;
}
function build(text, kind, color) {
var tw = measure(text);
var W = Math.round(tw + PAD * 2);
var id = "blksvg" + (++uid);
var br = 5, nr = 5, vbX = 0, vbY = -br, vbW = W, vbH = H + br;
var shape = "", maskCircle = "";
if (kind === "stmt") {
shape = '<rect x="0" y="0" width="' + W + '" height="' + H + '" rx="4" fill="' + color + '"/>' +
'<circle cx="8" cy="0" r="' + br + '" fill="' + color + '"/>';
maskCircle = '<circle cx="8" cy="' + H + '" r="' + nr + '" fill="#000"/>';
} else if (kind === "hat") {
vbY = 0; vbH = H + 6;
shape = '<rect x="0" y="0" width="' + W + '" height="' + H + '" rx="8" fill="' + color + '"/>' +
'<circle cx="8" cy="0" r="' + br + '" fill="' + color + '"/>';
maskCircle = '<circle cx="8" cy="' + H + '" r="' + nr + '" fill="#000"/>';
} else if (kind === "val") {
vbX = -6; vbW = W + 6;
shape = '<rect x="0" y="0" width="' + W + '" height="' + H + '" rx="' + H / 2 + '" fill="' + color + '"/>' +
'<circle cx="0" cy="' + H / 2 + '" r="6" fill="' + color + '"/>';
maskCircle = '<circle cx="' + W + '" cy="' + H / 2 + '" r="6" fill="#000"/>';
} else {
vbX = -6; vbW = W + 12;
shape = '<path d="M0 ' + H / 2 + ' L8 0 L' + (W - 8) + ' 0 L' + W + ' ' + H / 2 +
' L' + (W - 8) + ' ' + H + ' L8 ' + H + ' Z" fill="' + color + '"/>' +
'<circle cx="0" cy="' + H / 2 + '" r="5" fill="' + color + '"/>';
maskCircle = '<circle cx="' + W + '" cy="' + H / 2 + '" r="5" fill="#000"/>';
}
return '<svg class="blk-svg" viewBox="' + vbX + " " + vbY + " " + vbW + " " + vbH +
'" width="' + vbW + '" height="' + vbH + '" role="img" aria-label="' + escapeHtml(text) + '">' +
'<defs><mask id="' + id + '">' +
'<rect x="-8" y="-8" width="' + (vbW + 16) + '" height="' + (vbH + 16) + '" fill="#fff"/>' +
maskCircle + "</mask></defs>" +
'<g mask="url(#' + id + ')">' + shape + "</g>" +
'<text x="' + W / 2 + '" y="' + H / 2 + '" dominant-baseline="central" text-anchor="middle" ' +
'fill="#fff" font-family="-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif" ' +
'font-size="13" font-weight="700">' + escapeHtml(text) + "</text></svg>";
}
function upgradeBlks(root) {
root.querySelectorAll(".blk").forEach(function (el) {
if (el.querySelector("svg")) return;
var text = (el.textContent || "").replace(/\s+/g, " ").trim();
if (!text) return;
var svg = build(text, kindOf(el), colorOf(el, root));
el.innerHTML = svg;
el.classList.add("blk-upgraded");
});
}
function wireQuiz(root) {
root.querySelectorAll(".quiz-q").forEach(function (q) {
if (q.getAttribute("data-bound")) return;
q.setAttribute("data-bound", "1");
var answer = q.getAttribute("data-answer");
var okMsg = q.getAttribute("data-ok") || "Sì! Esatto. 👏";
var retryMsg = q.getAttribute("data-retry") || "Non ancora, riprova!";
var feedback = q.querySelector(".quiz-feedback");
function answerPick(btn) {
var correct = btn.getAttribute("data-opt") === answer;
btn.disabled = true;
if (correct) {
btn.classList.add("correct");
q.querySelectorAll(".quiz-btn").forEach(function (b) { b.disabled = true; });
q.classList.add("answered");
if (feedback) { feedback.textContent = okMsg; feedback.className = "quiz-feedback ok"; }
} else {
btn.classList.add("wrong");
if (feedback) { feedback.textContent = retryMsg; feedback.className = "quiz-feedback no"; }
}
}
q.querySelectorAll(".quiz-btn").forEach(function (btn) {
btn.addEventListener("click", function () { answerPick(btn); });
btn.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); answerPick(btn); }
});
});
});
}
function renderGrids(root) {
root.querySelectorAll(".ledgrid[data-leds]").forEach(function (grid) {
if (grid.querySelector(".led")) return;
var pattern = (grid.getAttribute("data-leds") || "").replace(/[\/\s]+/g, "");
for (var i = 0; i < 25; i++) {
var led = document.createElement("span");
led.className = "led" + (pattern[i] === "#" ? " on" : "");
grid.appendChild(led);
}
});
}
function init(root) {
var target = root || document;
upgradeBlks(target);
wireQuiz(target);
renderGrids(target);
}
window.course = { init: init };
if (typeof mw !== "undefined" && mw.hook) {
mw.hook("wikipage.content").add(function ($content) {
init(($content && $content[0]) || document);
});
} else {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", function () { init(document); });
} else {
init(document);
}
}
})();