Widget:Grafico: differenze tra le versioni

Da WikiLectio.
m test
m test
Riga 1: Riga 1:
<div style="padding:8px;border:1px solid #ccc;">
<!-- Widget:Grafico — Chart.js con supporto a 4 serie + punto di equilibrio -->
   Widget attivo: <!--{$id|escape:'html'}-->
<div id="chartwrap_<!--{$id|escape:'html'}-->"
    style="width:<!--{$width|default:600|escape:'html'}-->px;
            height:<!--{$height|default:380|escape:'html'}-->px;">
   <canvas id="canvas_<!--{$id|escape:'html'}-->"
          width="<!--{$width|default:600|escape:'html'}-->"
          height="<!--{$height|default:380|escape:'html'}-->"
          data-id="<!--{$id|escape:'html'}-->"
          data-title="<!--{$title|escape:'html'}-->"
          data-x-title="<!--{$xTitle|default:'Quantità di appartamenti'|escape:'html'}-->"
          data-y-title="<!--{$yTitle|default:'Prezzo dell\'affitto'|escape:'html'}-->"
          data-labels="<!--{$labels|default:'0,2,4,6,8,10'|escape:'html'}-->"
          data-series1-title="<!--{$series1title|escape:'html'}-->"
          data-series1-data="<!--{$series1data|escape:'html'}-->"
          data-series1-type="<!--{$series1type|default:'line'|escape:'html'}-->"
          data-series1-color="<!--{$series1color|escape:'html'}-->"
          data-series2-title="<!--{$series2title|escape:'html'}-->"
          data-series2-data="<!--{$series2data|escape:'html'}-->"
          data-series2-type="<!--{$series2type|default:'line'|escape:'html'}-->"
          data-series2-color="<!--{$series2color|escape:'html'}-->"
          data-series3-title="<!--{$series3title|escape:'html'}-->"
          data-series3-data="<!--{$series3data|escape:'html'}-->"
          data-series3-type="<!--{$series3type|default:'line'|escape:'html'}-->"
          data-series3-color="<!--{$series3color|escape:'html'}-->"
          data-series4-title="<!--{$series4title|escape:'html'}-->"
          data-series4-data="<!--{$series4data|escape:'html'}-->"
          data-series4-type="<!--{$series4type|default:'line'|escape:'html'}-->"
          data-series4-color="<!--{$series4color|escape:'html'}-->"
          data-eqx="<!--{$eqX|escape:'html'}-->"
          data-eqy="<!--{$eqY|escape:'html'}-->"
          data-show-legend="<!--{$showLegend|default:'true'|escape:'html'}-->"
          data-responsive="<!--{$responsive|default:'true'|escape:'html'}-->"
          data-xmin="<!--{$xMin|escape:'html'}-->"
          data-xmax="<!--{$xMax|escape:'html'}-->"
          data-ymin="<!--{$yMin|escape:'html'}-->"
          data-ymax="<!--{$yMax|escape:'html'}-->"
  ></canvas>
</div>
</div>
<!-- Chart.js (CDN) -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
{literal}
<script>
(function(){
  function csvToArray(str){ if(!str) return []; return str.split(',').map(s=>s.trim()); }
  function csvToNum(str){ return csvToArray(str).map(v=>{const n=Number(v); return isNaN(n)?null:n;}); }
  function truthy(s){ return String(s||'').toLowerCase() !== 'false'; }
  function numOrUndef(s){ const n = Number(s); return isNaN(n) ? undefined : n; }
  function buildDataset(title, data, type, color){
    if(!title || !data) return null;
    return {
      label: title,
      data: csvToNum(data),
      type: (type || 'line'),
      fill: false,
      borderColor: color || undefined,
      backgroundColor: color || undefined,
      tension: 0,
      pointRadius: 2
    };
  }
  document.querySelectorAll("canvas[id^='canvas_']").forEach(function(c){
    var ds = c.dataset;
    var labels = csvToArray(ds.labels);
    var datasets = [];
    [['series1Title','series1Data','series1Type','series1Color'],
    ['series2Title','series2Data','series2Type','series2Color'],
    ['series3Title','series3Data','series3Type','series3Color'],
    ['series4Title','series4Data','series4Type','series4Color']
    ].forEach(function(keys){
      var d = buildDataset(ds[keys[0].toLowerCase()], ds[keys[1].toLowerCase()], ds[keys[2].toLowerCase()], ds[keys[3].toLowerCase()]);
      if(d) datasets.push(d);
    });
    // Punto di equilibrio opzionale
    var eqx = Number(ds.eqx), eqy = Number(ds.eqy);
    if(!isNaN(eqx) && !isNaN(eqy)){
      datasets.push({
        label: 'Equilibrio',
        type: 'scatter',
        data: [{x:eqx, y:eqy}],
        showLine: false,
        pointRadius: 5,
        pointHoverRadius: 6,
        borderColor: "#000000",
        backgroundColor: "#000000"
      });
    }
    var numericLabels = labels.every(l => !isNaN(Number(l)));
    var cfg = {
      type: 'line',
      data: { labels: labels, datasets: datasets },
      options: {
        responsive: truthy(ds.responsive),
        maintainAspectRatio: false,
        plugins: {
          title: { display: !!ds.title, text: ds.title },
          legend: { display: truthy(ds.showLegend) },
          tooltip: { enabled: true }
        },
        elements: { line: { borderWidth: 2 } },
        scales: {
          x: numericLabels ? {
            type: 'linear',
            title: { display: true, text: ds.xTitle || 'Quantità di appartamenti' },
            min: numOrUndef(ds.xmin), max: numOrUndef(ds.xmax)
          } : {
            type: 'category',
            title: { display: true, text: ds.xTitle || 'Quantità di appartamenti' }
          },
          y: {
            title: { display: true, text: ds.yTitle || "Prezzo dell'affitto" },
            min: numOrUndef(ds.ymin), max: numOrUndef(ds.ymax),
            beginAtZero: false
          }
        }
      }
    };
    new Chart(c.getContext('2d'), cfg);
  });
})();
</script>
{/literal}

