{"elements":[{"id":7011,"title":"Editor WYSIWYG","body":"<section class=\"da-section\">\n  <div class=\"container\">\n    <h2>Editor WYSIWYG Integrato<\/h2>\n    <p class=\"lead\">Creare pagine web senza dover scrivere codice HTML &egrave; uno degli obiettivi del CMS di DressAPI. L&rsquo;editor WYSIWYG integrato offre un ambiente visuale completo per la composizione dei contenuti, con supporto per formattazione avanzata, inserimento di componenti e anteprima in tempo reale.<\/p>\n    <div class=\"text-center my-4\"><img src=\"\/assets\/images\/editor_1.png\" alt=\"Editor WYSIWYG di DressAPI\" class=\"img-fluid rounded shadow\" style=\"max-width: 80%;\"><\/div>\n\n    <h3 class=\"mt-4\">Tre modalit&agrave; di editing<\/h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Modalit&agrave;<\/th><th>Descrizione<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><strong>Work<\/strong><\/td><td>Editing visuale WYSIWYG con toolbar di formattazione<\/td><\/tr>\n          <tr><td><strong>Preview<\/strong><\/td><td>Anteprima con rendering server-side dei componenti<\/td><\/tr>\n          <tr><td><strong>Source<\/strong><\/td><td>Editing HTML diretto del codice sorgente<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n\n    <h3 class=\"mt-5\">Toolbar di formattazione<\/h3>\n    <ul>\n      <li>Grassetto, corsivo, sottolineato, barrato<\/li>\n      <li>Titoli (H1-H6)<\/li>\n      <li>Liste ordinate e non ordinate<\/li>\n      <li>Link e immagini<\/li>\n      <li>Tabelle<\/li>\n      <li>Allineamento testo<\/li>\n      <li>Colori testo e sfondo<\/li>\n    <\/ul>\n\n    <h3 class=\"mt-5\">Componenti drag-and-drop<\/h3>\n    <p>La sidebar dell'editor mostra i componenti disponibili. Si inseriscono nel contenuto tramite drag-and-drop e si configurano con un modal generato dinamicamente.<\/p>\n    <p>I parametri dei componenti vengono serializzati come JSON all'interno del tag <code>&lt;component&gt;<\/code>.<\/p>\n\n    <h3 class=\"mt-5\">Gestione media<\/h3>\n    <ul>\n      <li>Gallery integrata per la selezione di immagini esistenti<\/li>\n      <li>Upload diretto dall'editor<\/li>\n      <li>API dedicata per la gestione dei file<\/li>\n    <\/ul>\n\n    <h3 class=\"mt-5\">Architettura<\/h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>File<\/th><th>Ruolo<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><code>dressapi_editor_scoped.js<\/code><\/td><td>Classe principale WebEditor (~206 KB)<\/td><\/tr>\n          <tr><td><code>dressapi_editor_config.js<\/code><\/td><td>Configurazione e traduzioni 5 lingue<\/td><\/tr>\n          <tr><td><code>dressapi_editor_scoped.css<\/code><\/td><td>Stili scoped (prefisso <code>.dae-*<\/code>)<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n\n    <h3 class=\"mt-5\">Passi per l'integrazione<\/h3>\n    <p>Per includere l'editor nella tua pagina, aggiungi i file CSS e JavaScript nell'ordine corretto:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">HTML - Inclusione CSS e JS<\/div>\n&lt;!-- CSS dell'editor --&gt;\n&lt;link rel=&quot;stylesheet&quot; href=&quot;\/assets-core\/editor\/dressapi_editor_scoped.min.css&quot;&gt;\n\n&lt;!-- JavaScript (l'ordine &egrave; importante) --&gt;\n&lt;script src=&quot;\/assets-core\/editor\/dressapi_editor_config.js&quot;&gt;&lt;\/script&gt;\n&lt;script src=&quot;\/assets-core\/editor\/dressapi_editor_scoped.min.js&quot;&gt;&lt;\/script&gt;\n    <\/div>\n    <p class=\"mt-3\">Il file <code>dressapi_editor_config.js<\/code> deve essere caricato <strong>prima<\/strong> del file principale dell'editor, perch&eacute; contiene le traduzioni e la funzione di configurazione.<\/p>\n\n    <h3 class=\"mt-5\">Opzioni di configurazione<\/h3>\n    <p>L'editor viene inizializzato tramite la funzione <code>getDressApiEditorConfig()<\/code> con le seguenti opzioni:<\/p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Opzione<\/th><th>Tipo<\/th><th>Default<\/th><th>Descrizione<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><code>selector<\/code><\/td><td>string<\/td><td><code>'#content'<\/code><\/td><td>Selettore CSS della textarea da trasformare<\/td><\/tr>\n          <tr><td><code>language<\/code><\/td><td>string<\/td><td><code>'en'<\/code><\/td><td>Lingua dell'interfaccia (en, it, de, fr, es)<\/td><\/tr>\n          <tr><td><code>security_level<\/code><\/td><td>string<\/td><td><code>'balanced'<\/code><\/td><td>Livello di sicurezza: strict, balanced, permissive<\/td><\/tr>\n          <tr><td><code>components_endpoint<\/code><\/td><td>string<\/td><td><code>'\/api-core\/components\/'<\/code><\/td><td>Endpoint API per i componenti<\/td><\/tr>\n          <tr><td><code>rest_endpoint<\/code><\/td><td>string<\/td><td><code>'\/api-core\/gallery\/'<\/code><\/td><td>Endpoint API per la gallery<\/td><\/tr>\n          <tr><td><code>custom_components<\/code><\/td><td>array<\/td><td><code>&#91;]<\/code><\/td><td>Componenti personalizzati aggiuntivi<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">JavaScript - Inizializzazione editor<\/div>\ndocument.addEventListener('DOMContentLoaded', function() {\n    const config = getDressApiEditorConfig({\n        selector: '#content',\n        language: 'it',\n        security_level: 'balanced',\n        components_endpoint: '\/components\/',\n        rest_endpoint: '\/api-core\/gallery\/'\n    });\n\n    const editor = new DressApiEditor(config);\n});\n    <\/div>\n\n    <h3 class=\"mt-5\">Livelli di sicurezza nel dettaglio<\/h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Livello<\/th><th>Descrizione<\/th><th>Cosa permette<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><strong>strict<\/strong><\/td><td>Solo formattazione di base<\/td><td>Grassetto, corsivo, titoli, liste, link. Nessun HTML personalizzato, nessun componente custom.<\/td><\/tr>\n          <tr><td><strong>balanced<\/strong><\/td><td>Default, la maggior parte delle funzionalit&agrave;<\/td><td>Tutti i componenti approvati, tabelle, immagini, video incorporati. HTML limitato senza script.<\/td><\/tr>\n          <tr><td><strong>permissive<\/strong><\/td><td>Tutto l'HTML permesso<\/td><td>Qualsiasi HTML inclusi iframe, embed e HTML personalizzato. Solo per amministratori fidati.<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n\n    <h3 class=\"mt-5\">Traduzioni disponibili<\/h3>\n    <p>L'interfaccia dell'editor &egrave; tradotta in 5 lingue. La lingua si imposta con l'opzione <code>language<\/code>:<\/p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Codice<\/th><th>Lingua<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><code>en<\/code><\/td><td>English<\/td><\/tr>\n          <tr><td><code>it<\/code><\/td><td>Italiano<\/td><\/tr>\n          <tr><td><code>de<\/code><\/td><td>Deutsch<\/td><\/tr>\n          <tr><td><code>fr<\/code><\/td><td>Fran&ccedil;ais<\/td><\/tr>\n          <tr><td><code>es<\/code><\/td><td>Espa&ntilde;ol<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n\n    <h3 class=\"mt-5\">Caricamento componenti da API<\/h3>\n    <p>L'editor carica i componenti disponibili dall'endpoint API configurato. Per il CMS l'endpoint &egrave; <code>\/components\/<\/code>, per le applicazioni client-side &egrave; <code>\/api-core\/components\/<\/code>.<\/p>\n    <p>La richiesta viene effettuata con il parametro <code>action=list<\/code> e il parametro <code>view<\/code> che indica il tema attivo (es. <code>bi5<\/code>, <code>b5<\/code>):<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">URL - Richiesta componenti<\/div>\nGET \/components\/?action=list&amp;view=bi5\n    <\/div>\n    <p class=\"mt-3\">L'API restituisce la lista dei componenti con i loro template, parametri e valori di esempio. L'editor li mostra nella sidebar come blocchi trascinabili.<\/p>\n\n    <h3 class=\"mt-5\">Direttive dei componenti nell'editor<\/h3>\n    <p>I template dei componenti utilizzano direttive speciali per il rendering dinamico:<\/p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Direttiva<\/th><th>Descrizione<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><code>&#91;single]...&#91;\/single]<\/code><\/td><td>Contenuto per un singolo elemento<\/td><\/tr>\n          <tr><td><code>&#91;multiple]...&#91;\/multiple]<\/code><\/td><td>Contenuto per una lista di elementi<\/td><\/tr>\n          <tr><td><code>&#91;empty]...&#91;\/empty]<\/code><\/td><td>Contenuto visualizzato se la lista &egrave; vuota<\/td><\/tr>\n          <tr><td><code>&#91;if-exists(param)]...&#91;\/if-exists]<\/code><\/td><td>Mostra il blocco solo se il parametro esiste<\/td><\/tr>\n          <tr><td><code>&#91;if-not-exists(param)]...&#91;\/if-not-exists]<\/code><\/td><td>Mostra il blocco solo se il parametro non esiste<\/td><\/tr>\n          <tr><td><code>&#91;repeat(param)]...&#91;\/repeat]<\/code><\/td><td>Ripete il blocco per ogni elemento dell'array<\/td><\/tr>\n          <tr><td><code>{{parametro}}<\/code><\/td><td>Inserisce il valore del parametro<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">HTML - Esempio template componente<\/div>\n&lt;!--\nCard Componente\n\n@example {&quot;title&quot;:&quot;Titolo&quot;,&quot;text&quot;:&quot;Descrizione&quot;}\n\n@param string title - Titolo della card\n@param string text - Testo descrittivo\n@param string image - URL immagine (optional)\n--&gt;\n&#91;single]\n  &lt;div class=&quot;card&quot;&gt;\n    &#91;if-exists(image)]&lt;img src=&quot;{{image}}&quot; class=&quot;card-img-top&quot;&gt;&#91;\/if-exists]\n    &lt;div class=&quot;card-body&quot;&gt;\n      &lt;h5&gt;{{title}}&lt;\/h5&gt;\n      &lt;p&gt;{{text}}&lt;\/p&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n&#91;\/single]\n    <\/div>\n\n    <h3 class=\"mt-5\">Metodi API JavaScript<\/h3>\n    <p>L'istanza dell'editor espone i seguenti metodi:<\/p>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Metodo<\/th><th>Descrizione<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td><code>GetContent()<\/code><\/td><td>Restituisce il contenuto HTML dell'editor<\/td><\/tr>\n          <tr><td><code>SetContent(html)<\/code><\/td><td>Imposta il contenuto HTML dell'editor<\/td><\/tr>\n          <tr><td><code>Clear()<\/code><\/td><td>Svuota il contenuto dell'editor<\/td><\/tr>\n          <tr><td><code>Destroy()<\/code><\/td><td>Rimuove l'istanza dell'editor e ripristina la textarea<\/td><\/tr>\n          <tr><td><code>RefreshComponents()<\/code><\/td><td>Ricarica e renderizza tutti i componenti<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">JavaScript - Utilizzo metodi API<\/div>\nconst editor = new DressApiEditor(config);\n\n\/\/ Ottenere il contenuto HTML\nconst html = editor.GetContent();\n\n\/\/ Impostare nuovo contenuto\neditor.SetContent('&lt;div&gt;Nuovo contenuto&lt;\/div&gt;');\n\n\/\/ Svuotare l'editor\neditor.Clear();\n\n\/\/ Aggiornare i componenti dall'API\neditor.RefreshComponents();\n\n\/\/ Distruggere l'editor\neditor.Destroy();\n    <\/div>\n\n    <h3 class=\"mt-5\">Gestori di eventi<\/h3>\n    <p>L'editor emette eventi che puoi intercettare per reagire alle azioni dell'utente:<\/p>\n    <div class=\"da-snippet\">\n      <div class=\"da-snippet-label\">JavaScript - Gestori di eventi<\/div>\n\/\/ Contenuto modificato\neditor.on('change', function(content) {\n    console.log('Contenuto modificato:', content);\n});\n\n\/\/ Componente aggiunto\neditor.on('component:added', function(component) {\n    console.log('Componente aggiunto:', component);\n});\n\n\/\/ Componente rimosso\neditor.on('component:removed', function(component) {\n    console.log('Componente rimosso:', component);\n});\n\n\/\/ Salvataggio\neditor.on('save', function(content) {\n    fetch('\/api\/save', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application\/json' },\n        body: JSON.stringify({ content: content })\n    });\n});\n    <\/div>\n\n    <h3 class=\"mt-5\">Risoluzione problemi<\/h3>\n    <div class=\"table-responsive\">\n      <table class=\"table table-striped\">\n        <thead class=\"table-dark\">\n          <tr><th>Problema<\/th><th>Soluzione<\/th><\/tr>\n        <\/thead>\n        <tbody>\n          <tr><td>I componenti non vengono renderizzati<\/td><td>Verifica che l'endpoint API risponda correttamente: <code>\/components\/?action=list&amp;view=bi5<\/code>. Controlla i permessi della directory components e che i template abbiano il formato corretto.<\/td><\/tr>\n          <tr><td>La toolbar non appare<\/td><td>Verifica che i file CSS e JS siano caricati nell'ordine corretto: prima <code>dressapi_editor_config.js<\/code>, poi <code>dressapi_editor_scoped.min.js<\/code>. Controlla la console del browser per errori.<\/td><\/tr>\n          <tr><td>Stili non applicati correttamente<\/td><td>Usa la versione scoped (<code>dressapi_editor_scoped.*<\/code>) per evitare conflitti con Bootstrap o altri framework CSS.<\/td><\/tr>\n          <tr><td>La gallery non funziona<\/td><td>Verifica che l'API <code>\/api-core\/gallery\/<\/code> risponda e che l'utente sia autenticato. Controlla i permessi della directory <code>public-files\/<\/code>.<\/td><\/tr>\n          <tr><td>L'editor non si carica<\/td><td>Controlla la console del browser per errori JavaScript. Verifica che la textarea con il selettore configurato esista nel DOM al momento dell'inizializzazione.<\/td><\/tr>\n          <tr><td>Componenti personalizzati non visibili<\/td><td>Verifica che il file template sia nella directory corretta: <code>cms\/plugins\/{modulo}\/views\/{tema}\/components\/{nome}\/{nome}.html<\/code>.<\/td><\/tr>\n        <\/tbody>\n      <\/table>\n    <\/div>\n  <\/div>\n<\/section>\n\n<section class=\"da-section text-center\">\n  <a href=\"\/tutorials\" class=\"btn btn-outline-primary\">&larr; Torna ai Tutorial<\/a>\n<\/section>","description":"Editor visuale con drag-and-drop dei componenti","meta_keywords":"","visible":"yes","status":"public","creation_date":"0000-00-00","id__user":1,"priority":0,"groupname":"TUTORIAL"}],"module":"pages","permissions":{"can_read":true},"main_item_title":"title","related_tables":[{"name":"Newsonpage","module":"newsonpage","FK":"id_cmspage","permissions":[]}],"page_info":{"table":"","key":"id","url":"\/pages","url_list":"\/pages","filters":{"id":["=","7011"]},"pagination":{"total_items":23,"page":1,"total_pages":2,"step":1,"items_per_page":20,"url_prev":"\/pages","url_next":"\/pages\/p\/2","url_tmpl":"\/pages\/p\/[[p]]","url_tmpl_with_order":"\/pages\/p\/[[p]]\/ob\/[[ob]]"},"order":{"field":"id","type":"DESC","url_tmpl":"\/pages\/p\/[[p]]"},"module":{"title":"Pages","description":"List of pages","name":"pages"},"current":{"title":"Pages","description":"List of pages","name":"pages","url":"\/tutorials\/editor"}},"components":{"alert":{"alert1":[{"type":"warning","message":"OK COMPONENT!"},{"type":"danger","message":"ERROR COMPONENT!"}]}},"messages":[]}