|
|
| (23 versioni intermedie di uno stesso utente non sono mostrate) |
| Riga 1: |
Riga 1: |
| <includeonly> | | <includeonly> |
| <div id="chartwrap_<!--{$id|escape:'html'}-->" | | <div id="chartwrap_<!--{$id}-->" |
| style="width:<!--{$width|default:600|escape:'html'}-->px;height:<!--{$height|default:380|escape:'html'}-->px;"> | | style="width:<!--{$width|default:600}-->px;height:<!--{$height|default:380}-->px;"> |
| <canvas id="canvas_<!--{$id|escape:'html'}-->" | | <canvas id="canvas_<!--{$id}-->" |
| width="<!--{$width|default:600|escape:'html'}-->" | | width="<!--{$width|default:600}-->" |
| height="<!--{$height|default:380|escape:'html'}-->" | | height="<!--{$height|default:380}-->"></canvas> |
| 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 id="chartmsg_<!--{$id|escape:'html'}-->" style="font-size:12px;color:#a00;margin-top:4px;"></div>
| |
| </div>
| |
|
| |
|
| <!-- Chart.js (CDN) --> | | <!-- Config INI dentro <pre hidden> --> |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | | <pre id="cfg_<!--{$id}-->" hidden> |
| | id=<!--{$id}--> |
| | title=<!--{$title}--> |
| | xTitle=<!--{$xTitle}--> |
| | yTitle=<!--{$yTitle}--> |
| | labels=<!--{$labels}--> |
|
| |
|
| | series1title=<!--{$series1title}--> |
| | series1data=<!--{$series1data}--> |
| | series1type=<!--{$series1type}--> |
| | series1color=<!--{$series1color}--> |
|
| |
|
| <script> | | series2title=<!--{$series2title}--> |
| (function(){
| | series2data=<!--{$series2data}--> |
| function csvToArray(str){ if(!str) return []; return str.split(',').map(s=>s.trim()); }
| | series2type=<!--{$series2type}--> |
| function csvToNum(str){ return csvToArray(str).map(v=>{const n=Number(v); return isNaN(n)?null:n;}); }
| | series2color=<!--{$series2color}--> |
| function truthy(s){ return String(s||'').toLowerCase() !== 'false'; }
| |
| function numOrUndef(s){ const n = Number(s); return isNaN(n) ? undefined : n; }
| |
|
| |
|
| var id = document.currentScript.previousElementSibling.previousElementSibling.id.replace('canvas_',''); // robusto
| | series3title=<!--{$series3title}--> |
| var c = document.getElementById("canvas_" + id);
| | series3data=<!--{$series3data}--> |
| var msg = document.getElementById("chartmsg_" + id);
| | series3type=<!--{$series3type}--> |
| | series3color=<!--{$series3color}--> |
|
| |
|
| if(!c){ if(msg) msg.textContent = "Canvas non trovato (id="+id+")"; return; }
| | series4title=<!--{$series4title}--> |
| if(typeof Chart === "undefined"){ if(msg) msg.textContent = "Chart.js non caricato (CDN bloccato?)"; return; }
| | series4data=<!--{$series4data}--> |
| | series4type=<!--{$series4type}--> |
| | series4color=<!--{$series4color}--> |
|
| |
|
| try {
| | eqX=<!--{$eqX}--> |
| var ds = c.dataset;
| | eqY=<!--{$eqY}--> |
| var labels = csvToArray(ds.labels);
| | showLegend=<!--{$showLegend}--> |
| | | responsive=<!--{$responsive}--> |
| var seriesDefs = [
| | xMin=<!--{$xMin}--> |
| { t: ds.series1Title, d: ds.series1Data, ty: ds.series1Type, c: ds.series1Color },
| | xMax=<!--{$xMax}--> |
| { t: ds.series2Title, d: ds.series2Data, ty: ds.series2Type, c: ds.series2Color },
| | yMin=<!--{$yMin}--> |
| { t: ds.series3Title, d: ds.series3Data, ty: ds.series3Type, c: ds.series3Color },
| | yMax=<!--{$yMax}--> |
| { t: ds.series4Title, d: ds.series4Data, ty: ds.series4Type, c: ds.series4Color }
| | </pre> |
| ];
| |
| | |
| var datasets = [];
| |
| seriesDefs.forEach(function(s){
| |
| if(s.t && s.d){
| |
| datasets.push({
| |
| label: s.t,
| |
| data: csvToNum(s.d),
| |
| type: (s.ty || 'line'),
| |
| fill: false,
| |
| borderColor: s.c || undefined,
| |
| backgroundColor: s.c || undefined,
| |
| tension: 0,
| |
| pointRadius: 2
| |
| });
| |
| }
| |
| });
| |
| | |
| 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: '#000', backgroundColor: '#000'
| |
| });
| |
| }
| |
| | |
| var numericLabels = labels.every(function(l){ return !isNaN(Number(l)); });
| |
| | |
| new Chart(c.getContext('2d'), {
| |
| type: 'line',
| |
| data: { labels: labels, datasets: datasets },
| |
| options: {
| |
| responsive: (ds.responsive||'true').toLowerCase() !== 'false',
| |
| maintainAspectRatio: false,
| |
| plugins: {
| |
| title: { display: !!ds.title, text: ds.title },
| |
| legend: { display: (ds.showLegend||'true').toLowerCase() !== 'false' },
| |
| tooltip: { enabled: true }
| |
| },
| |
| elements: { line: { borderWidth: 2 } },
| |
| scales: {
| |
| x: numericLabels ? {
| |
| type: 'linear',
| |
| title: { display: true, text: ds.xTitle || 'Quantità di appartamenti' },
| |
| min: Number.isNaN(Number(ds.xmin)) ? undefined : Number(ds.xmin),
| |
| max: Number.isNaN(Number(ds.xmax)) ? undefined : Number(ds.xmax)
| |
| } : {
| |
| type: 'category',
| |
| title: { display: true, text: ds.xTitle || 'Quantità di appartamenti' }
| |
| },
| |
| y: {
| |
| title: { display: true, text: ds.yTitle || "Prezzo dell'affitto" },
| |
| min: Number.isNaN(Number(ds.ymin)) ? undefined : Number(ds.ymin),
| |
| max: Number.isNaN(Number(ds.ymax)) ? undefined : Number(ds.ymax),
| |
| beginAtZero: false
| |
| }
| |
| }
| |
| }
| |
| });
| |
| | |
| if (msg) msg.textContent = "";
| |
| } catch(e){ | |
| if (msg) msg.textContent = "Errore rendering: " + (e && e.message ? e.message : e);
| |
| console.error("[Widget:Grafico] errore:", e);
| |
| }
| |
| })();
| |
| </script> | |
|
| |
|
| | <!-- opzionale: area debug tenuta nascosta --> |
| | <pre id="debug_<!--{$id}-->" hidden></pre> |
| | </div> |
|
| |
|
| <!-- | | <script src="/resources/chart.umd.js" defer></script> |
| Se il tuo hosting blocca il CDN, scarica Chart.js (chart.umd.js) e servilo in locale:
| | <script src="/resources/widget-grafico.js" defer></script> |
| 1) carica /resources/chart.umd.js
| |
| 2) sostituisci la riga del CDN con:
| |
| <script src="/resources/chart.umd.js"></script>
| |
| -->
| |
| </includeonly> | | </includeonly> |