Versione delle 16:25, 19 set 2025

 <canvas id="canvas_"
         width=""
         height=""
         data-id=""
         data-title=""
         data-x-title=""
         data-y-title=""
         data-labels=""
         data-series1-title=""
         data-series1-data=""
         data-series1-type=""
         data-series1-color=""
         data-series2-title=""
         data-series2-data=""
         data-series2-type=""
         data-series2-color=""
         data-series3-title=""
         data-series3-data=""
         data-series3-type=""
         data-series3-color=""
         data-series4-title=""
         data-series4-data=""
         data-series4-type=""
         data-series4-color=""
         data-eqx=""
         data-eqy=""
         data-show-legend=""
         data-responsive=""
         data-xmin=""
         data-xmax=""
         data-ymin=""
         data-ymax=""
 ></canvas>

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

{literal} <script> (function(){

 function csvToArray(str){ if(!str) return []; return str.split(',').map(s=>s.trim()); }
 function csvToNum(str){ return csvToArray(str).map(v=>{const n=Number(v); return isNaN(n)?null:n;}); }
 function truthy(s){ return String(s||).toLowerCase() !== 'false'; }
 function numOrUndef(s){ const n = Number(s); return isNaN(n) ? undefined : n; }
 function buildDataset(title, data, type, color){
   if(!title || !data) return null;
   return {
     label: title,
     data: csvToNum(data),
     type: (type || 'line'),
     fill: false,
     borderColor: color || undefined,
     backgroundColor: color || undefined,
     tension: 0,
     pointRadius: 2
   };
 }
 document.querySelectorAll("canvas[id^='canvas_']").forEach(function(c){
   var ds = c.dataset;
   var labels = csvToArray(ds.labels);
   var datasets = [];
   [['series1Title','series1Data','series1Type','series1Color'],
    ['series2Title','series2Data','series2Type','series2Color'],
    ['series3Title','series3Data','series3Type','series3Color'],
    ['series4Title','series4Data','series4Type','series4Color']
   ].forEach(function(keys){
     var d = buildDataset(ds[keys[0].toLowerCase()], ds[keys[1].toLowerCase()], ds[keys[2].toLowerCase()], ds[keys[3].toLowerCase()]);
     if(d) datasets.push(d);
   });
   // Punto di equilibrio opzionale
   var eqx = Number(ds.eqx), eqy = Number(ds.eqy);
   if(!isNaN(eqx) && !isNaN(eqy)){
     datasets.push({
       label: 'Equilibrio',
       type: 'scatter',
       data: [{x:eqx, y:eqy}],
       showLine: false,
       pointRadius: 5,
       pointHoverRadius: 6,
       borderColor: "#000000",
       backgroundColor: "#000000"
     });
   }
   var numericLabels = labels.every(l => !isNaN(Number(l)));
   var cfg = {
     type: 'line',
     data: { labels: labels, datasets: datasets },
     options: {
       responsive: truthy(ds.responsive),
       maintainAspectRatio: false,
       plugins: {
         title: { display: !!ds.title, text: ds.title },
         legend: { display: truthy(ds.showLegend) },
         tooltip: { enabled: true }
       },
       elements: { line: { borderWidth: 2 } },
       scales: {
         x: numericLabels ? {
           type: 'linear',
           title: { display: true, text: ds.xTitle || 'Quantità di appartamenti' },
           min: numOrUndef(ds.xmin), max: numOrUndef(ds.xmax)
         } : {
           type: 'category',
           title: { display: true, text: ds.xTitle || 'Quantità di appartamenti' }
         },
         y: {
           title: { display: true, text: ds.yTitle || "Prezzo dell'affitto" },
           min: numOrUndef(ds.ymin), max: numOrUndef(ds.ymax),
           beginAtZero: false
         }
       }
     }
   };
   new Chart(c.getContext('2d'), cfg);
 });

})(); </script> {/literal}