/
appunti.js
5 lines (5 loc) · 98.7 KB
/
appunti.js
1
2
3
4
5
var categorie, appunti;
function caricaDaAppuntiJS() {
categorie = {"*":"*","html":"HTML","css":"CSS","bootstrap":"Bootstrap","js":"JavaScript","javascript":"JavaScript","jq":"JQuery","$":"JQuery","jquery":"JQuery","ng":"Angular","angular":"Angular","php":"PHP","sql":"SQL","oop":"OOP","java":"Java","javafx":"JavaFX","cs":"C#","c#":"C#","git":"Git","gnulinux":"GNU-Linux","gnu-linux":"GNU-Linux","linux":"GNU-Linux","netbeans":"NetBeans","maven":"Maven","mvn":"Maven","tdd":"TDD","cc":"CleanCode","cleancode":"CleanCode"}
appunti = {"JavaScript":[[["console","messaggio","debug"],"<mark>console.log(stringa1, stringa2, stringaN);</mark>"],[["alert","avviso","messaggio"],"<mark>window.alert(stringa);</mark>"]],"PHP":[[["echo","stampa","stringa"],"Stampa una stringa nella pagina in uscita:<br><mark>echo('stringa');</mark><br><br>oppure:<br><mark>echo 'stringa';</mark>"],[["autoload","class","spl","register"],"<mark>spl_autoload_register()</mark> permette di caricare automaticamente tutte le classi che vengono usate con la sintassi \"new Class()\". Così, non serve specificare ogni volta \"require a; require b; ...\", basta specificare una sola volta \"require '__autoload.php';\" (questo file speciale solitamente viene scritto con due underscore __ all'inizio).<br><br>N.B. Convenzione da rispettare: ciascuna classe deve stare in un singolo file ed il file deve avere lo stesso nome della classe.<br><br><h3>File: __autoload.php</h3><mark><?php<br>spl_autoload_register(function($nome_classe) {<br> // Convenzione: un file per ogni classe, e file con stesso nome della classe<br> $path = $_SERVER['DOCUMENT_ROOT'] . '/class/' . $nome_classe . '.php';<br> require $path;<br>});</mark><br><br><h3>File: esempio.php</h3><mark><?php<br>require '__autoload.php';<br><br>$esempio = new Esempio();<br>$istanza = new ClasseAutomaticamenteInclusa();<br>$unAltro = new NonServeIncludermi();</mark>"],[["filter","input","get","post"],"I parametri tramite GET o POST conviene prenderli con filter, perché la funzione esegue alcuni controlli di sicurezza in più rispetto al recuperare i dati grezzi.<br><br><mark>$nomePagina = filter_input(INPUT_GET, 'nomePagina');<br>$idUtente = filter_input(INPUT_POST, 'idUtente');</mark><br>"],[["costanti"],"Le costanti è convenzione scriverle tutte in maiuscolo.<br><br><mark>define('PI_GRECO', 3.14);</mark><br><br>Esempio d'uso:<br><mark>$circonferenza = $raggio * 2 * PI_GRECO;</mark><br><br>"],[["array","semplice","array","associativo"],"<mark>$frutta = array('mela', 'pera', 'banana');</mark><br><br>$frutta[0]<br>$frutta[1]<br>$frutta[2]<br><br><mark>$coloriFrutta = array(<br> 'mela' => 'rossa',<br> 'pera' => 'verde',<br> 'banana' => 'gialla'<br>);</mark><br><br>$coloriFrutta['mela']"],[["pdo","istanziazione","parametri","database"],"- <strike>mysql_connect</strike> (deprecato)<br>- <mark>mysql</mark> (più vecchio)<br>- <mark>mysqli </mark>(i sta per improved, offre approccio object oriented e prepared statement)<br>- <mark>PDO</mark> (PHP Database Object) (più recente)<br><br><h2>PDO</h2>È una classe fornita da PHP (modulo da abilitare in php.ini con scelta di driver per mysql o altro), va instanziata:<br><br><mark>$pdo = new PDO('mysql:host=localhost;dbname=nome_database;', 'root', 'password', []);</mark><br>Se serve specificarlo, in coda a dbname si può aggiungere: <mark>charset=utf8;</mark><br><br>I parametri è bene averli come costanti in un file config.php da includere:<br><mark>$pdo = new PDO('mysql:host=' .DB_HOST. ';dbname=' .DB_NAME, DB_USER, DB_PASSWORD, []);</mark><br><br>Per controllare ogni errore, dopo l'istanziazione, impostare:<br><mark>$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);</mark><br><br><br>"],[["preparare","twig"],"<a href=\"https://twig.symfony.com/doc/2.x/intro.html#installation\" target=\"_blank\">Twig</a> è un componente di Symfony 2 ed è un motore di template. Si installa tramite composer:<br><mark>composer require \"twig/twig:^2.0\"</mark><br><br>Per usare le dipendenze di composer, serve includerle nel nostro progetto con l'autoloader di composer:<br><mark>require_once '/vendor/autoload.php';</mark><br><br>Conviene gestire Twig tramite una classe View:<br><mark><?php<br>class View<br>{<br> private $twig;<br><br> public function __construct() {<br> $loader = new \\Twig\\Loader\\FilesystemLoader('view');<br> $this->twig = new \\Twig\\Environment($loader, [<br> 'cache' => 'view/cache',<br> ]);<br> $this->twig->addGlobal('site_url', SITE_URL);<br> }<br><br> public function render($templatePath, $data = []) {<br> return $this->twig->render($templatePath, $data);<br> }<br>}</mark><br><br>Per usare Twig tramite View:<br><mark>$view = new View();<br>echo $view->render($paginaTwig, ['titolo_esempio' => 'Pagina di prova']);</mark><br><br>N.B.<br>Non dimenticare <b>echo</b>! altrimenti non si vedrà nulla e neanche compariranno errori per capire.<br><br>"],[["attivare","notifiche","errori","query"],"Di default, soprattutto su Linux, le notifiche sulle query sql sono spente.<br>Per attivare tutti i messaggi specificare questo attributo:<br><mark>$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);</mark><br><br>"],[["oggetto","istanza","attributi","privati","json"],"Se vogiamo convertire un oggetto in formato json, ma questo ha gli attributi privati, occorre implementare l'interfaccia <mark>JsonSerializable</mark>:<br><br>class mioOggetto implements \\JsonSerializable {<br><br>}<br><br><br>"],[["cross","origin","policy","richieste","altro","dominio"],"Quando PHP riceve richieste che non sono sotto il suo dominio, ma provengono da altri siti/domini, in via predefinita rifiuta le richieste (cross origin policy). Per abilitarle occorre usare la funzione header() e specificare:<br><mark>header('Access-Control-Allow-Origin: *');</mark><br><br>Questa funzione modifica l'header della pagina in uscita, composta solitamente attraverso una serie di echo.<br>"],[["pdo","metodi","crud","esempio"],"<h2>File esempio: DaoOggetti.php</h2><mark><?php</mark><br>// È necessario avere anche la classe Oggetto del model con metodi getter & setter<br>// Dao può essere esteso da un DaoOggetti specifico, basta passare gli argomenti al costruttore padre:<br>// parent::__construct('Accesso', 'tb_accessi',<br>// 'CodiceAccesso', [<br>// 'Username',<br>// 'DataLogin'<br>// ]<br>// );<br><br><mark>abstract class Dao {\n<br> protected static $pdo;\n<br> protected $classeOggetto = '';\n<br> protected $nomeTabella = '';\n<br> protected $chiaveIndicizzata = '';\n<br> protected $colonne = [];\n<br> \n<br> public function __construct($classeOggetto, $nomeTabella, $chiaveIndicizzata, $colonne) {\n<br> self::$pdo = Db::getInstance();\n<br> $this->colonne = $colonne;\n<br> $this->classeOggetto = $classeOggetto;\n<br> $this->nomeTabella = $nomeTabella;\n<br> $this->chiaveIndicizzata = $chiaveIndicizzata;\n<br> }\n<br>\n<br> public function create($oggetto) {\n<br> // Costruzione query con segnaposti\n<br> $query = 'INSERT INTO '.$this->nomeTabella.' SET '.$this->chiaveIndicizzata.'=:'.$this->chiaveIndicizzata.',';\n<br> foreach ($this->colonne as $colonna) {\n<br> $query .= ' '.$colonna.'=:'.$colonna.',';\n<br> }\n<br> $query = rtrim($query, ',') . ';';\n<br>\n<br> // Parametri con valore per i segnaposti\n<br> $getChiaveIndicizzata = 'get'.$this->chiaveIndicizzata;\n<br> $parameters = array(':'.$this->chiaveIndicizzata => $oggetto->{$getChiaveIndicizzata}());\n<br> foreach ($this->colonne as $colonna) {\n<br> $getValueColumn = 'get'.$colonna;\n<br> $parameters[':'.$colonna] = $oggetto->{$getValueColumn}();\n<br> }\n<br>\n<br> try {\n<br> $stm = self::$pdo->prepare($query);\n<br> $stm->execute($parameters);\n<br>\n<br> } catch (PDOException $e) {\n<br> echo $e->getMessage();\n<br> }\n<br> }\n<br> public function read($chiaveIndicizzata = null) {\n<br> $query = 'SELECT * FROM '.$this->nomeTabella;\n<br> $parameters = array();\n<br> if (!$chiaveIndicizzata) {\n<br> $query .= ';';\n<br> } else {\n<br> $query .= ' WHERE '.$this->chiaveIndicizzata.'=:'.$this->chiaveIndicizzata.';';\n<br> $parameters[':'.$this->chiaveIndicizzata] = $chiaveIndicizzata;\n<br> }\n<br>\n<br> try {\n<br> $stm =self::$pdo->prepare($query);\n<br> $stm->execute($parameters);\n<br> $fetched = $stm->fetchAll(PDO::FETCH_CLASS,$this->classeOggetto);\n<br> if (!$chiaveIndicizzata) {\n<br> return $fetched;\n<br> } else {\n<br> return $fetched[0];\n<br> }\n<br>\n<br> } catch (PDOException $e) {\n<br> echo $e->getMessage();\n<br> }\n<br> }\n<br> public function update($oggetto) {\n<br> // Costruzione query con segnaposti\n<br> $query = 'INSERT INTO '.$this->nomeTabella.' SET';\n<br> foreach ($this->colonne as $colonna) {\n<br> $query .= ' '.$colonna.'=:'.$colonna.',';\n<br> }\n<br> $query = rtrim($query, ',') .\n<br> 'WHERE '.$this->chiaveIndicizzata.'=:'.$this->chiaveIndicizzata.';';\n<br>\n<br> // Parametri con valore per i segnaposti\n<br> $getChiaveIndicizzata = 'get'.$this->chiaveIndicizzata;\n<br> $parameters = array();\n<br> $parameters[':'.$this->chiaveIndicizzata] = $oggetto->{$getChiaveIndicizzata}();\n<br> foreach ($this->colonne as $colonna) {\n<br> $getValueColumn = 'get'.$colonna;\n<br> $parameters[':'.$colonna] = $oggetto->{$getValueColumn}();\n<br> }\n<br> try {\n<br> $stm = self::$pdo->prepare($query);\n<br> $stm->execute($parameters);\n<br> } catch (PDOException $e) {\n<br> echo $e->getMessage();\n<br> }\n<br> }\n<br> public function delete($chiaveIndicizzata) {\n<br> $query = 'DELETE FROM '.$this->nomeTabella.\n<br> ' WHERE '.$this->chiaveIndicizzata.'=:'.$this->chiaveIndicizzata.';';\n<br> $parameters[':'.$this->chiaveIndicizzata] = $chiaveIndicizzata;\n<br>\n<br> try {\n<br> $stm = self::$pdo->prepare($query);\n<br> $stm->execute($parameters);\n<br> return $stm->rowCount();\n<br>\n<br> } catch (PDOException $e) {\n<br> echo $e->getMessage();\n<br> }\n<br> }\n<br>}</mark><mark></mark><br><br>"],[["laravel","installazione","composer"],"Laravel usa Composer per gestire le dipendenze. Per i moduli PHP richiesti consultare la <a href=\"https://laravel.com/docs/5.8#installation\" target=\"_blank\">documentazione</a>.<br>Per installare Laravel via Composer:<br><mark>composer global require laravel/installer</mark><br><br><br>"]],"Git":[[["utilizzo","uso","scopo"],"Git è un CVS (Sistema di Controllo di Versione) che è utile localmente ed in remoto:<br><br>- In locale: permette di avere copie di backup, mentre il lavoro avanza con nuove funzionalità. Quindi offre possibilità di recuperare versioni precedenti ed avere uno storico con tutte le modifiche commentate.<br><br>- In remoto: più sviluppatori possono collaborare e sincronizzare i loro lavori con il deposito in remoto, fondamentalmente ciò avviene tramite una logica a rami, ogni serie di modifiche viene realizzata su un ramo e questo può essere innestato sul progetto principale insieme ad altri rami. Possono coesistere anche dei rami principali dedicati alla versione stabile, di testing e di sviluppo.<br>"],[["installazione","download"],"Git è multipiattaforma e può essere scaricato dal sito ufficiale:<br><a href=\"https://git-scm.com/download\" target=\"_blank\">https://git-scm.com/download</a><br><br>In linux è disponibile nel software center.<br>"],[["configurazione"],"Ci sono 3 livelli di configurazione: tutti gli utenti (--system), singolo utente (--global), singolo progetto (cartella .git del progetto). Il livello più specifico sovrascrive quello più generale.<br><br>L'identità definita da nome ed email va inserita come prima cosa a livello utente:<br><br><mark>git config --global user.name \"MioNome\"<br>git config --global user.email \"mia@email.it\"</mark><br><br>Per controllare le configurazioni:<br><br><mark>git config --list</mark><br><br>È possibile attivare una cache di breve durata (pochi minuti) per le credenziali, così che in una serie di invii successivi non devono essere specificate ogni volta:<br><br><mark>git config --global credential.helper cache</mark><br><br>Di default Git usa l'editor Vim, probabilmente è preferibile usare nano:<br><br><mark>git config --global core.editor \"nano\"</mark><br><br>È comodo usare delle abbreviazioni per alcuni comandi molto usati, al posto di 'commit', potremo scrivere 'cm'; al posto di 'branch', 'br'; 'checkout', 'co' e 'status', 'st':<br><br><mark>git config --global alias.co checkout<br>git config --global alias.br branch<br>git config --global alias.cm commit<br>git config --global alias.st status</mark>"],[["avviare","progetto","nuovo","init"],"Creare una cartella con il nome del progetto, collocarsi al suo interno e partire con:<br><br><mark>git init</mark><br><br>Se la cartella contiene già dei file sarà possibile inserirli come prima modifica. Per inviare il progetto e le successive modifiche ad un deposito remoto, occorre specificare l'URL del deposito:<br><br><mark>git remote add origin https://github.com/Autore/NomeDeposito</mark><br><br>- origin è il nome del deposito, può essere modificato, così da averne più di uno.<br><br>Se serve forzare un primo commit su un deposito quasi vuoto che ospiterà il progetto, possiamo cancellare tutti i commit in remoto, sovrascrivendo con il progetto locale così:<br><br><mark>git push origin master --force</mark><br>(non è un metodo elegante, bisognerebbe approfondire le tecniche di rebase)<br>"],[["clonare","progetto"],"Recuperare l'URL del progetto da clonare (copiare in locale) e usare:<br><br><mark>git clone https://github.com/Autore/Progetto</mark><br><br>Verrà creata una cartella con il nome del progetto, per personalizzare il nome della cartella:<br><br><mark>git clone https://github.com/Autore/Progetto NomeCartella</mark>"],[["rimuovere","file","modifica","staging"],"<h2>Escludere un file dalla fase di modifica</h2><br>Se il file è segnato come modificato dobbiamo escluderlo dall'albero inserendo il suo nome in \".git/info/exclude\", ma questo avrà effetto solo per le prossime volte. Per la situazione corrente usare:<br><br><mark>git rm --cached nome_file</mark><br><br><h2>Escludere un file dalla fase di staging</h2><br>Se il file è già stato allestito per un commit e vogliamo continuare a monitorarlo, ma escluderlo dal commit preparato (e non ancora eseguito), usare:<br><br><mark>git reset HEAD nome_file</mark>"],[["sovrascrivere","ultimo","commit","amend"],"Per correggere l'ultimo commit, bisogna apportare le modifiche, mettere i file modificati in staging ed eseguire il comando:<br><br><mark>git commit --amend -m \"Titolo breve\" -m \"Descrizione completa\"</mark><br><br>Conviene specificare i messaggi, che andranno a sovrascrivere quelli precedenti, altrimenti verrà aperto un editor di testo per modificarli o confermarli.<br><br><b>N.B.</b><br>Il commit corretto (se quello sbagliato era stato già caricato in remoto) viene considerato nuovo e diverso, quindi sarà in conflitto con il deposito remoto. Se si è gli unici sviluppatori si può azzardare questa operazione:<br><br><mark>git push origin master --force</mark><br><br>Altrimenti occorre approfondire le possibilità offerte da:<br><br><mark>git rebase --continue<br></mark>"]],"*":[[["soap","rest"],"L'architettura SOAP usa file xml per configurazioni e per descrivere il funzionamento delle API. È molto verboso, difficile da scrivere, spesso viene autogenerato e poi processato con dispendio di cicli.<br><br>L'architettura REST è: client-server, senza stato, cachable, a strati, codice su richiesta, interfaccia uniforme (si stabilisce una convenzione poi si segue sempre, anziché passare configurazioni).<br><br><br>"],[["extreme","programming"],"<b>Extreme programming</b> si basa su alcuni valori:<br>- Coraggio (aggiornarsi, fare refactoring, esprimere la propria opinione)<br>- Semplicità (ridurre riunioni e documentazione e puntare all'obiettivo)<br>- Feedback (assicurarsi se si sta procedendo bene e comunicare problematiche)<br>- Comunicazione (tenere tutti informati degli eventi che incidono sul lavoro)<br>- Umiltà / rispetto (c'è sempre da imparare, rispettare il codice altrui)<br>"]],"Java":[[["web","enterprise","edition","ee","introduzione"],"<h1>Java e Web</h1><br>JavaEE (Enterprise Edition) è un contenitore di librerie Java:<br><br>- JDBC (Java DataBase Connectivity)<br>- JSP (Java Server Pages) tradotti in istanze tramite classe Servlet<br>- EJB (Enterprise JavaBean)<br>- JSF (Java Server Faces)<br><br>= Servlet =<br>Classe java che gestisce un sistema client-server di richieste e risposte.<br>Funziona all'interno di un contenitore java che fa da Server Application / Web Server (alcuni esempi: Tomcat, JBoss, Glassfish, ecc.). Questi fanno funzionare le servlet.<br><br>I Server Java si dividono in due gruppi:<br><br>-- Application Server<br>Un'applicazione Web è un insieme di servlet, filter e listener.<br>container java per tutto il container EE compresi gli EJB<br>(es. JBoss)<br><br>-- Web Server<br>container java per servlet e JSP e JSF<br>(es. Tomcat)<br>"],[["preparare","apache","tomcat"],"In Eclipse occorre dedicare un Workspace per JavaEE ed avere la giusta perspective. Serve aver scaricato il file zip <a href=\"https://tomcat.apache.org/download-90.cgi\" target=\"_blank\">Apache Tomcat</a> che contiene il server.<br><br>- C'è una scheda dei server (in basso)<br>- Tasto destro > Proprietà - Scegliere \"Switch Location\" per non legare il server ad Eclipse<br>- Sul server con doppio click si apre la finestra Overview, qui impostiamo la porta 8081 (per evitare eventuali conflitti col database Oracle o altro) e la deploy path dovrebbe essere: /opt/apache-tomcat/webapps<br>- Definire gli utenti, la configurazione essenziale in <mark>tomcatusers.xml</mark> è:<br><br><mark><role rolename=\"tomcat\"/><br><role rolename=\"admin\"/><br><role rolename=\"admin-gui\"/><br><role rolename=\"manager-gui\"/><br><user username=\"tomcat\" password=\"password\" roles=\"tomcat,admin,admin-gui,manager-gui\"/></mark><br><br>ovvero 4 ruoli essenziali tutti attribuiti ad un super utente tomcat.<br><br>- Avviando il server si potrà visitare: <a href=\"http://localhost:8081\" target=\"_blank\">http://localhost:8081</a><br>- Il passo successivo è solitamente creare un nuovo Dynamic Web Project<br><br><h3>Alcuni possibili problemi</h3>- C'è un processo tomcat attivo, quando avviamo il nostro, l'ultimo crasha e non risponde come atteso. Soluzione: terminare il processo precedente.<br>- Assicurarsi che tutti i ruoli siano presenti in tomcatusers.xml, se non è così, si chiudono i server, non specifica quale errore si è verificato e resta anche un processo attivo da terminare.<br>- La variabile di sistema JAVA_HOME deve esistere (soprattutto su Windows), il suo valore deve essere il percorso della jdk.<br>- Si può tentare anche un deploy manuale dal file war (creato in ogni progetto dentro la cartella 'target'). Si va su <a href=\"http://localhost:8081/manager/html/list\" target=\"_blank\">http://localhost:8081/manager/html/list</a> e si cerca \"WAR file to deploy\"."],[["servlet","definizione"],"La Servlet è una classe Java che gestisce il traffico http. Questa viene istanziata con la prima chiamata di un utente qualsiasi. Per ogni chiamata di un utente viene aperto un thread parallelo (multi-threading).<br><br>È possibile istanziare una servlet all'avvio dell'applicazione Web, specificando l'ordine di istanziazione (0, 1, 2...) o fargli aspettare il momento della prima chiamata (con -1).<br>"],[["jsp","jstl","el","definizione"],"<h2>JSP (Java Server Page)</h2><br>File contenenti codice html e codice java (scriptlet, simile ai file php)<br><br>Le JSP sono tradotte in Servlet da un motore jsp presente nell'Application / Web Server<br>(in Tomcat questo motore si chiama Jasper, le servlet compilate vengono eseguite da Catalina)<br><br>JSP hanno 3 componenti:<br><br><h3>Direttive</h3>Istruzioni generali alla servlet:<br><%@ page: informazioni per la generazione della pagina<br><%@ include: include codice statico per il lato client (html, js, semplice testo)<br><%@ taglib: include librerie di tag<br><br><h3>Azioni</h3>Tag che compiono azioni particolari richiamando metodi o oggetti per la servlet sottostante.<br><jsp:useBean id=\"nomeIstanza\" class=\"NomeClasse\" scope=\"page\"><br><jsp:setProperty ... <br><jsp:getProperty ...<br><jsp:param ...<br><jsp:include ... permette di includere contenuto dinamico proseguendo l'esecuzione nel jsp chiamante<br><jsp:forward ... chiamare una servlet interrompendo il flusso in quella chiamante<br><br><br>N.B.<br>JavaBean sono oggetti di tipo POJO (Plain Old Java Object), ovvero oggetti serializzabili (rappresentabili tramite stringa e deve avere un costruttore vuoto).<br>Gli EJB (Enterprise Java Bean) sono diversi dai JavaBean: oggetti Java specializzati (SJO).<br><br><h3>Oggetti impliciti</h3>Sono variabili con nomi riservati per gli oggetti: request, response, session, application, ecc.<br><br><h2>JSTL</h2><br>Libreria di tag lato server che incapsula codice Java:<br>core, fn, xml, sql<br><br><h2>EL (Expression Language)</h2><br>Specificato così: <mark>${}</mark> linguaggio minimale per interagire con gli attributi dei tag JSTL<br><br>"],[["direttiva","page","superflua"],"Questa riga di codice è una direttiva page:<br><mark><%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%></mark><br><br>Viene posta all'inizio di un nuovo file JSP, ma è superflua perché specifica aspetti predefiniti, quindi si può eliminare.<br>"],[["jsp","chiamate","servlet"],"Una servlet riceve request e response e può:<br>- inoltrare con RequestDispatcher: metodo forward()<br>- avviare una nuova chiamata con response.sendRedirect(\"nome_file.jsp\")<br>- includere con RequestDispatcher una servlet mantenendosi sulla servlet chiamante con jsp:include<br>"],[["import","statico","test"],"Anche se un metodo non è statico, soprattutto nei test, è comodo importarlo come metodo statico. Esempio:<br><br><mark>import static org.junit.Assert.assertEquals;</mark><br><br><mark>@Test<br>public void esempioTest()<br>{</mark><br> // ...<br><br> // posso usare il metodo direttamente<br><mark> assertEquals(\"2 + 3 should have returned 5\", 5, result);<br>}</mark><br><br>"],[["junit","test","suite"],"JUnit funziona con una <mark>test suite</mark> (semplicemente è una classe), all'interno avremo dei <mark>test case</mark>, composti da <mark>assertion</mark>.<br>Al momento JUnit 4 e 5 sono le versioni usate.<br><br><br>"],[["el","expression","language"],"Quando una jsp dal client chiama una servlet, automaticamente verranno passati i parametri inviati con metodo get e post, ma anche gli attributi specificati con:<br><mark>request.setAttribute(\"messaggio\", \"<div>Si è verificata questa cosa.</div>\");</mark><br><br>Nella jsp l'EL può usare sia i parametri get e post con param. :<br><mark>${param.username}</mark><br><br>sia gli attributi da noi impostati con setAttribute :<br><mark>${messaggio}</mark><br><br>"],[["struts","introduzione"],"- Struts 2 è un framework datato, non usato nei nuovi progetti, ma ancora presente in tante aziende<br>- la versione 2 sarà verosimilmente l'ultima, adesso si usa Spring (o JavaEE alternativa proprietaria)<br>- funziona come un grande filtro e gestisce le chiamate prima di passarle alle servlet<br>- Struts si serve solo di azioni e intercettatori<br>- il file struts.xml gestisce il routing: path_url -> action (classe)<br>- I metodi getter popolano la jsp che risponde, i metodi setter popolano la classe chiamata<br>- gli interceptor vanno messi in uno stack nel file xml e poi si specifica lo stack predefinito o quale stack ciascuna azione deve usare<br>"],[["spring","flusso","richieste","web","jsp"],"N.B. Vari file xml e dipendenze nel pom.xml vanno configurate correttamente affinché spring funzioni.<br><br>N.B. Il sito web nel file WAR si trova in una cartella che deve essere specificata per vedere il sito. Se vogliamo specificare un path generale diverso, che leggerà quella cartella, va fatto nel file META-INF/context.xml:<br><mark><Context path=\"/nomeprogetto\"/></mark><br><br><h3>HTTP --> smistatore</h3>Le richieste su spring arrivano a web.xml che dichiara una servlet smistatrice (DispatcherServlet). Possono esserci più smistatori che vengono attivati in funzione di una path generale specificata.<br><br><h3>smistatore --> controller</h3>La richiesta viene smistata ai controller, che normalmente dovrebbero essere raccolti nel pacchetto controller, ma per comunicare a spring che certe classi sono controller di spring si usa la direttiva @Controller prima della classe. Immediatamente dopo questa direttiva, se ne inserisce un'altra @RequestMapping(\"/mia-pagina\") che serve a stabilire in funzione della pagina richiesta quale controller eseguire. Possiamo non mettere questa direttiva e risulterà un controller da eseguire con la path generale del progetto.<br><br>Dopo aver intercettato il nome della pagina e dunque il controller da eseguire, possiamo decidere quale metodo chiamare grazie a @GetMapping e @PostMapping, che potranno passare anche argomenti ai metodi. Esempi:<br><br>La direttiva senza argomenti intercetta la path di base:<br><mark>@GetMapping<br>public String execute(Model model) {<br> // Legge una lista oggetti da un database<br> model.addAttribute(\"oggetti\", db.getAll());<br> return \"vista-oggetti\";<br>}controller > pagina jsp</mark><br><br>@GetMapping(\"prodotti\")<br><mark>public String mostraProdotti(Model model) {<br> // Legge una lista prodotti da un database<br> model.addAttribute(\"prodotti\", prodotti);<br> return \"vista-prodotti\";<br>}</mark><br><br>Con le graffe possiamo recuperare un argomento dall'URL e poi usarlo nel metodo con la direttiva @PathVariable:<br><mark>@GetMapping(\"prodotto/{id}\")<br>public String mostraProdotti(Model model, @PathVariable Integer id) {<br> // Legge prodotto con id da un database<br> model.addAttribute(\"prodotto\", prodotto);<br> return \"vista-prodotto\";<br>}</mark><br><br>Se i dati arrivano da una form si usa @PostMapping e si recuperano gli argomenti in funzione dei name negli input della forma con @RequestParam:<br><mark>@PostMapping(\"iscrizione\")<br>public String iscriviUtente(Model model,<br> @RequestParam String username,<br> @RequestParam String email,<br> @RequestParam String password) {<br><br> // Vengono svolte alcune operazioni di controllo e di scrittura sul database<br> // Vengono raccolti eventuali messaggi nell'array messaggi<br> model.addAttribute(\"messaggi\", messaggi);<br> return \"profilo\";<br>}</mark><br><br><h3>controller --> pagina jsp</h3>Nei metodi dei controller possiamo usare l'argomento \"Model model\", spring lo auto valorizza. Questo model tramite il metodo .addAttribute(chiave, valore) può passare parametri che giungeranno alla jsp chiamata da return \"nome-jsp\" e saranno recuperabili con ${chiave} e possiamo recuperare anche oggetti con ${oggetto} o ${oggetto.id}<br><br>Attenzione. Spring automaticamente recupera gli attributi che trova tramite GET e li usa per compilare i valori degli input che hanno corrispondenza con il name di un elemento input. Questi valori diventano disponibili solo grazie a:<br><mark>@GetMapping(\"read/{id}\")<br>public String metodo (@PathVariable Integer id) { ... }</mark><br><br>"],[["spring","definizione","introduzione"],"Spring è un ecosistema di software (Spring Framework, Spring boot, ecc.) che può integrare anche Struts 2, Hibernate, ecc."],[["hibernate","introduzione"],"Hibernate serve per la persistenza dei dati nel database. La sua articolazione varia molto in base all'interfaccia utilizzata. Hibernate può funzionare con: JPA, Spring, No-Spring, XML, Annotation, Config-Class, Spring boot."],[["jpa","java","persistence","api"],"JPA è un'interfaccia per comunicare ad un livello sottostante come salvare gli oggetti nel database. Il livello sottostante può essere gestito da Hibernate, EclipseLink, iBatis, ecc. Il linguaggio per fare le query si chiama JPQL, ma è molto simile a HQL."]],"SQL":[[["creare","eliminare","database","namespace"],"<mark>CREATE DATABASE nome_database;</mark><br><br>Se in seguito si devono fare varie operazioni sul database si può usare un namespace:<br><br><mark>USE nome_database;</mark><br><br>Per eliminare:<br><br><mark>DROP DATABASE nome_database;</mark>"],[["funzioni","gruppo","raggruppamento","max","min","avg","sum","count"],"<h1>Funzioni di gruppo / di raggruppamento</h1><br><mark>MAX</mark> recupera il valore maggiore in una colonna<br><mark>MIN</mark> idem, ma il valore minore<br><mark>SUM</mark> somma tutti i valori di una colonna<br><mark>AVG</mark> la media dei valori: es. SELECT AVG(cilindrata) FROM veicoli<br><mark>COUNT</mark> conta le righe: SELECT COUNT(*) FROM tabella (inutile specificare una colonna)<br><br>Sintassi:<br><mark>SELECT FUNZIONE_DI_GRUPPO(colonna) FROM tabella;</mark><br>"],[["select","ordine","istruzioni"],"SELECT<br>FROM<br>WHERE<br>GROUP BY<br>HAVING<br>ORDER BY"],[["where","having","in"],"L'operatore IN permette di valutare se un valore è presente in un insieme di valori. Si può usare con where e con having.<br><br><mark>SELECT * FROM veicoli WHERE targa IN ('AX123BY','AZ234AS','QQ123WW');</mark><br><br>"],[["select","where","equijoin"],"L'equijoin è una query che restituisce una tabella le cui righe sono generate consultando due tabelle relazionate tramite una chiave comune alle righe da associare. L'uguaglianza delle chiavi si specifica con WHERE.<br><br><mark>SELECT a.id_automobili, targa, nome_modello FROM automobili a, modelli m\n<br>WHERE (a.id_automobili = m.id_automobili) ORDER BY targa;</mark><br><br>"],[["select","from","inner","join","using","natural"],"INNER JOIN ... USING è una query che restituisce una tabella le cui righe sono costituite da tutte le righe di una ed un'altra tabella associate in base ad una chiave comune. Dunque USING è obbligatorio e si tratta di un modo più breve di fare l'equijoin.<br><br>N.B. Questa sintassi è supportata solo da alcuni database, per esempio Oracle.<br><br>Partire da una tabella e poi unirne un'altra o viceversa è equivalente:<br><mark>select * from Veicoli INNER JOIN Modelli USING(id_modello);\n<br>select * from Modelli INNER JOIN Veicoli USING(id_modello);</mark><br><br>Se i nomi dei campi delle chiavi comuni sono uguali è possibile usare:<br><mark>select * from Veicoli NATURAL INNER JOIN Modelli;</mark><br><br>Tutte le query precedenti sono equivalenti a:<br><mark>select * from Veicoli v, Modelli m where v.id_modello = m.id_modello;</mark><br><br>"]],"Angular":[[["preparare","installare","dipendenze"],"<h1>Installare Angular</h1><br>Angular dipende da NodeJS<br>N.B. AngularJS è la vecchia versione, adesso si chiama Angular (<a href=\"https://angular.io\" target=\"_blank\">angular.io</a>).<br><br>- Installare <a href=\"https://nodejs.org/it\" target=\"_blank\">NodeJS</a>, si tratta di un'applicazione che esegue JS (arricchito con qualche potenzialità) fuori dal browser e quindi anche lato server. NodeJS è una dipendenza/componente di Chrome.<br>- Installare <a href=\"https://git-scm.com/downloads\" target=\"_blank\">Git</a> perché è usato per recuperare le dipendenze di volta in volta necessarie.<br>- La presenza di NodeJS mette a disposizione il comando 'npm' che è un gestore di pacchetti.<br>- angular-cli, installarlo con: <mark>npm i -g @angular/cli</mark> (con permessi di root, i sta per install, -g esegue un'installazione globale, altrimenti installa componenti sulla cartella corrente)<br>- Ora è disponibile il comando 'ng' che sarebbe l'abbreviazione di angular.<br>- Per installare una nuova applicazione: <mark>ng new nome_progetto</mark><br>- Si lavora principalmente in: nome_progetto/src<br>- Collocarsi su: <mark>cd nome_progetto</mark> ed eseguire: <mark>ng serve</mark> (così avremo un server in locale), il comando comunica a quale porta del localhost viene servito il sito, in via predefinita: <a href=\"http://localhost:4200\" target=\"_blank\">http://localhost:4200</a><br><br>"],[["nuovo","componente"],"Un'app Angular si struttura tramite componenti. Per crearne uno nuovo:<br><mark>ng g component nome_componente</mark> (g sta per generate)<br><br>I componenti sono inseriti in una cartella omonima dentro src/app e sono costituiti da 4 file:<br><mark>nome.component.css</mark> (grafica del componente)<br><mark>nome.component.html</mark> (template specifico e si può usare <mark>{{variabile</mark> o espressione<mark>}}</mark> )<br><mark>nome.component.spec.ts</mark> (file TypeScript dedicato al testing)<br><mark>nome.component.ts</mark> (file TypeScript)"],[["nuovo","servizio"],"Un servizio viene usato per chiedere dati ad Angular. Essi vengono istanziati una sola volta (singleton):<br><mark>ng g service nome_servizio</mark> (g: generate)<br><br>Si creano due file:<br><mark>nome.service.spec.ts</mark> (file TypeScript dedicato ai test)<br><mark>nome.service.ts</mark> (file TypeScript del servizio)<br><br>Nel file app.module.ts , nella direttiva @NgModule, inserire i servizi dentro providers:<br><mark> providers: [<br> AutoreService<br> ],</mark><br><br>"],[["expressions","espressioni","{{}}"],"In Angular dentro i file html dei componenti si possono usare le espressioni Angular:<br><mark>{{variabile}}</mark> (stampa nome variabile)<br><mark>{{object|json}}</mark> (converte l'oggetto in formato json e stampa)<br><mark>{{2+3}}</mark> (risolve e scrive 5)<br><mark>{{autori[0].cognome}}</mark> (valori di array semplici e associativi)<br><br>In generale possiamo scrivere espressioni js con dei limiti.<br><br>Negli attributi del template html possiamo avere solo testo (caso 1), un'espressione js (caso 2) o l'attributo stesso dentro parentesi quadre (caso 3), così che il valore dell'attributo verrà valutato come un'espressione js:<br><br>1) <mark>attributo=\"4+4\"</mark><br>2) <mark>attributo=\"{{4+4}}\"</mark><br>3) <mark>[attributo]=\"4+4\"</mark><br><br>Spesso le parentesi quadre servono per i dati in input (comportamento più affidabile):<br><mark>[oggetto]=\"item\"</mark> (item non sarà una stringa, ma verrà cercata la variabile item)<br><br>"],[["ajax","httpclient","chiamata","servizi"],"Su Angular per fare chiamate ad un database si usa il protocollo HTTP ed occorre importare il relativo modulo:<br>- modificare il file <mark>app.module.ts</mark>, aggiungere:<br><mark>import { HttpClientModule } from '@angular/common/http';</mark><br><br>Dentro la direttiva @NgModule, controllare che il seguente pezzo sia corretto:<br><mark> imports: [<br> BrowserModule, HttpClientModule<br> ],</mark><br><br>"]],"HTML":[[["elementi","semantici","generici","sezioni"],"<mark><header></mark><br>Specifica una intestazione del sito o di un contenuto o di una scheda e simili.<br>Non può essere usato dentro header o dentro footer.<br><br><mark><section></mark><br>Raggruppa elementi omogenei oppure specifica un contenuto articolato in cui vogliamo inserire un'intestazione, un corpo, informazioni di contatto, ecc. Serve anche per indicare una parte del sito che non rientra in altre categorie semantiche predefinite.<br><br><mark><main></mark><br>Deve essere unico. È come un section, ma più specifico ed indica il contenuto principale di un sito (tale contenuto può consistere anche in un elenco di sommari o risultati di una ricerca).<br><br><mark><article></mark><br>Specifica un contenuto che da solo (indipendentemente dal contesto offerto dal sito) ha un senso e può essere ripresentato altrove.<br><br>N.B. <section> e <article> possono annidarsi tra loro liberamente. Es.: una sezione di articoli e un articolo con una sezione tecnica.<br><br><mark><footer></mark><br>Solitamente contiene meta-informazioni sui contenuti, può essere inserito nel documento o nelle sezioni.<br><br><mark><nav></mark><br>Indica i menu, insiemi di link di importanza rilevante per la navigazione del sito.<br><br><mark><aside></mark><br>Indica parti secondarie del sito dedicate a contenuti correlati, extra, curiosità, ecc.<br><br><br>"],[["elementi","semantici","specifici"],"<mark><figure></mark><br>Serve a descrivere semanticamente un'immagine. Esempio:<br> <br><mark><figure><br> <img src=\"nome_file.jpg\" alt=\"Descrizione immagine\"><br> <figcaption>Fig. 1 - Titolo, località, fotografo.</figcaption><br></figure></mark><br><br><mark><mark></mark><br>Evidenzia porzioni di testo o parole chiave attribuendogli una rilevanza semantica.<br><br><mark><time></mark><br>Attribuisce un giorno ed un ora ad un evento scritto per umani:<br><br><mark><time datetime=\"2020-02-14 00:00\">Giorno di San Valentino</time></mark><br><br>N.B.<br>Ci sono altri tag specifici ma spesso sono parzialmente supportati o sperimentali.<br> "],[["comandi","http","principali"],"Ci sono alcuni comandi principali che però, quando giungono al server, questo decide cosa fare con queste informazioni e spesso si usano unicamente GET e POST per comunicare ogni operazione. HTML supporta solo GET e POST, il protocollo HTTP ha più comandi.<br><br><mark>http get</mark> : lettura dati<br>(spedisce dati via URL mediante querystring)<br><br><mark>http post</mark> : inserimento dati<br>(spedisce dati via header http)<br><br><mark>http put</mark> : aggiornamento dati<br>(aggiorna l'intero oggetto sostituendo l'originale)<br><br><mark>http patch</mark> : aggiornamento dati<br>(aggiorna proprietà specifiche di un oggetto)<br><br><mark>http delete</mark> : eliminazione dati<br><br>Json è considerato lo standard per passare oggetti.<br>"],[["picture","img","cambia","immagine"],"In base alla specifica media=\"()\" si può selezionare un'immagine o un'altra (differenze tra PC e stampa, dispositivi o larghezze diverse, ecc.):<br><br><mark><picture><br> <source media=\"(min-width: 650px)\" srcset=\"img_pink_flowers.jpg\"><br> <source media=\"(min-width: 465px)\" srcset=\"img_white_flower.jpg\"><br> <img src=\"img_orange_flowers.jpg\" alt=\"Flowers\" style=\"width:auto;\"><br></picture></mark><br><br>"]],"Bootstrap":[[["inserimento","link","css","js"],"HEAD:<br><br><mark><link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\" integrity=\"sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T\" crossorigin=\"anonymous\"></mark><br><br>Raccomandato aggiungere:<br><mark><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\"></mark><br><br>SCRIPT (in fondo a BODY):<br><br><mark><script src=\"https://code.jquery.com/jquery-3.3.1.slim.min.js\" integrity=\"sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo\" crossorigin=\"anonymous\"></script><br><script src=\"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js\" integrity=\"sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1\" crossorigin=\"anonymous\"></script><br><script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js\" integrity=\"sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM\" crossorigin=\"anonymous\"></script></mark><br><br>"],[["contenitore","container","fisso","fluido"],"Affinché bootstrap lavori correttamente è bene inserire ogni sua classe dentro un contenitore. Questo può essere fisso o fluido:<br><br><mark><div class=\"container\"><br></div><br><br><div class=\"container-fluid\"><br></div></mark><br><br>I contenitori verranno usati come se fossero una griglia di 12 colonne e si specificherà agli elementi contenuti quante colonne devono occupare.<br>"],[["personalizzare","scss","compilare","npm"],"Bootstrap può essere personalizzato attraverso i file scss, però occorre avere i suoi sorgenti per esempio con:<br><mark>npm install bootstrap</mark><br><br>Le modifiche si realizzano tramite override degli stili scss (consultare documentazione). Poi si ricompilano i file di distribuzione con:<br><mark>npm run dist</mark><br><br>Per includere bootstrap nel proprio progetto indicare nel punto di ingresso dell'applicazione Web (solitamente index.js o app.js):<br><mark>import 'bootstrap';</mark><br><br>"],[["grid","row","col","size","colonne","a","capo"],"Il layout di un sito si struttura tramite la griglia di bootstrap:<br><br><mark><div class=\"container\"><br> <div class=\"row\"><br> <div class=\"col-md-6\"><br> One of three columns<br> </div><br> <div class=\"col-md-6\"><br> One of three columns<br> </div><br> </div><br></div></mark><br><br>Il numero finale specifica quante colonne deve occupare l'elemento. In via predefinita lo spazio è diviso in parti uguali. Esempi: col-6 (6 colonne su 12), col-2 (2 colonne su 12), ecc.<br><br>Le taglie (size) servono per legare il numero di colonne specificato ad un dispositivo:<br><mark>col</mark> (implicito xs, dispositivo extra small)<br><mark>col-sm</mark> (dispositivo small)<br><mark>col-md</mark> (medium)<br><mark>col-lg</mark> (large)<br><mark>col-xl</mark> (extra large)<br><br>Per mandare a capo delle colonne si può usare l'elemento invisibile:<br><mark><div class=\"w-100\"></div></mark><br><br>"],[["grid","row","justify-content","allineamento","orizzontale"],"Le colonne di una tabella (se non occupano 12/12) possono essere giustificate:<br><br>a sinistra: \"<mark>row</mark>\" (senza dire altro)<br>al centro: \"<mark>row justify-content-md-center</mark>\"<br>a destra: \"<mark>row justify-content-md-end</mark>\"<br>spazio intorno: \"<mark>row justify-content-around</mark>\"<br>spazio tra elementi: \"<mark>row justify-content-between</mark>\"<br><br>Siccome le direttive accompagnano row, ciascuna riga può ricevere direttive diverse.<br>Inoltre, si possono spostare le colonne tramite offset:<br>spazio vuoto di 2 colonne e poi la colonna desiderata: \"<mark>col offset-md-2</mark>\"<br>Se si superano le 12 colonne, va a capo.<br>Per eliminare l'offset con taglie superiori: \"<mark>col offset-lg-0</mark>\"<br>"],[["grid","margin","padding","positivo","negativo"],"Il padding ed il margin si possono impostare per un contenitore, una riga, una colonna, un qualsiasi elemento di bootstrap.<br><br>padding: <mark>p-4</mark><br>padding orizzontale: <mark>px-2</mark><br>padding verticale: <mark>py-4</mark><br><br>margin: <mark>m-4</mark><br>margin orizzontale: <mark>mx-2</mark><br>margin verticale: <mark>my-0</mark><br>margin orizzontale negativo: <mark>mx-n2</mark><br><br>Le taglie si possono sempre inserire tra m o p e il numero:<br><mark>mx-1 mx-md-4</mark><br><br>"],[["grid","row","align-items","allineamento","verticale"],"Se il contatore è più alto del contenuto (altezza) delle colonne, queste si possono posizionare:<br><br>In alto: \"<mark>row align-items-start</mark>\"<br>Al centro: \"<mark>row align-items-center</mark>\"<br>In basso: \"<mark>row align-items-end</mark>\"<br><br>È possibile specificare il posizionamento verticale per singole colonne:<br><br><mark><div class=\"container\"><br> <div class=\"row\"><br> <div class=\"col align-self-start\"><br> Mi trovo in alto<br> </div><br> <div class=\"col align-self-center\"><br> Mi trovo al centro<br> </div><br> <div class=\"col align-self-end\"><br> Mi trovo in basso<br> </div><br> </div><br></div></mark><br><br>"],[["grid","col","order","ordinamento"],"Le colonne si possono ordinare aggiungengo una classe di fianco a col:<br><br>\"<mark>col</mark>\" (dopo first vengono elencati i senza numero)<br>\"<mark>col order-1</mark>\" (dopo first e dopo i senza numero)<br>\"<mark>col order-first</mark>\" (al primo posto e prevale su tutto)<br>\"<mark>col order-last</mark>\" (ultimo posto)<br>\"<mark>col order-3</mark>\" (segue l'ordinamento dei numeri)<br><br>"],[["stili","predefiniti","reboot"],"In Bootstrap spesso si deve indicare una classe per applicare uno stile, ma ci sono una serie di stili già pronti per alcuni elementi html, senza ricorrere a classi:<br><br><body><br><h1> fino ad <h6><br><ul>, <ol>, <dl> (lista non ordinata, ordinata e di definizioni)<br><pre><br><fieldset> (gruppo di controlli invisibile)<br><legend><br><label><br><input><br><select><br><textarea><br><button><br><address><br><br><br><abbr><br><input type=\"text\" hidden> (in bootstrap servirsi dell'attributo hidden per i campi nascosti)<br><code> (codifica le entità html)<br><pre> (conserva tabulazioni e ritorni a capo)<br><var> (specifica una variabile)<br><samp> (stile per l'output di un programma)<br><br>"],[["stile","immagine","img","figure"],"Immagine a grandezza 1:1, ma se più grande del contenitore si ridimensiona:<br><mark><img src=\"\" alt=\"\" class=\"img-fluid\"></mark><br><br>L'immagine deve essere già dimensionata come anteprima (es. 200x200), gli viene dato giusto un bordo:<br><mark><img src=\"\" alt=\"\" class=\"img-thumbnail\"></mark><br><br>Per arrotondare leggermente l'immagine stessa, aggiungere la classe \"rounded\" (vale per ogni elemento):<br><mark>class=\"img-fluid rounded\"</mark><br><br>Per centrare l'immagine specificare che è un blocco \"d-block\" e impostare su auto i margini orizzontali con \"mx-auto\" (vale per ogni elemento):<br><mark>class=\"rounded mx-auto d-block\"</mark><br>In alternativa, inserire l'immagine dentro un div:<br><mark><div class=\"text-center\"></div></mark><br><br>Per accompagnare un'immagine con una descrizione:<br><mark><figure class=\"figure\"><br> <img src=\"\" class=\"figure-img img-fluid rounded\" alt=\"\"><br> <figcaption class=\"figure-caption text-center\">Breve titolo d'accompagnamento</figcaption><br></figure></mark><br><br>"],[["stile","tabella","table"],"Con class=\"table\" bootstrap prepara una tabella fluida, con bordi per le righe:<br><br><mark><table class=\"table\"><br> <thead><br> <tr><br> <th scope=\"col\">ID</th><br> <th scope=\"col\">Nome</th><br> <th scope=\"col\">Cognome</th><br> </tr><br> </thead><br> <tbody><br> <tr><br> <th scope=\"row\">1</th><br> <td>Mario</td><br> <td>Rossi</td><br> </tr><br> <tr><br> <th scope=\"row\">2</th><br> <td>Giorgio</td><br> <td>Verdi</td><br> </tr><br> <tr><br> <th scope=\"row\">3</th><br> <td>Simone</td><br> <td>Bianchi</td><br> </tr><br> </tbody><br></table></mark><br><br>Per avere le righe di colore alternato (tabella zebrata):<br><mark><table class=\"table table-striped\"></mark><br><br>Per avere tutti i bordi delle celle:<br><mark><table class=\"table table-bordered\"></mark><br><br>Oppure nessun bordo:<br><mark><table class=\"table table-borderless\"></mark><br><br>Per evidenziare la riga su cui si passa sopra:<br><mark><table class=\"table table-hover\"></mark><br><br>Per avere una tabella dagli spazi compatti:<br><mark><table class=\"table table-sm\"></mark><br><br>"],[["stile","messaggi","alert"],"Un messaggio può essere comunicato all'utente con uno stile alert:<br><mark><div class=\"alert alert-success\" role=\"alert\"><br> Prodotto inserito nel carrello.<br></div></mark><br><br>Gli stili disponibili sono:<br><mark>alert-success<br>alert-info<br>alert-warning<br>alert-danger</mark><br><br>Meno usati:<br><mark>alert-primary<br>alert-secondary<br>alert-light<br>alert-dark</mark><br><br>Un alert può dotarsi di un pulsante di chiusura:<br><mark><div class=\"alert alert-warning <u>alert-dismissible fade show</u>\" role=\"alert\"><br> <strong>Holy guacamole!</strong> You should check in on some of those fields below.<br> <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\"><br> <span aria-hidden=\"true\">×</span><br> </button><br></div></mark><br><br>Se vogliamo dare un titolo al messaggio usiamo questa classe:<br><mark><h4 class=\"alert-heading\">Well done!</h4></mark><br><br>Se usiamo un link dentro un alert è meglio specificare:<br><mark><a href=\"\" class=\"alert-link\">Torna al profilo</a></mark><br><br>"],[["stile","etichetta","distintivo","badge"],"I badge mettono in rilievo parole, tag, o numeri che solitamente contano qualcosa. Sono elementi in linea collocabili dentro link e pulsanti:<br><mark><span class=\"badge badge-primary\">Etichetta</span></mark><br><br>Altre classi che differiscono per colore:<br><mark>badge-secondary<br>badge-success<br>badge-danger<br>badge-warning<br>badge-info<br>badge-light<br>badge-dark</mark><br><br>Lo stile è smussato, ma se vogliamo l'etichetta simile ad una pillola:<br><mark><span class=\"badge badge-primary badge-pill\">Pillola</span></mark><br><br>Le classi badge possono essere assegnate direttamente ai link."],[["stile","nav","percorso","breadcrumb"],"Stile del percorso per facilitare la navigazione del sito:<br><br><mark><nav aria-label=\"breadcrumb\"><br> <ol class=\"breadcrumb\"><br> <li class=\"breadcrumb-item\"><a href=\"\">Home</a></li><br> <li class=\"breadcrumb-item\"><a href=\"\">Servizi</a></li><br> <li class=\"breadcrumb-item active\" aria-current=\"page\">Sei qui</li><br> </ol><br></nav></mark><br><br>Il separatore dei breadcrumb-item si può impostare così (regola css):<br><br><mark>.breadcrumb-item + .breadcrumb-item::before {<br> content: \"»\";<br>}</mark><br><br>"],[["stile","pulsanti","button","link","checkbox","radio"],"La classe per lo stile dei pulsanti si applica a button o ad input tipo pulsante:<br><mark><button type=\"button\" class=\"btn btn-primary\">Ok</button><br><input type=\"submit\" class=\"btn btn-primary\" value=\"Invia\"></mark><br><br>Altre classi disponibili:<br><mark>btn-primary<br>btn-secondary<br>btn-success<br>btn-danger<br>btn-warning<br>btn-info<br>btn-light<br>btn-dark</mark><br><br>Inserire -outline- tra btn- e lo stile -primary (o gli altri), per impostare il pulsante con solo contorno colorato:<br><mark>btn-outline-primary<br>btn-outline-secondary<br>btn-outline-success<br>btn-outline-danger<br>btn-outline-warning<br>btn-outline-info<br>btn-outline-light<br>btn-outline-dark</mark><br><br>Per scegliere la dimensione del pulsante:<br><mark>btn-sm</mark><br>(nulla è medium)<br><mark>btn-lg</mark><br><br>Pulsante lungo tutta la riga:<br><mark>btn-block</mark><br><br>L'attributo disabled è gestito, però se siamo in un link, inserire:<br><mark>class=\"btn ... disabled\" aria-disabled=\"true\"</mark><br><br>Pulsante che si attiva e disattiva (toggle):<br><mark><button type=\"button\" class=\"btn btn-primary\" data-toggle=\"button\">Selezionami</button></mark><br><br>Gruppo di checkbox stile pulsante:<br><mark><div class=\"btn-group-toggle\" data-toggle=\"buttons\"><br> <label class=\"btn btn-secondary active\"><br> <input type=\"checkbox\">Mele<br> </label><br> <label class=\"btn btn-secondary\"><br> <input type=\"checkbox\">Pere<br> </label><br></div></mark><br><br>Gruppo di opzioni esclusive:<br><mark><div class=\"btn-group btn-group-toggle\" data-toggle=\"buttons\"><br> <label class=\"btn btn-secondary active\"><br> <input type=\"radio\" name=\"options\" id=\"option1\" checked>Auto<br> </label><br> <label class=\"btn btn-secondary\"><br> <input type=\"radio\" name=\"options\" id=\"option2\">Mezzi pubblici<br> </label><br></div></mark><br><br>N.B.<br>Specificare \"<mark>btn-group</mark>\" è facoltativo e raccoglie i pulsanti come se fosse uno unico suddiviso.<br>Ulteriori possibilità su pulsanti in una toolbar, menu/annidamento, menu verticale, dimensione del gruppo, vedere la documentazione <a href=\"https://getbootstrap.com/docs/4.2/components/button-group/\" target=\"_blank\">Button group</a>.<br><br>"],[["stile","card","schede"],"Una card (scheda) occupa il 100% della larghezza, relativamente alle colonne disponibili della griglia bootstrap, a meno che non specifichiamo la larghezza con un attributo style. Segue una scheda caricata con quasi tutto il possibile, dalla quale si può rimuovere ciò che non si desidera.<br><br>Per avere una scheda scura: <mark>class=\"card bg-dark text-white\"</mark> (list-group-item richiede un'applicazione individuale)<br>Disponibili anche i colori: <mark>bg-primary</mark>, <mark>bg-secondary</mark>, <mark>bg-success</mark>, <mark>bg-danger</mark>, <mark>bg-warning</mark>, <mark>bg-info</mark>.<br>Se vogliamo colorare solo il bordo: <mark>border-primary</mark>, ecc. (in tal caso torna utile <mark>bg-transparent</mark> per alcuni elementi)<br><br><mark><div class=\"card text-center\" style=\"width: 18rem;\"><br> <div class=\"card-header\"><br> Titolo su sfondo grigetto<br> </div><br> <img src=\"\" alt=\"\" class=\"card-img-top\"><br> <div class=\"card-body\"><br> <h5 class=\"card-title\">Card title</h5><br> <p class=\"card-text\">Some quick example text to build on the card title and make up the bulk of the card's content.</p><br> </div><br> <ul class=\"list-group list-group-flush\"><br> <li class=\"list-group-item\">Cras justo lorem</li><br> <li class=\"list-group-item\">Dapibus ac facilisis in</li><br> <li class=\"list-group-item\">Vestibulum at eros</li><br> </ul><br> <blockquote class=\"blockquote mb-0\"><br> <p class=\"mt-3\">Intera frase che si desidera citare.</p><br> <footer class=\"blockquote-footer\">Nome personaggio di <cite title=\"Source Title\">Titolo opera</cite></footer><br> </blockquote><br> <div class=\"card-body\"><br> <a href=\"#\" class=\"card-link\">Primo link</a><br> <a href=\"#\" class=\"card-link\">Altro link</a><br> </div><br> <div class=\"card-footer text-muted\"><br> 2 giorni fa<br> </div><br></div></mark><br><br>L'header di una card può presentare anche delle schede che bootstrap renderizza, ma l'effettiva gestione va implementata lato server. Si può scegliere lo stile tra \"<mark>card-header-tabs</mark>\" e \"<mark>card-header-pills</mark>\".<br><br><mark><div class=\"card-header\"><br> <ul class=\"nav nav-tabs <u>card-header-tabs</u>\"><br> <li class=\"nav-item\"><br> <a class=\"nav-link active\" href=\"#\">Active</a><br> </li><br> <li class=\"nav-item\"><br> <a class=\"nav-link\" href=\"#\">Link</a><br> </li><br> <li class=\"nav-item\"><br> <a class=\"nav-link disabled\" href=\"#\" tabindex=\"-1\" aria-disabled=\"true\">Disabled</a><br> </li><br> </ul><br></div></mark><br><br>È possibile avere anche:<br>- immagine di sfondo con testo sopra (<a href=\"https://getbootstrap.com/docs/4.2/components/card/#image-overlays\" target=\"_blank\">overlay</a>)<br><br>Le card si possono raccogliere in gruppi (<mark>card-group</mark>), in mazzi (<mark>card-deck</mark>), in colonne (<mark>card-columns</mark>):<br><mark><div class=\"<u>card-group</u>\"><br> <div class=\"card\"></div><br> <div class=\"card\"></div><br></div></mark><br><br>"],[["stile","diapositive","carousel"],"Recuperare e adattare gli esempi da qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/carousel\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/carousel</a><br><br>"],[["stile","tendine","collapse"],"Testo nascosto richiamabile con pulsanti o schede.<br><br>- Soluzione semplice: uno o più pulsanti che mostrano e nascondono (toggle) dei testi che spesso sono semplici card bootstrap. Più target sono ammessi.<br><br>- Accordion: è un gruppo di schede collassate e quando se ne consulta una, le altre si chiudono.<br><br>Esempi di codice qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/collapse\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/collapse</a><br><br>"],[["stile","menu","a","tendina","dropdown"],"Disponibili pulsanti che aprono menu sotto, sopra o a lato. Il pulsante può essere diviso in una parte di azione immediata e nella freccina che apre il menu.<br><br>Poco frequente: un elenco di link che se premuti fanno l'effetto di pulsanti, ammessi divisori.<br><br>Volendo dovrebbe esser possibile mettere un form dentro un menu a tendina richiamabile con un pulsante.<br><br>Esempi qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/dropdowns\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/dropdowns</a><br><br>"],[["stile","form","controlli","input","campi"],"Bootstrap offre numerosi elementi di controllo nelle form validate lato client:<br>campo testo, email, password, pulsante submit, menu di scelta, lista di scelta, area di testo, invio file, scorrimento su un range, checkbox, radio, interruttore.<br><br>- I form si possono internamente organizzare in griglie.<br>- I campi possono ricevere un'icona all'inizio del campo.<br>- Si può inserire un testo di aiuto (HelpBlock) per ogni elemento.<br>- Dentro l'input si può indicare un esempio con l'attributo: placeholder=\"First name\"<br>- Per ogni controllo si possono inserire feedback di validazione: accettato, errato.<br>- Esiste anche l'interruttore come controllo speciale equivalente a checkbox.<br>- Ogni volta che compare un nome (es. Sfoglia su input file) c'è il modo di tradurlo.<br><br>Per tutti gli esempi di codice leggere qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/forms\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/forms</a><br><br>"],[["stile","gruppi","input","prepend","append"],"Un gruppo di input sono elementi attaccati come se fossero uno unico e si possono così mettere prepend, append o altri elementi input. Append e prepend servono per esplicitare quel che viene automaticamente aggiunto al proprio input (es. simbolo €, http://).<br><br>L'input upload file può essere reso più carino con un gruppo:<br><mark><div class=\"input-group mb-3\"><br> <div class=\"input-group-prepend\"><br> <span class=\"input-group-text\" id=\"inputGroupFileAddon01\">Upload</span><br> </div><br> <div class=\"custom-file\"><br> <input type=\"file\" class=\"custom-file-input\" id=\"inputGroupFile01\" aria-describedby=\"inputGroupFileAddon01\"><br> <label class=\"custom-file-label\" for=\"inputGroupFile01\">Choose file</label><br> </div><br></div></mark><br><br>Per gli altri esempi leggere qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/input-group\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/input-group</a><br><br>"],[["stile","contenitore","vetrina","jumbotron"],"Per avere una sezione che include un titolo ed altri elementi a piacere, ma messi in rilievo, come fossero in una vetrina, si può usare jumbotron. La classe jumbotron si comporta come i contenitori e può essere fisso o fluido.<br><br>Alcuni classici esempi:<br><a href=\"https://getbootstrap.com/docs/4.2/components/jumbotron\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/jumbotron</a><br><br>"],[["stile","elenchi","list","group"],"Una lista <ul> può essere definita come gruppo di elementi, che possono essere semplici voci, ma anche elementi articolati tipo le schede (card). Per ogni \"list-group-item\" si può specificare se l'elemento è attivo, disabilitato, con un colore particolare (primary, secondary, danger, ecc.).<br><br>Qui gli esempi:<br><a href=\"https://getbootstrap.com/docs/4.2/components/list-group\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/list-group</a>"],[["stile","elenchi","immagini","media","object"],"Media object serve per avere elenchi di paragrafi con titolo accompagnati da immagini. Queste si possono allineare in alto, al centro, in basso, tenere a destra o a sinistra. Sembrerebbe che le card posso realizzare questo tipo di contenuti...<br><br>Qualche esempio qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/media-object\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/media-object</a>"],[["modal","finestre","dialogo"],"Un esempio base di finestra modale è il seguente:<br><br><mark><button type=\"button\" class=\"btn btn-primary\" data-toggle=\"modal\" data-target=\"#exampleModal\"><br> Apri finestra di dialogo<br></button></mark><br><br><!-- Modal --><br><mark><div class=\"modal fade\" id=\"exampleModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"modalLabel\" aria-hidden=\"true\"><br> <div class=\"modal-dialog\" role=\"document\"><br> <div class=\"modal-content\"><br> <div class=\"modal-header\"><br> <h5 class=\"modal-title\" id=\"modalLabel\">Titolo della finestra</h5><br> <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Chiudi\"><br> <span aria-hidden=\"true\">&times;</span><br> </button><br> </div><br> <div class=\"modal-body\"><br> Qui il messaggio di testo che deve comparire.<br> </div><br> <div class=\"modal-footer\"><br> <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">Close</button><br> <button type=\"button\" class=\"btn btn-primary\">Fare qualcosa onclick</button><br> </div><br> </div><br> </div><br></div></mark><br><br>- data-target=\"#exampleModal\" serve per agganciarsi ad un modale id=\"exampleModal\" che resta nascosto.<br>- gli attributi aria-... riguardano specifiche per l'accessibilità.<br>- class=\"modal-dialog modal-dialog-centered\" per visualizzare il modale al centro.<br>- class=\"modal-dialog modal-sm\" per avere un modal small, disponibili anche -lg, -xl.<br>- Esiste la possibilità di far apparire <a href=\"https://getbootstrap.com/docs/4.2/components/modal/#tooltips-and-popovers\" target=\"_blank\">popover e tooltip</a>, ma potrebbero risultare opprimenti...<br>- Il sistema grid di bootstrap si può usare dentro i modali, ma difficilmente servirà mai.<br>- Tramite jquery è possibile far apparire, annullare il modale più <a href=\"https://getbootstrap.com/docs/4.2/components/modal/#methods\" target=\"_blank\">altri metodi</a>.<br>- Tramite jquery si può recuperare dati da un pulsante (es. data-qualcosa=\"...\") e personalizzare il modale aperto nel titolo o nei valori predefiniti o in alcuni campi specifici. Serve quando abbiamo la stessa struttura per il modale e <a href=\"https://getbootstrap.com/docs/4.2/components/modal/#varying-modal-content\" target=\"_blank\">variano solo alcuni dati</a>.<br><br>Volendo inserire una form html in un modale, si può mettere dentro \"modal-body\":<br><br><mark><form><br> <div class=\"form-group\"><br> <label for=\"recipient-name\" class=\"col-form-label\">Recipient:</label><br> <input type=\"text\" class=\"form-control\" id=\"recipient-name\"><br> </div><br> <div class=\"form-group\"><br> <label for=\"message-text\" class=\"col-form-label\">Message:</label><br> <textarea class=\"form-control\" id=\"message-text\"></textarea><br> </div><br> <input id=\"mySubmit\" type=\"submit\" class=\"d-none\" name=\"comando\" value=\"login\"><br></form></mark><br><br>Il submit sarà nascosto (dispay none), si può sfruttare per inserire una coppia chiave-valore (conviene specificare il comando richiesto), deve essere dentro la form e verrà azionato dai pulsanti del modale (dentro \"modal-footer\") con jquery:<br><br><mark><button type=\"button\" class=\"btn btn-primary\" onclick=\"$('#mySubmit').click()\">Invia</button></mark><br><br>"],[["stile","menu","navigazione","nav"],"Bootstrap offre nav semplici o tramite liste di link. Esempio semplice:<br><mark><nav class=\"nav\"><br> <a class=\"nav-link active\" href=\"#\">Active</a><br> <a class=\"nav-link\" href=\"#\">Link</a><br> <a class=\"nav-link disabled\" href=\"#\" tabindex=\"-1\" aria-disabled=\"true\">Disabled</a><br></nav></mark><br><br>Per centrare il menu (o -end per averlo a destra):<br><mark><nav class=\"nav justify-content-center\"></mark><br><br>Per mettere le voci in colonna:<br><mark><nav class=\"nav flex-column\"></mark><br><br>Effetto schede (o nav-pills per l'effetto bottoni):<br><mark><nav class=\"nav nav-tabs\"></mark><br><br>Per occupare tutta la larghezza, a prescindere dallo stile scelto:<br><mark><nav class=\"nav nav-fill\"></mark><br>Forse può tornare utile nei dispositivi piccoli.<br><br>Inserendo -sm-, -md-, -lg-, dentro le specifiche per gli stili di nav, si possono destinare quegli stili a dispositivi con la relativa taglia.<br><br>Una voce di menu può presentare un sottomenu a tendina:<br><mark><li class=\"nav-item dropdown\"><br> <a class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\">Dropdown</a><br> <div class=\"dropdown-menu\"><br> <a class=\"dropdown-item\" href=\"#\">Action</a><br> <a class=\"dropdown-item\" href=\"#\">Another action</a><br> <div class=\"dropdown-divider\"></div><br> <a class=\"dropdown-item\" href=\"#\">Separated link</a><br> </div><br></li></mark><br><br>Queste voci di menu si possono legare a schede che vengono presentate dinamicamente con JS (simile ad accordion). Probabilmente è un'eventualità poco frequente, per approfondire vedere la <a href=\"https://getbootstrap.com/docs/4.2/components/navs/#javascript-behavior\" target=\"_blank\">documentazione</a>.<br><br>"],[["stile","menu","navigazione","navbar"],"navbar ha un ruolo più centrale di nav, è destinata alla navigazione principale del sito e può contenere un logo ed una casella di ricerca, come anche campi di vario tipo, pulsanti, testo semplice, ecc. Copiare le parti di esempio desiderate direttamente qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/navbar\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/navbar</a><br><br>Sono possibili alcune <a href=\"https://getbootstrap.com/docs/4.2/components/navbar/#color-schemes\" target=\"_blank\">personalizzazioni grafiche</a>.<br>In fondo alle personalizzazioni, si mostra come rendere il menu collassabile (stile sito mobile).<br>"],[["stile","paginazione","pagination"],"Semplicemente ci sono alcune classi da inserire in una classica lista per specificare che si tratta di una paginazione.<br>Esempi: <a href=\"https://getbootstrap.com/docs/4.2/components/pagination\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/pagination</a><br><br>"],[["finestrelle","a","comparsa","popover"],"Utilizzando o meno popover si può decidere se tenere o meno popper.js tra le dipendenze di bootstrap. Ci sono delle attenzioni particolari da osservare descritte qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/popovers/#overview\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/popovers/#overview</a><br><br>Fondamentalmente si tratta di finestrelle a comparsa. Si possono far apparire sopra, sotto o a lato, e cliccando fuori da esse possono persistere o chiudersi. Si possono comandare tramite jquery.<br><br>Un semplice esempio mostra che sono interamente definiti da attributi:<br><mark><button type=\"button\" class=\"btn btn-secondary\" id=\"myPopover\"<br> data-container=\"body\"<br> data-toggle=\"popover\"<br> data-placement=\"top\"<br> data-content=\"Questo testo apparirà cliccando sul pulsante.\"><br> Cliccami<br></button></mark><br><br>Gli attributi:<mark><br> data-trigger=\"focus\"<br> title=\"Titolo del popover\"</mark><br>permettono rispettiamente di far sparire il popover con la perdita del focus ed avere un titolo.<br><br><b>N.B.</b><br>Popover per funzionare deve essere inizializzato con jquery:<br><mark>$('#myPopover').popover({});</mark><br><br>Per conoscere le opzioni da inserire nell'array, leggere <a href=\"https://getbootstrap.com/docs/4.2/components/popovers/#options\" target=\"_blank\">Options</a>.<br><br>"],[["stile","barra","progresso","progress"],"Le barre del progresso sono costruite con un contenitore progress ed una barra interna (div) con classe progress-bar. Questo div interno può ricevere un valore e così la barra avrà un'etichetta. L'altezza del contenitore specifica l'altezza per tutti, la larghezza va specificata alla sola barra del progresso per farla crescere. Si possono avere barre multiple e con effetto strisce diagonali.<br><br>Esempio onnicomprensivo da cui togliere ciò che non serve:<br><mark><div class=\"progress\" style=\"height: 32px;\"><br> <div class=\"progress-bar progress-bar-striped progress-bar-animated\" role=\"progressbar\"<br> style=\"width: 25%\" aria-valuenow=\"25\" aria-valuemin=\"0\" aria-valuemax=\"100\"><br> 25%<br> </div><br> <div class=\"progress-bar bg-warning\" role=\"progressbar\"<br> style=\"width: 20%\" aria-valuenow=\"20\" aria-valuemin=\"0\" aria-valuemax=\"100\"><br> 20%<br> </div><br></div></mark><br><br>"],[["navbar","spy","scrollspy"],"È possibile avere un menu collegato alle sezioni (ancore) di un articolo e mentre si scorre l'articolo, le relative voci raggiunte si evidenziano. Esempio:<br><br><mark><nav id=\"navbar-spy\" class=\"navbar navbar-light bg-light\"><br> <a class=\"navbar-brand\" href=\"#\">Titolo linkabile</a><br> <ul class=\"nav nav-pills\"><br> <li class=\"nav-item\"><br> <a class=\"nav-link\" href=\"#inizio\">§ 1. Inizio</a><br> </li><br> <li class=\"nav-item dropdown\"><br> <a class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\">§ 2. Sviluppo</a><br> <div class=\"dropdown-menu\"><br> <a class=\"dropdown-item\" href=\"#one\">Parte 1</a><br> <a class=\"dropdown-item\" href=\"#two\">Parte 2</a><br> <div role=\"separator\" class=\"dropdown-divider\"></div><br> <a class=\"dropdown-item\" href=\"#three\">Parte 3</a><br> </div><br> </li><br> <li class=\"nav-item\"><br> <a class=\"nav-link\" href=\"#fine\">§ 3. Fine</a><br> </li><br> </ul><br></nav><br><div data-spy=\"scroll\" data-target=\"#navbar-spy\" data-offset=\"0\" style=\"height: 150px; overflow-y: scroll;\"><br> <h4 id=\"inizio\">§ 1. Inizio</h4><br> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sem posuere, pulvinar orci eget, efficitur tortor. Pellentesque vel volutpat erat. Praesent interdum urna leo, ut finibus nunc eleifend imperdiet. Aliquam hendrerit, est eget vulputate commodo, nisi turpis placerat enim, nec ultricies nulla odio nec purus.</p><br> <h4 id=\"one\">Parte 1</h4><br> <p>Integer ante neque, pretium eu sem ac, hendrerit varius dui. Aenean consectetur et dolor at elementum. Integer luctus mi ut erat feugiat egestas. Etiam eleifend auctor molestie. Curabitur maximus at felis quis tristique. Integer massa nulla, mattis et sem et, venenatis luctus erat.</p><br> <h4 id=\"two\">Parte 2</h4><br> <p>Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas lacinia massa sollicitudin leo rutrum rutrum. Proin eu aliquam elit. Proin laoreet ullamcorper est et fringilla. Donec in pulvinar orci. Sed pharetra ligula ac arcu fermentum, vel ultrices lacus semper.</p><br> <h4 id=\"three\">Parte 3</h4><br> <p>Aenean quis felis imperdiet, volutpat ligula at, condimentum eros. Maecenas vel maximus lorem. Pellentesque mattis sem at sodales dapibus. Quisque a mollis sem. Donec maximus purus a eros lacinia vulputate. Pellentesque erat nulla, feugiat tincidunt aliquet at, posuere sed nisi.</p><br> <h4 id=\"fine\">§ 3. Fine</h4><br> <p>Phasellus nec massa et eros maximus commodo. Pellentesque ligula lorem, sollicitudin sit amet lacinia eu, tristique nec eros. Vivamus vehicula vitae neque quis feugiat. Aenean sit amet pulvinar ligula. Ut vel finibus ipsum. Ut ut vestibulum est. Suspendisse pretium cursus interdum.</p><br></div></mark><br><br>Per le varianti con menu laterale annidato o elementi in una list-group, recuperare altri esempi dalla <a href=\"https://getbootstrap.com/docs/4.2/components/scrollspy/#example-with-nested-nav\" target=\"_blank\">documentazione</a>.<br><br>"],[["stile","animazione","icona","caricamento","spinner"],"Con due righe di codice bootstrap offre animazioni classiche in CSS per segnalare un caricamento in corso.<br>Scegliere quello desiderato da <a href=\"https://getbootstrap.com/docs/4.2/components/spinners/\" target=\"_blank\">qui</a>.<br>"],[["notifiche","push","toast","alert"],"In modo simile alle notifiche su desktop o su smartphone, internamente alla pagina del sito bootstrap può far comparire dei messaggi da chiudere manualmente o che si chiudono in automatico con un ritardo.<br><br>Esempio semplice:<br><mark><div class=\"toast\" role=\"alert\" aria-live=\"assertive\" aria-atomic=\"true\" data-autohide=\"false\" style=\"position: absolute; bottom: 0; right: 0;\"><br> <div class=\"toast-header\"><br> <img src=\"\" class=\"rounded mr-2\" alt=\"Icona\"><br> <strong class=\"mr-auto\">Titoletto</strong><br> <small>10 min fa</small><br> <button type=\"button\" class=\"ml-2 mb-1 close\" data-dismiss=\"toast\" aria-label=\"Close\"><br> <span aria-hidden=\"true\">×</span><br> </button><br> </div><br> <div class=\"toast-body\"><br> Hello, world! Questo è un avviso da chiudere manualmente.<br> </div><br></div></mark><br><br>Per far aprire i toast, occorre un comando jquery:<br><mark>$('.toast').toast('show');</mark><br><br>Se vogliamo che si chiuda in automatico usare questi due attributi:<br><mark>data-autohide=\"true\" data-delay=\"5000\"</mark> (tempo ritardo chiusura in millisecondi)<br><br>N.B.<br>Se vengono aperti più toast contemporaneamente, e non è impostata la posizione assoluta, questi si impilano uno sopra l'altro.<br><br><br>"],[["suggerimenti","a","comparsa","tooltip"],"I tooltip appaiono passando sopra col mouse, finché c'è il focus restano visibili e possono includere testo HTML. Alcuni semplici esempi qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/tooltips/#examples\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/tooltips/#examples</a><br><br>N.B. Occorre inizializzare i tooltip con il comando:<br><mark>$('#id_tooltip').tooltip(options)</mark><br><br>options è un array che può ricevere i valori illustrati qui:<br><a href=\"https://getbootstrap.com/docs/4.2/components/tooltips/#options\" target=\"_blank\">https://getbootstrap.com/docs/4.2/components/tooltips/#options</a>"],[["stili","classi","utilità"],"Bootstrap definisce utilità alcune classi che applicano stili a qualsiasi elemento.<br><br>Si possono inserire bordi o eliminarli, scegliere il colore e la rotondità del bordo:<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/borders/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/borders/</a><br><br>Attribuire colori al testo e allo sfondo con la classica terminologia (primary, secondary, ecc.):<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/colors/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/colors/</a><br><br>Impostare il valore display con l'abbreviazione d- seguito dall'eventuale taglia -md- e dal valore:<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/display/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/display/</a><br><br>Per incorporare contenuti esterni (iframe) e mantenere la responsività:<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/embed/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/embed/</a><br><br>Lavorare rapidamente con display flex (usare la grid bootstrap preferibilmente):<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/flex/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/flex/</a><br><br>Il float può tornare utile per immagini ed elementi di contorno:<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/float/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/float/</a><br><br>Per impostare rapidamente la posizione (utile sticky):<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/position/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/position/</a><br><br>Aggiunta rapida dell'effetto ombra:<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/shadows/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/shadows/</a><br><br>Dimensionamento (meglio affidarsi alle colonne bootstrap preferibilmente):<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/sizing/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/sizing/</a><br><br>Gestire margin e padding (utilissimo e frequente):<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/spacing/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/spacing/</a><br><br>Vari stili ed effetti per il testo (ritorno a capo, effetti grafici...):<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/text/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/text/</a><br><br>Allineamento verticale:<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/vertical-align/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/vertical-align/</a><br><br>Visibilità:<br><a href=\"https://getbootstrap.com/docs/4.2/utilities/visibility/\" target=\"_blank\">https://getbootstrap.com/docs/4.2/utilities/visibility/</a><br><br>"],[["form","controlli","input","campi","validazione"],"La validazione dei campi in bootstrap può integrarsi con la validazione nativa html ed una validazione personalizzata javascript.<br><br>Il form bootstrap deve avere questi attributi:<br><mark>novalidate onsubmit=\"return controlloSpeciale()\"</mark><br><br>- Nei campi di input si può usare type e pattern per stabilire una validazione lato client. Però, va disattivata con l'attributo novalidate.<br><br>- L'evento onsubmit deve, tramite la funzione controlloSpeciale(), applicare al form la classe 'was-validated' e controllare subito la validità secondo le possibilità offerte da html:<br><mark>let e_form = document.getElementsByName('formName')[0];<br>e_form.classList.add('was-validated');<br>if (!e_form.checkValidity()) return false;</mark><br><br>- In seguito la funzione può operare controlli a piacere e preparare dati da elaborare. Se tutto è valido per l'invio, allora ritorneremo true, altrimenti false.<br><br>"]],"CSS":[[["transizioni","animate"],"Innumerevoli effetti di transizione si possono realizzare con CSS. Il metodo più semplice consiste nel definire due classi, una con lo stile iniziale, una con lo stile finale. L'elemento che passerà da una classe all'altra deve possedere:<br><mark>transition: all .5s ease 1s;</mark><br><br><mark>all</mark>: tutte le proprietà cercheranno di fare una transizione, ma si può limitare: es. width.<br><mark>.5s</mark>: mezzo secondo, è il tempo di durata della transizione.<br><mark>ease</mark>: sono modalità della transizione per ammorbidire inizio e fine o averla lineare.<br><mark>1s</mark>: è il ritardo facoltativo prima di far partire la transizione."],[["grid","spazi","dimensionamento"],"La direttiva grid viene data ad un box genitore insieme al numero e alla dimensione delle colonne e delle righe:<br><mark>display: grid;<br>grid-template-columns: 1fr 1fr 1fr 1fr;<br>grid-template-rows: 10vh 20vh 20vh 50vh;</mark><br><br>fr è una frazione, nel caso precedente corrisponde al 25%.<br><br>Quasi sempre servirà dare direttive ai figli. Questi cercano di occupare i primi posti liberi in relazione alla loro dimensione. La loro dimensione è definita dicendo da quale colonna iniziano a quale colonna finiscono e da quale riga iniziano a quale riga finiscono. La sintassi breve è questa:<br><mark>grid-column: 1 / 2;<br>grid-row: 2 / 4;</mark><br><br>N.B. Singoli errori nella griglia possono portare a guastarla tutta.<br><br>Le stesse cose si possono fare con la direttiva <mark>grid-template-areas</mark>, ma è più chiaro il metodo qui sopra."],[["float"],"Il concetto di float è problematico, si tratta di un flusso, fuori dal flusso ordinario, ma con la possibilità per questi flussi di scorrere in parallelo.<br><br>Si può avviare un flusso a sinistra o a destra:<br><mark>float: left;<br>float: right;</mark><br><br>Si deve interrompere un flusso avviato con clear:<br><mark>clear: left;<br>clear: right;<br>clear: both;</mark><br><br>N.B. Si possono realizzare testi a colonne con questa tecnica, ma conviene flex.<br>"],[["flex","riga","colonna","spazio","direction","justify","align","allineamento","orizzontale","verticale"],"La direttiva flex viene data ad un box genitore ed anche le prossime direttive sono per il genitore.<br><mark>display: flex;</mark><br><br>Il flusso di elementi è automaticamente orizzontale (riga) e non va a capo.<br>Orizzontale e che va a capo:<br><mark>flex-direction: row;<br>flex-wrap: wrap;</mark><br>Scorciatoia:<br><mark>flex-flow: row wrap;</mark><br><br>Verticale:<br><mark>flex-direction: column;</mark><br><br>Verticale con ordine invertito:<br><mark>flex-direction: column-reverse;</mark><br><br>Gli elementi orizzontalmente possono essere:<br>Centrati: <mark>justify-content: center;</mark><br>Messi a sinistra: <mark>justify-content: left;</mark><br>Messi a destra: <mark>justify-content: right;</mark><br>Giustificati con spazio tra loro: <mark>justify-content: space-between;</mark><br>Giustificati con spazio tra loro e il bordo: <mark>justify-content: space-evenly;</mark><br>Giustificati con spazio attorno loro: <mark>justify-content: space-around;</mark><br><br>Gli elementi verticalmente possono essere:<br>Posti in alto: <mark>align-items: flex-start;</mark><br>Posti al centro: <mark>align-items: center;</mark><br>Posti in basso: <mark>align-items: flex-end;</mark><br>Espansi dall'alto al basso: <mark>align-items: stretch;</mark><br><br>"],[["pseudo","elementi","html"],"Qui l'elenco ed il significato degli pseudo elementi HTML:<br><a href=\"https://www.w3schools.com/css/css_pseudo_elements.asp\" target=\"_blank\">https://www.w3schools.com/css/css_pseudo_elements.asp</a><br><br>::before (aggiunge un elemento prima)<br>::after (aggiunge un elemento dopo)<br>::first-letter<br>::first-line<br>::selection<br><br>:active<br>:checked<br>:disabled<br>:empty<br>:enabled<br>:first-child<br>:first-of-type<br>:focus<br>:hover<br>:in-range<br>:invalid<br>:lang(language)<br>:last-child<br>:last-of-type<br>:link (non visitato)<br>:not(selector) (tutto tranne selector)<br>:nth-child(n)<br>:nth-last-child(n)<br>:nth-last-of-type(n)<br>:nth-of-type(n)<br>:only-of-type<br>:only-child<br>:optional (senza attributo required)<br>:out-of-range<br>:read-only<br>:read-write<br>:required<br>:root<br>:target<br>:valid (input con valore valido)<br>:visited<br><br>"],[["posizionamento","fisso","relativo","assoluto"],"Il posizionamento fisso è relativo al documento, si posiziona specificando distanze dai bordi:<br><mark>position: fixed;<br>top: 0;<br>right: 0;</mark><br><br>Se vogliamo sovrapporre elementi figli tra loro, servirà un elemento padre con:<br><mark>position: relative;</mark><br>ed entrambi gli elementi figli con:<br><mark>position: absolute;</mark><br><br>N.B. absolute senza un padre relative non funziona.<br>"]],"JQuery":[[["ajax"],"<a href=\"http://api.jquery.com/jquery.ajax\" target=\"_blank\">http://api.jquery.com/jquery.ajax</a><br><br><mark>$.('url_path.php', {<br> data: {<br> chiave: valore<br> },<br> success: function(response) {</mark><br> /* In caso di successo */<br><mark> },<br> error: function(response) {</mark><br> /* In caso di errore */<br><mark> }<br>});<br><br>L'URL può essere inserito nell'array associativo del secondo argomento:<br></mark><br><mark>$.(</mark><mark>{url: 'url_path.php',<br> data: {<br> chiave: valore<br> },<br> success: function(response) {</mark><br> /* In caso di successo */<br> <mark> }<br>});</mark><br><br>N.B. <mark>response</mark> viene creato implicitamente<br>"]],"OOP":[[["scaffolding"],"Scaffolding significa prepare tutta la struttura e le configurazioni."]],"GNU-Linux":[[["grep"],"<mark>comando_che_produce_output_testuale | grep '^PATH'</mark><br><mark>grep 'regex' nome_file</mark><br><br>'^PATH' : esempio di regex"]],"CleanCode":[[["design","pattern"],"Un <mark>design pattern</mark> è una soluzione standard a problemi ricorrenti.<br>N.B. ci sono anche <mark>anti-pattern</mark> es. \"oggetto dio\" (che fa tutto)<br><br><h2>GRASP (General Responsibility Assignment Software Patterns)</h2>Consiste nell'assegnare le responsabilità all'oggetto più esperto.<br>Lo scopo è ridurre il più possibile l'accoppiamento tra classi.<br>Rendere le classi coese, ovvero con poche o singole responsabilità.<br>Occorre proteggersi anche dalle variazioni: far interagire l'utente con le interfacce, anziché con le classi. Questo è un approccio diffuso anziché far nascere il model con le classi, lo facciamo nascere con le interfacce e poi creiamo classi che implementano quelle interfacce.<br><br><h2>GoF (Gang of Four)</h2>Sono 4 autori che hanno scritto un libro: \"Design Patterns: Elements of Reusable Object-Oriented Software\". Qui sono trattati numerosi pattern divisi in 3 grandi categorie: pattern strutturali, creazionali e comportamentali.<br><br><h2>SOLID</h2>- Principio di singola responsabilità<br>- Aperto alle estensioni e chiuso alle modifiche<br>- Oggetti sostituibili con loro sottotipi<br>- Sono preferibili più interfacce specifiche che una generica<br>- Una classe dovrebbe dipendere da astrazioni, non da classi concrete<br><br><h2> OOP (Object Oriented Programming)</h2>OOP modella il dominio di interesse ed associa responsabilità.<br><br><h2>MVC (Model View Controller)</h2>Software complessi devono essere organizzati in strati (layer).<br> | -- <mark>Presentation</mark> (end-to-end test) [V] [C] (V e C a volte sono accorpati nei framework)<br> | -- <mark>Business logic</mark> / <mark>Domain model</mark> (unit test) [M] (a volte è usato per rappresentare lo strato di presentazione)<br>\\_/-- <mark>Services</mark> (integration test)<br><br>I comandi vanno dall'alto al basso, così da poter modularizzare bene: V > C > M (la V invia un evento al C, il C aggiorna M e comunica a V che può aggiornarsi, V legge M e si aggiorna). L'alternativa è usare un altro pattern: observer.<br><br><h2>Observer</h2>Per semplificare V > C > M, si è pensato che V può dotarsi di un ascoltatore di M, così che piccole notifiche possono passare dal basso verso l'alto.<br>Ci sono due fasi: 1) \"l'abbonamento all'ascolto\" e 2) l'invio di una notifica.<br>Si può creare l'interfaccia Observer che sarà implementata da V, e creare la classe Observable che sarà ereditata da M. Però, si crea un forte accoppiamento tra Observable e M.<br><br><b>Composition over inheritance</b> (anche chiamato \"composizione e delega\"): provare ad usare la composizione invece dell'ereditarietà. Invece di estendere Observable, ci limitiamo ad usare Observable. Questo tipo di composizione assomiglia molto al pattern <b>Strategy</b> della GoF.<br><br><h2>- Inheritance</h2>Model potrebbe ereditare Observable, ma questa è la situazione più limitante e da evitare. Dato che poi model non può ereditare più da nessuno e si crea un forte accoppiamento.<br><br><h2>- Strategy (Semplicemente composizione)<br></h2>Delegare una responsabilità ad un oggetto che ne implementa la strategia. L'oggetto avrà come attributo un altro oggetto a cui delega la responsabilità di Observable.<br><br><h2>- Decorator (Un oggetto implementa l'interfaccia di un altro e gli delega le responsabilità)<br></h2>Si rovesciano le parti di strategy. Le nuove responsabilità vengono usate direttamente con l'oggetto competente (es. Observable) e si prenderà come sua composizione l'oggetto base che vogliamo arricchire con tali responsabilità.<br><br><h3>ProperyChangeEvent e ProperyChangeListener</h3>Nello specifico di Java, la classe Observer è deprecata e si consiglia di lavorare con ProperyChangeListener<br><br>"],[["behaviour-driven","development"],"Si tratta di un modo di fare TTD. È molto richiesto l'approccio BDD (Behaviour-Driven Development), la cui finalità è realizzare test quasi espressi con il linguaggio umano.<br><br>'test suite' diventa <mark>describe</mark> (descrive come funziona l'applicazione)<br>'test case' diventa <mark>it</mark> (esso fa.. nome della funzione)<br>'assertion' diventa <mark>expect</mark> (mi aspetto...)<br><br>Un buon modo di commentare un test unitario:<br>// given<br>...<br>// when<br>...<br>// then<br>...<br><br><br>"],[["tdd","test-driven","development"],"<h1>TDD Test-Driven Development</h1>È un approccio che mette al centro i test. Prima si scrive il test che fallisce, poi si implementa il codice per far funzionare il test e poi si passa al prossimo test. Lo sviluppo è dunque guidato dai test.<br><br>I test servono in ordine: a fornire documentazione (perché offrono numerosi esempi concreti e cosa ci si aspetta debba accadere), a fare progettazione, a prevenire regressioni (una nuova funzionalità crea errori e si rischia di regredire, posso procedere se tutti i test finora svolti continuano ad essere verdi).<br><br><h2>Test end-to-end (E2E) (Presentation Test)</h2>Test \"da punto a punto\" simulano l'interazione dell'utente, sono i più difficili da eseguire. Es.: cosa succede se l'utente clicca su un bottone in un certo momento del suo percorso?<br><br><h2>Test unitari (Domain Model Test)<br></h2>Sono test interni, si testa la funzionalità dell'applicazione. Sono ben incapsulati (da cui il nome unitari), quindi facili da scrivere e rapidi.<br><br><h2>Test di integrazione (Service Test)</h2>Verificare che l'applicazione java comunica con il database (o altro). Comunica? Trovo i record scritti nel DB? ecc. La difficoltà è che esternamente c'è uno stato che cambia col tempo, oppure occasionalmente il servizio è spento, oppure sono test che falliscono se eseguiti 2 volte.<br><br>"]],"Maven":[[["nuovo","progetto","pom.xml"],"Comando maven: <mark>mvn</mark><br><mark>archetype:generate</mark> (si basa su un \"archetipo\" e genererà un progetto)<br><mark>-DgroupId=it.formarete</mark> (definisce il gruppo a cui il progetto appartiene, è giusto un namespace)<br><mark>-DartifactId=mvc</mark> (definisce l'id del progetto che sarà il nome della cartella)<br><mark>-DarchetypeArtifactId=maven-archetype-quickstart</mark> (un archetipo di inizio, conviene non inserirlo, verranno proposti numerosi progetti, scrivere una parte del nome del progetto desiderato e poi specificare quale si desidera dal filtraggio effettuato - se si specifica, il rischio è che viene installata la versione più vecchia)<br><mark>-DinteractiveMode=false</mark> (meglio evitare)<br><br>Esempio tipico: <mark>mvn archetype:generate -DgroupId=it.nome_gruppo -DartifactId=nome_progetto</mark><br><br>Verrà creato nella cartella un file pom.xml dove ci sono configurazioni che, se modificate, ridefiniscono i parametri del progetto come le dipendenze e le versioni dei componenti.<br><br>N.B.<br>Se maven inizia a scaricare molti pacchetti può essere perché genericamente non li ha trovati, ne ha bisogno, e può cogliere un'occasione qualsiasi (es. lancio di un comando) per scaricarli.<br><br>Ctrl+C interrompe il comando<br>"],[["compilare","eseguire","package"],"<mark>mvn package</mark><br>compilare il pacchetto dentro la cartella target<br><br><mark>java -cp target/nome_progetto.jar it.nome_gruppo.App</mark><br>esegue un jar compilato da maven<br><br><mark>mvn clean</mark><br>cancella la cartella target (situazione pulita per ricompilare)<br><br>N.B.<br>Spesso viene detto \"BUILD SUCCESS\", ma non sempre a seguito di una compilazione.<br>"]],"NetBeans":[[["migrazione","versione"],"Se NetBeans si aggiorna:<br>- All'avvio chiede di importare i file della versione precedente, farlo.<br>- Per i progetti che non funzionano (es. run disabilitato), tasto destro > Solve project problems...<br><br>N.B.<br>Se non funziona comunque, un tentativo consiste nel copiare la cartella di configurazione di NetBeans (es. '10.0') e rinominarla per la nuova versione (es. '11.0').<br>"]]}
}