Widget:Grafico: differenze tra le versioni

Da WikiLectio.
m test
Etichette: Sostituito Annullato
m test
Etichette: Ripristino manuale Annullato
Riga 1: Riga 1:
<div style="padding:8px;border:1px solid #ccc;">
<!-- Widget:Grafico — Grafici domanda/offerta con Chart.js, fino a 4 serie + punto equilibrio opzionale -->
   Widget attivo: {{{id}}}
<div id="chart_{{{id}}}" style="width:{{{width|600}}}px;height:{{{height|380}}}px;">
   <canvas id="canvas_{{{id}}}" width="{{{width|600}}}" height="{{{height|380}}}"></canvas>
</div>
</div>
<!-- Chart.js (CDN) -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
/* ===== Helpers ===== */
function parseCSVNumbers(str){
  if(!str) return [];
  return str.split(',').map(s=>{
    const n = Number(s.trim());
    return isNaN(n) ? null : n;
  });
}
function parseCSVStrings(str){
  if(!str) return [];
  return str.split(',').map(s=>s.trim());
}
function colorOrNull(s){ return (s && s.trim()) ? s.trim() : null; }
function numOrUndef(x){ var n = Number(x); return isNaN(n) ? undefined : n; }
/* ===== Costruzione grafico ===== */
(function(){
  var id = "{{{id}}}";
  var canvas = document.getElementById("canvas_{{{id}}}");
  if(!canvas){ return; }
  var ctx = canvas.getContext("2d");
  // Parametri base
  var labels = parseCSVStrings("{{{labels|0,2,4,6,8,10}}}");
  var chartTitle = "{{{title|}}}";
  var xTitle = "{{{xTitle|Quantità di appartamenti}}}";
  var yTitle = "{{{yTitle|Prezzo dell'affitto}}}";
  var showLegend = "{{{showLegend|true}}}".toLowerCase() !== "false";
  var responsive = "{{{responsive|true}}}".toLowerCase() !== "false";
  // Limiti assi opzionali
  var yMin = numOrUndef("{{{yMin|}}}");
  var yMax = numOrUndef("{{{yMax|}}}");
  var xMin = numOrUndef("{{{xMin|}}}");
  var xMax = numOrUndef("{{{xMax|}}}");
  // Serie 1..4
  var series = [
    {t:"{{{series1title|}}}", d:"{{{series1data|}}}", ty:"{{{series1type|line}}}", c:"{{{series1color|}}}"},
    {t:"{{{series2title|}}}", d:"{{{series2data|}}}", ty:"{{{series2type|line}}}", c:"{{{series2color|}}}"},
    {t:"{{{series3title|}}}", d:"{{{series3data|}}}", ty:"{{{series3type|line}}}", c:"{{{series3color|}}}"},
    {t:"{{{series4title|}}}", d:"{{{series4data|}}}", ty:"{{{series4type|line}}}", c:"{{{series4color|}}}"}
  ];
  var datasets = [];
  series.forEach(function(s){
    if(!s.t || !s.d) return;
    var dataArr = parseCSVNumbers(s.d);
    datasets.push({
      label: s.t,
      data: dataArr,
      type: (s.ty && s.ty.trim()) || 'line',
      fill: false,
      borderColor: colorOrNull(s.c),
      backgroundColor: colorOrNull(s.c),
      tension: 0,
      pointRadius: 2
    });
  });
  // Punto di equilibrio opzionale (eqX, eqY)
  var eqX = numOrUndef("{{{eqX|}}}");
  var eqY = numOrUndef("{{{eqY|}}}");
  if(eqX !== undefined && eqY !== undefined){
    datasets.push({
      label: "Equilibrio",
      type: "scatter",
      data: [{x:eqX, y:eqY}],
      showLine: false,
      pointRadius: 5,
      pointHoverRadius: 6,
      borderColor: "#000000",
      backgroundColor: "#000000"
    });
  }
  // Se le labels sono numeriche, usa asse X lineare
  var numericLabels = labels.every(function(l){ return !isNaN(Number(l)); });
  var dataConfig = { labels: labels, datasets: datasets };
  new Chart(ctx, {
    type: 'line',
    data: dataConfig,
    options: {
      responsive: responsive,
      maintainAspectRatio: false,
      plugins: {
        title: { display: !!chartTitle, text: chartTitle },
        legend: { display: showLegend },
        tooltip: { enabled: true }
      },
      elements: { line: { borderWidth: 2 } },
      scales: {
        x: numericLabels ? {
          type: 'linear',
          title: { display: true, text: xTitle },
          min: xMin, max: xMax
        } : {
          type: 'category',
          title: { display: true, text: xTitle }
        },
        y: {
          title: { display: true, text: yTitle },
          min: yMin, max: yMax,
          beginAtZero: false
        }
      }
    }
  });
})();
</script>
<!--
Documentazione rapida parametri:
Obbligatorio: id
Opzionali: width, height, title, xTitle, yTitle, showLegend, responsive, xMin, xMax, yMin, yMax
labels = CSV (es. 0,2,4,6,8,10)
Fino a 4 serie:
seriesNtitle, seriesNdata (CSV), seriesNtype (line|bar), seriesNcolor (es. #d62728)
Punto equilibrio opzionale:
eqX=numero, eqY=numero
Esempio minimo:
{{#widget:Grafico
| id=test
| labels=0,2,4,6
| series1title=Domanda
| series1data=10,7,4,1
| series2title=Offerta
| series2data=0,3,6,9
}}
-->

Versione delle 15:06, 19 set 2025

 <canvas id="canvas_{{{id}}}" width="600" height="380"></canvas>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<script> /* ===== Helpers ===== */ function parseCSVNumbers(str){

 if(!str) return [];
 return str.split(',').map(s=>{
   const n = Number(s.trim());
   return isNaN(n) ? null : n;
 });

} function parseCSVStrings(str){

 if(!str) return [];
 return str.split(',').map(s=>s.trim());

} function colorOrNull(s){ return (s && s.trim()) ? s.trim() : null; } function numOrUndef(x){ var n = Number(x); return isNaN(n) ? undefined : n; }

/* ===== Costruzione grafico ===== */ (function(){

 var id = "{{{id}}}";
 var canvas = document.getElementById("canvas_{{{id}}}");
 if(!canvas){ return; }
 var ctx = canvas.getContext("2d");
 // Parametri base
 var labels = parseCSVStrings("0,2,4,6,8,10");
 var chartTitle = "";
 var xTitle = "Quantità di appartamenti";
 var yTitle = "Prezzo dell'affitto";
 var showLegend = "true".toLowerCase() !== "false";
 var responsive = "true".toLowerCase() !== "false";
 // Limiti assi opzionali
 var yMin = numOrUndef("");
 var yMax = numOrUndef("");
 var xMin = numOrUndef("");
 var xMax = numOrUndef("");
 // Serie 1..4
 var series = [
   {t:"", d:"", ty:"line", c:""},
   {t:"", d:"", ty:"line", c:""},
   {t:"", d:"", ty:"line", c:""},
   {t:"", d:"", ty:"line", c:""}
 ];
 var datasets = [];
 series.forEach(function(s){
   if(!s.t || !s.d) return;
   var dataArr = parseCSVNumbers(s.d);
   datasets.push({
     label: s.t,
     data: dataArr,
     type: (s.ty && s.ty.trim()) || 'line',
     fill: false,
     borderColor: colorOrNull(s.c),
     backgroundColor: colorOrNull(s.c),
     tension: 0,
     pointRadius: 2
   });
 });
 // Punto di equilibrio opzionale (eqX, eqY)
 var eqX = numOrUndef("");
 var eqY = numOrUndef("");
 if(eqX !== undefined && eqY !== undefined){
   datasets.push({
     label: "Equilibrio",
     type: "scatter",
     data: [{x:eqX, y:eqY}],
     showLine: false,
     pointRadius: 5,
     pointHoverRadius: 6,
     borderColor: "#000000",
     backgroundColor: "#000000"
   });
 }
 // Se le labels sono numeriche, usa asse X lineare
 var numericLabels = labels.every(function(l){ return !isNaN(Number(l)); });
 var dataConfig = { labels: labels, datasets: datasets };
 new Chart(ctx, {
   type: 'line',
   data: dataConfig,
   options: {
     responsive: responsive,
     maintainAspectRatio: false,
     plugins: {
       title: { display: !!chartTitle, text: chartTitle },
       legend: { display: showLegend },
       tooltip: { enabled: true }
     },
     elements: { line: { borderWidth: 2 } },
     scales: {
       x: numericLabels ? {
         type: 'linear',
         title: { display: true, text: xTitle },
         min: xMin, max: xMax
       } : {
         type: 'category',
         title: { display: true, text: xTitle }
       },
       y: {
         title: { display: true, text: yTitle },
         min: yMin, max: yMax,
         beginAtZero: false
       }
     }
   }
 });

})(); </script>