Capitolo - Mondadori Informatica
Transcript
Capitolo - Mondadori Informatica
TITOLO ORIGINALE JavaScript Step by Step, 2E Published with the authorization of Microsoft Corporation by: O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, California 95472 Copyright © 2010 Steve Suehring © 2011, Sperling & Kupfer Authorized Italian translation of the English edition of JavaScript Step by Step Second edition, ISBN 978-0-7356-4552-3 @ 2010 Steve Suehring. This translation is published and sold by permission of O’Reilly Media, Inc. ITALIAN Language Edition published by Sperling & Kupfer Editori SpA All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any means without the written permission of the publisher. Nessuna parte del testo può essere in alcun modo riprodotta senza autorizzazione scritta di Sperling & Kupfer Editori. Copertina per l’edizione italiana: Sperling & Kupfer Editori SpA Traduzione, revisione tecnica e realizzazione editoriale: Publish Art - Pavia Ogni cura è stata posta nella raccolta e nella verifica della documentazione contenuta in questo libro. Tuttavia né gli autori, né O’Reilly Media, Inc., né Microsoft Corporation, né Sperling & Kupfer Editori possono assumersi alcuna responsabilità derivante dall’utilizzo della stessa. Lo stesso dicasi per ogni persona o società coinvolta nella creazione, nella produzione e nella distribuzione di questo libro. Microsoft, Microsoft Press, ActiveX, Excel, FrontPage, Internet Explorer, PowerPoint, SharePoint, Webdings, Windows e Windows 7 sono marchi o marchi registrati di Microsoft Corporation altri nomi di prodotti e di aziende citati in queste pagine possono essere marchi dei rispettivi proprietari. Mondadori Informatica® è un marchio registrato da Arnoldo Mondadori Editore SpA Prima edizione Miti informatica: ottobre 2013 ISBN 978-88-6114-392-0 Edizioni: 1 2 3 4 5 20132014201520162017 6 Finito di stampare nel mese di ottobre 2013 presso ELCOGRAF S.p.A. Stabilimento di Cles (TN) Printed in Italy 7 8 Sommario XIII Sommario breve parte IV-V Scaricabile dal sito Mondadori Informatica Parte IV AJAX 17 18 19 20 e l’integrazione lato-server JavaScript e XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Applicazioni JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Un tocco di AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Qualche approfondimento su AJAX . . . . . . . . . . . . . . . . . . . . . . . 331 341 345 367 Parte VjQuery 21 22 23 Introduzione alle librerie e ai framework JavaScript . . . . . . . . . 383 Introduzione a jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 Effetti e plug-in di jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 Sommario parte IV-V Scaricabile dal sito Mondadori Informatica Parte IV AJAX e l’integrazione lato-server 17 JavaScript e XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 Utilizzare XML con JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 Un esempio di documento XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 Caricare un documento XML con JavaScript . . . . . . . . . . . . . . . . . . . . . . . . 332 Lavorare con dati XML da Excel 2007 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 Un’anteprima del futuro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 18 Applicazioni JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 Componenti delle applicazioni JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 I magnifici tre: visualizzazione, comportamento e dati . . . . . . . . . . . . . . . 341 JavaScript e le interfacce web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342 19 Un tocco di AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 Introduzione ad AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345 L’oggetto XMLHttpRequest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 Istanziare l’oggetto XMLHttpRequest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 Inviare una richiesta AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 Elaborare una risposta AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350 Elaborare risposte XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 Lavorare con JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 Elaborare le intestazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 Utilizzare il metodo POST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357 Caso di studio: ricerca e aggiornamento live . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 20 Qualche approfondimento su AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 Creare una tabella HTML con XML e CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 Stilizzare la tabella con CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 Cambiare gli attributi di stile con JavaScript . . . . . . . . . . . . . . . . . . . . . . . . 371 Creare una casella a discesa dinamica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 Accettare input dall’utente e AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 Parte VjQuery 21 Introduzione alle librerie e ai framework JavaScript . . . . . . . . . . . . . . . . . 383 Comprendere le librerie di programmazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383 Definire una propria libreria JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383 Librerie e framework JavaScript diffusi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 Yahoo! User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 MooTools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 XV Altre librerie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 22 Introduzione a jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 Presentazione di jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 Utilizzare jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 I due download di jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 Includere jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 Sintassi jQuery di base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388 Collegare jQuery all’evento load . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 Utilizzare i selettori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 Selezionare elementi tramite l’ID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 Selezionare elementi tramite la classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 Selezionare elementi tramite il tipo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 Selezionare elementi tramite la gerarchia . . . . . . . . . . . . . . . . . . . . . . . . . . 392 Selezionare elementi tramite la posizione . . . . . . . . . . . . . . . . . . . . . . . . . . 393 Selezionare elementi tramite un attributo . . . . . . . . . . . . . . . . . . . . . . . . . . 396 Selezionare elementi dei form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 Altri selettori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 Funzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 Attraversare il DOM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398 Lavorare con gli attributi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 Modificare il testo e l’HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403 Inserire elementi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404 Funzioni callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404 Eventi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405 Associare e disassociare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405 Eventi del mouse e hover . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407 Altri gestori di evento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408 AJAX e jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409 Errori e timeout AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 Inviare dati al server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 Altre opzioni importanti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413 Altro codice jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414 23 Effetti e plug-in di jQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 Funzionalità centrali per migliorare l’usabilità . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 Effetti nativi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 jQuery UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Utilizzare jQuery UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Drag-and-drop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 Accordion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 Ulteriori informazioni su jQuery UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 428 XVI Appendice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429 Parte IV AJAX e l’integrazione lato-server Capitolo 17: JavaScript e XML Capitolo 18: Applicazioni JavaScript Capitolo 19: Un tocco di AJAX Capitolo 20: Qualche approfondimento su AJAX 17 Java PpP.indd 329 329 28/04/11 16:00 17 Java PpP.indd 330 28/04/11 16:00 Capitolo 17 JavaScript e XML Dopo aver letto questo capitolo, sarete in grado di: n Esaminare le funzioni per aprire un documento Extensible Markup Language (XML) utilizzando JavaScript. n Visualizzare un documento XML come tabella Hypertext Markup Language (HTML). n Visualizzare un foglio di calcolo XML di Microsoft Office Excel 2007 utilizzando JavaScript. Utilizzare XML con JavaScript XML è un linguaggio che consiste quasi completamente di tag definiti dall’utente. Poiché i tag definiti dall’utente rendono l’XML estremamente personalizzabile, l’XML è utilizzato di frequente come formato file per lo scambio dei dati. Una considerazione importante per i programmatori JavaScript è che l’XML rappresenta la X dell’acronimo AJAX (Asynchronous JavaScript and XML). AJAX è un metodo molto diffuso per creare applicazioni web interattive. Ulteriori informazioni su AJAX sono riportate nei due capitoli successivi: Il capitolo 19, “Un tocco di AJAX”, e il capitolo 20, “Qualche approfondimento su AJAX”. XML è uno standard aperto definito dal World Wide Web Consortium (W3C) ed è attualmente alla sua quarta edizione. Questa sezione esamina brevemente l’XML in quanto appartenente a JavaScript. Potete trovare ulteriori informazioni su XML sul sito di XML Working Group, all’indirizzo http://www.w3.org/XML/Core/ o sul sito web di Microsoft, all’indirizzo http://msdn.microsoft.com/xml/ (le informazioni sono in inglese). Un esempio di documento XML I documenti XML consistono di elementi sistemati in una struttura di documento. Questi elementi hanno una sintassi propria, comprendente il fatto che essi richiedono un tag iniziale e un tag finale. Per il programmatore web l’aspetto di un documento (definito nel testo fra i tag) potrebbe essere familiare. Ecco un documento XML di esempio, che potete trovare anche in books.xml nella cartella Chapter17 fra i file di esempio: <books> <book> <title>MySQL Bible</title> <author>Steve Suehring</author> <isbn>9780764549328</isbn> <publisher>Wiley Publishing Inc.</publisher> </book> <book> <title>JavaScript Step by Step</title> 17 Java PpP.indd 331 331 28/04/11 16:00 332 Parte IV AJAX e l’integrazione lato-server <author>Steve Suehring</author> <isbn>9780735624498</isbn> <publisher>Microsoft Press</publisher> </book> </books> La struttura globale del documento deve soddisfare determinati criteri, perché il documento possa qualificarsi come documento ben formato. Come potete vedere nell’esempio, ogni elemento ha un proprio tag iniziale seguito da un corrispondente tag finale. Gli elementi possono anche essere nidificati l’uno nell’altro. Molte di queste regole sono simili alle regole dell’HTML. I documenti XML possono contenere anche attributi, perciò è valido anche il seguente codice: <?xml version="1.0"?> <book title="JavaScript Step by Step" author="Steve Suehring" isbn="9780735624498" publisher="Microsoft Press" /> Caricare un documento XML con JavaScript Potete caricare e manipolare i documenti XML utilizzando JavaScript. Questa sezione spiega come farlo. Importare il documento Potete importare un documento XML utilizzando uno fra due approcci, a seconda dei browser che volete supportare. Per i browser più recenti, fra cui Chrome, Firefox e le ultime versioni di Windows Internet Explorer, potete utilizzare l’oggetto XMLHTTPRequest(), mentre le vecchie versioni di Internet Explorer utilizzano l’oggetto ActiveXObject. Il seguente codice carica il documento books.xml in un modo compatibile con più browser: if (window.XMLHttpRequest) { var httpObj = new XMLHttpRequest(); } else { var httpObj = new ActiveXObject("Microsoft.XMLHTTP"); } httpObj.open("GET","books.xml",false); httpObj.send(); var xmlDocument = httpObj.responseXML; 17 Java PpP.indd 332 28/04/11 16:00 Capitolo 17 JavaScript e XML 333 Visualizzare il documento Spesso i dati XML possono essere visualizzati al meglio in formato tabella o foglio di calcolo. La figura 17.1 mostra il file books.xml in Excel 2007. Figura 17.1 Un file XML rappresentato in un foglio di calcolo. Una tabella HTML è utile per rappresentare in un browser gli stessi dati mostrati nella figura 17.1. Visualizzare dati XML utilizzando JavaScript richiede soprattutto alcune conoscenze del Document Object Model (DOM), e nessun’altra speciale funzione o metodo oltre quelli richiesti per caricare il documento stesso, che avete già imparato. Il successivo esempio crea una funzione chiamata displayData() che mostra informazioni in formato tabella. 17 Java PpP.indd 333 28/04/11 16:00 334 Parte IV AJAX e l’integrazione lato-server La proprietà readyState Nelle versioni precedenti di questo libro utilizzavamo la proprietà readyState per determinare quando il documento XML era caricato. La proprietà readyState è un integer che contiene uno fra cinque valori indicanti lo stato corrente della richiesta di documento da elaborare. La tabella 17.1 mostra i valori e le corrispondenti descrizioni di readyState. Tabella 17.1 La proprietà readyState Valore Descrizione 0 Non inizializzato. Aperto ma non ancora chiamato. 1 Aperto. Inizializzato ma non ancora inviato. 2 Inviato. La richiesta è stata inviata. 3 In ricezione. La risposta è in fase di ricezione. 4 Caricato. La risposta è stata completamente ricevuta. Ulteriori informazioni sulla proprietà readyState e l’evento onreadystatechange sono riportate nel capitolo 18, “Applicazioni JavaScript”. Per visualizzare i nodi e i nodi figlio in un documento XML, occorre eseguire un’iterazione sui livelli del documento e creare il documento di output. La successiva funzione che vedremo lo fa iterando su un documento XML gerarchico al fine di visualizzare i dati del documento in una tabella HTML. Questo codice continua l’esempio già mostrato, in cui una variabile chiamata xmlDocument viene creata e caricata con un documento XML chiamato books.xml: function displayData(xmlDocument) { var xmlEl = xmlDocument.getElementsByTagName("book"); var table = document.createElement("table"); table.border = "1"; var tbody = document.createElement("tbody"); // Append the body to the table table.appendChild(tbody); // Create the table cells for the new row for (i = 0; i < xmlEl.length; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild.nodeValue); 17 Java PpP.indd 334 28/04/11 16:00 Capitolo 17 JavaScript e XML 335 td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); } document.getElementById("xmldata").appendChild(table); } Per mettere insieme tutto il codice in una pagina web, associate a un evento le funzioni che caricano e visualizzano il file XML. Il listato 17.1 (potete trovare questo codice anche in listing17-1.html fra i file di esempio) crea una nuova funzione chiamata getXML e la associa all’evento load dell’oggetto window. Il codice che associa l’evento è riportato in grassetto. LiSTATO17.1 Visualizzare dati XML in una tabella HTML. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd"> <html> <head> <title>Books</title> <script type="text/javascript" src="ehandler.js"></script> </head> <body id="mainBody"> <div id="xmldata"></div> <script type="text/javascript"> function displayData(xmlDocument) { var xmlEl = xmlDocument.getElementsByTagName("book"); var table = document.createElement("table"); table.border = "1"; var tbody = document.createElement("tbody"); // Append the body to the table table.appendChild(tbody); // Create table row for (i = 0; i < xmlEl.length; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild.nodeValue); td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); 17 Java PpP.indd 335 28/04/11 16:00 336 Parte IV AJAX e l’integrazione lato-server } document.getElementById("xmldata").appendChild(table); } function getXML() { if (window.XMLHttpRequest) { var httpObj = new XMLHttpRequest(); } else { var httpObj = new ActiveXObject("Microsoft.XMLHTTP"); } httpObj.open("GET","books.xml",false); httpObj.send(); var xmlDocument = httpObj.responseXML; displayData(xmlDocument); } var mainBody = document.getElementById("mainBody"); EHandler.add(mainBody, "load", function() { getXML(); }); </script> </body> </html> Quando è visualizzata tramite un sito web, la tabella mostra i dati in modo molto simile a un foglio di calcolo, come si vede nella figura 17.2. FigUrA17.2 Rappresentare books.xml in una tabella HTML. Esaminando il codice del listato 17.1 vediamo un grosso loop for che percorre la gerarchia XML, creando le righe della tabella mentre procede. Un fatto da notare è che il loop cerca solo i nodi Element all’interno del documento XML utilizzando il seguente codice: 17 Java PpP.indd 336 28/04/11 16:00 Capitolo 17 JavaScript e XML 337 // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } Il nodeType 1 rappresenta un nodo XML Element. Se il tipo di nodo in fase di esame nel loop non è element, il codice passa alla parte successiva del documento. Nella visualizzazione della figura 17.2 potreste notare che non sono presenti le intestazioni di colonna. Per mostrarle occorre aggiungere altro codice. La procedura che segue vi mostra come fare. Aggiungere le intestazioni di colonna da un documento XML 1. Utilizzando Microsoft Visual Studio, Eclipse o un altro editor, modificate il file books. htm nella cartella Chapter17 dei file di esempio (a questo punto della procedura, se lo visualizzate in un browser web, books.htm dovrebbe essere simile alla figura 17.2). 2. In books.htm aggiungete il codice riportato in grassetto di seguito al metodo displayData() (potete trovare questo codice anche in books.txt fra i file di esempio), sostituendo il commento TODO: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd"> <html> <head> <title>Books</title> <script type="text/javascript" src="ehandler.js"></script> </head> <body id="mainBody"> <div id="xmldata"></div> <script type="text/javascript"> function displayData(xmlDocument) { var xmlEl = xmlDocument.getElementsByTagName("book"); var table = document.createElement("table"); table.border = "1"; var tbody = document.createElement("tbody"); // Append the body to the table table.appendChild(tbody); var row = document.createElement("tr"); for (colHead = 0; colHead < xmlEl[0].childNodes.length; colHead++) { if (xmlEl[0].childNodes[colHead].nodeType != 1) { continue; } var tableHead = document.createElement("th"); var colName = document.createTextNode(xmlEl[0].childNodes[colHead].nodeName); tableHead.appendChild(colName); row.appendChild(tableHead); } // Append the row to the body 17 Java PpP.indd 337 28/04/11 16:00 338 Parte IV AJAX e l’integrazione lato-server tbody.appendChild(row); // Create table row for (i = 0; i < xmlEl.length; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild.nodeValue); td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); } document.getElementById("xmldata").appendChild(table); } function getXML() { if (window.XMLHttpRequest) { var httpObj = new XMLHttpRequest(); } else { var httpObj = new ActiveXObject("Microsoft.XMLHTTP"); } httpObj.open("GET","books.xml",false); httpObj.send(); var xmlDocument = httpObj.responseXML; displayData(xmlDocument); } var mainBody = document.getElementById("mainBody"); EHandler.add(mainBody, "load", function() { getXML(); }); </script> </body> </html> 3. Visualizzate la pagina in un browser web. Dovrebbe essere simile alla figura che segue: 17 Java PpP.indd 338 28/04/11 16:00 Capitolo 17 JavaScript e XML 339 Lavorare con dati XML da Excel 2007 Excel 2007 possiede diverse funzionalità che facilitano il lavoro con i dati XML. Con Excel è possibile sia importare sia esportare i dati XML. Quando si esportano dati da Excel, in effetti, il programma non aggiunge nulla di proprietario al documento XML. Ecco l’aspetto del file books.xml esportato da Excel 2007 (potete trovare questo codice anche in newbooks. xml fra i file di esempio): <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <book> <title>MySQL Bible</title> <author>Steve Suehring</author> <isbn>9780764549328</isbn> <publisher>Wiley Publishing Inc.</publisher> </book> <book> <title>JavaScript Step by Step</title> <author>Steve Suehring</author> <isbn>9780735624498</isbn> <publisher>Microsoft Press</publisher> </book> </books> Poiché Excel 2007 è XML-friendly, la funzione displayData() già vista in questo capitolo può agire senza richiedere modifiche sui dati XML esportati da Excel 2007. Per gli sviluppatori che hanno lavorato in passato con i formati proprietari, questa è una gradita sorpresa. 17 Java PpP.indd 339 28/04/11 16:00 340 Parte IV AJAX e l’integrazione lato-server Un’anteprima del futuro Essendo XML la X dell’acronimo AJAX, si può facilmente dedurre che AJAX è molto di più che JavaScript e XML. AJAX può funzionare con tipi di dati diversi da XML, e nel capitolo 19 lavorerete con AJAX partendo dalle brevi premesse presentate in questo capitolo. Nel capitolo 20 esaminerete l’integrazione di JavaScript, AJAX e Cascading Style Sheets (CSS) che vi permette di presentare i dati recuperati con JavaScript. Esercizi 1. Utilizzate il codice dell’esercizio sulla visualizzazione di questo capitolo per visualizzare la tabella dopo che è stato fatto clic su un collegamento anziché quando la pagina viene caricata. 2. Utilizzate il codice dell’esercizio sulla visualizzazione di questo capitolo per visualizzare la tabella, ma impiegate il DOM per assegnare colori alterni alle righe, in modo che una riga ogni due abbia lo sfondo grigio. Vi do un indizio: #aaabba è la rappresentazione esadecimale del colore grigio. 17 Java PpP.indd 340 28/04/11 16:00 Capitolo 18 Applicazioni JavaScript Dopo aver letto questo capitolo, sarete in grado di: n Comprendere i componenti di un’applicazione basata su JavaScript. Componenti delle applicazioni JavaScript Creare un’applicazione basata sul browser con l’aspetto sofisticato di un’applicazione desktop richiede spesso l’uso di JavaScript. Una tale applicazione possiede alcune caratteristiche e capacità di risposta simili a quelle di un’applicazione desktop, sebbene questa risieda sul computer locale anziché funzionare tramite un browser web. Questo breve capitolo presenta una panoramica dei componenti che formano un’applicazione basata su JavaScript. L’obiettivo è aiutarvi a comprendere l’architettura sottostante e alcune delle complessità necessarie per creare questo tipo di applicazione. I magnifici tre: visualizzazione, comportamento e dati Un’applicazione web presenta tre componenti principali: n Visualizzazione L’aspetto e lo spirito della pagina. n Comportamento Ciò che l’interfaccia applicativa fa, ovvero ciò che accade quando l’utente fa clic su un elemento sulla pagina o interagisce in altro modo con la pagina. n Dati Il componente server che contiene i dati ed esegue le azioni il cui risultato appare sulla pagina. Il codice JavaScript gestisce tipicamente i primi due componenti del precedente elenco, visualizzazione e comportamento, in modo da influenzare l’interfaccia o reagire quando un utente esegue un’azione sulla pagina. JavaScript lavora anche con i dati restituiti dal server, ma di solito lo fa soltanto per alterare in qualche modo la visualizzazione. Per esempio una chiamata a un servizio web che restituisce la temperatura o le condizioni atmosferiche correnti potrebbe utilizzare JavaScript per cambiare un’icona quando è soleggiato. Le sezioni che seguono esaminano ciascuno di questi tre elementi in maggiore dettaglio. 18 Java PpP.indd 341 341 28/04/11 16:00 342 Parte IV AJAX e l’integrazione lato-server Visualizzazione: layout di pagina La visualizzazione della pagina web comprende il layout di pagina e qualsiasi cosa correlata all’aspetto e allo spirito della pagina e del sito, compresa la combinazione di colori, le immagini, la stilizzazione dei menu (se hanno angoli arrotondati o squadrati e così via), il posizionamento dei pulsanti e il contenuto, i colori dei font e l’utilizzo delle immagini. JavaScript può influenzare tutti questi elementi, come avete visto nei capitoli precedenti su Cascading Style Sheets (CSS) e la convalida dei form. Questi elementi rappresentano l’interesse principale del web design e ricevono la massima attenzione da parte degli utenti, perciò dovreste considerarli nel determinare i requisiti del vostro sito. Comportamenti: controllare cosa succede e quando Uno dei fattori più importanti nel determinare l’esperienza dell’utente è anche uno degli elementi più spesso trascurati nella progettazione di un’applicazione web: Il comportamento dell’interfaccia applicativa, che controlla cosa accade quando gli utenti interagiscono con un dato elemento. Considerate questi due semplici scenari: n Quando un visitatore fa clic sul pulsante Submit di un web form, il pulsante rimane attivo o viene disabilitato? n Quando un campo di input ottiene lo stato attivo, dovrebbe cambiare colore o essere evidenziato? Anche questi comportamenti minori possono migliorare notevolmente l’esperienza dell’utente se sono progettati adeguatamente. Tuttavia quando si lavora alla progettazione di un sito, questi comportamenti sono spesso dimenticati, ignorati o applicati in modo incoerente per lasciare più spazio all’aspetto e allo spirito o alla mera progettazione del sito. Dati: consumo, visualizzazione e convalida JavaScript, almeno nel suo utilizzo trattato in questo libro, non interagisce direttamente con un database o un server. Naturalmente JavaScript lo fa attraverso Asynchronous JavaScript e XML (AJAX) e attraverso i servizi web, ma questi processi richiedono che il codice latoserver restituisca i dati al JavaScript chiamante. Come la porzione del sito relativa alla visualizzazione, i componenti di dati di back-end lato-server dovrebbero ricevere un’adeguata attenzione quando progettate un’applicazione web. Dalla progettazione di database alla programmazione della logica di business, questo codice back-end richiede attenzione. JavaScript e le interfacce web I programmatori utilizzano JavaScript per creare front-end che garantiscono un’esperienza di qualità all’utente. Microsoft Bing Maps (in precedenza Live Search Maps) è un esempio di applicazione web che fa pesante affidamento su JavaScript. La figura 18.1 mostra une esempio di Microsoft Bing Maps, che potete trovare all’indirizzo http://www.bing.com/maps/. 18 Java PpP.indd 342 28/04/11 16:00 Capitolo 18 Applicazioni JavaScript 343 Figura 18.1 L’interfaccia Bing Maps utilizza JavaScript per fornire una buona interattività. Gli utenti possono trascinare la visualizzazione della mappa in modo molto simile a come interagirebbero con un’applicazione desktop. La mappa è composta di porzioni a varie risoluzioni. Quando un utente trascina la mappa, il browser invia molte richieste HTTP al server web Virtual Earth richiedendo porzioni aggiuntive che il browser visualizza poi velocemente. Il motore di ricerca Bing utilizza anche una funzionalità di ricerca progressiva basata sulla digitazione simile a quella di altri motori di ricerca come Google. Se iniziate a digitare nella casella di testo principale su http://www.bing.com, il browser invia immediatamente una richiesta HTTP al server per individuare ricerche simili, come si vede nella figura 18.2. Figura 18.2 La funzionalità di ricerca progressiva basata sulla digitazione utilizza JavaScript per ottenere un elenco di ricerche corrispondenti dal server. 18 Java PpP.indd 343 28/04/11 16:00 344 Parte IV AJAX e l’integrazione lato-server Tutti questi elementi del motore di ricerca Bing utilizzano JavaScript. Un numero infinito di altre interfacce web fanno affidamento su JavaScript per migliorare l’esperienza dell’utente controllando il livello comportamento della pagina. La parte rimanente di questo libro vi introduce alla creazione di questo tipo di applicazioni con JavaScript. Il capitolo 19, “Un tocco di AJAX”, e il capitolo 20, “Qualche approfondimento su AJAX”, vi insegnano come creare una semplice interfaccia di ricerca progressiva basata sulla digitazione utilizzando JavaScript. Introducono inoltre AJAX e mostrano esempi di come si lavora con i dati per creare applicazioni. Il capitolo 21, “Introduzione alle librerie e ai framework JavaScript”, e il capitolo 22, “Introduzione a jQuery”, presentano le librerie JavaScript, concentrandosi su jQuery, che potete utilizzare per semplificare molte attività correlate alla scrittura di complesse applicazioni JavaScript. 18 Java PpP.indd 344 28/04/11 16:00 Capitolo 19 Un tocco di AJAX Dopo aver letto questo capitolo, sarete in grado di: n Comprendere i fondamenti del paradigma di programmazione Asynchronous JavaScript and XML (AJAX). n Comprendere la differenza fra chiamate AJAX sincrone e asincrone. n Utilizzare AJAX per recuperare dati. n Utilizzare AJAX con diversi metodi Hypertext Transfer Protocol (HTTP) per recuperare risposte da un server. Introduzione ad AJAX AJAX descrive il paradigma di programmazione che combina JavaScript e un server web. Gli sviluppatori utilizzano AJAX per creare applicazioni web altamente interattive come Microsoft Virtual Earth. Senza AJAX, un’applicazione web potrebbe far attendere il visitatore mentre una risposta viene messa insieme dal server web. Un’applicazione basata su AJAX invia richieste dal browser web al server web in background (in modo asincrono) mentre il visitatore utilizza l’applicazione. Questo rende l’applicazione più reattiva dal punto di vista dell’utente. In un’applicazione AJAX, JavaScript elabora la risposta e presenta i dati agli utenti. Quando è combinata con Cascading Style Sheets (CSS) e un buon layout, un’applicazione AJAX garantisce un’eccellente usabilità e la portabilità che soltanto un’applicazione web può offrire. Nonostante molte applicazioni AJAX possano sembrare complesse, gli effettivi processi di invio di una richiesta e gestione della risposta non sono molto complicati. Questo capitolo esplora come potete inviare richieste e ricevere risposte utilizzando un oggetto AJAX fondamentale: XMLHttpRequest. Un concetto centrale di AJAX è che occorre chiamare applicazioni lato-server per restituire dati. In questo capitolo presento una breve panoramica di come creare una tale applicazione utilizzando sia ASP.NET sia PHP (PHP è un acronimo ricorsivo che sta per PHP Hypertext Preprocessor). Se avete bisogno di ulteriore assistenza per la creazione della porzione latoserver di un’applicazione AJAX, potete ottenerla da varie fonti. Se state creando un’applicazione lato-server con tecnologie Microsoft, Microsoft Developer Network è un’importante risorsa che offre numerosi tutorial e un articolo introduttivo su AJAX (http://msdn.microsoft.com/it-it/magazine/cc163363.aspx). Microsoft Press pubblica inoltre molti eccellenti libri sulla creazione di applicazioni per il web. Uno di questi è 19 Java PpP.indd 345 345 28/04/11 16:02 346 Parte IV AJAX e l’integrazione lato-server Microsoft ASP.NET 3.5 Step By Step (Microsoft Press, 2008). Per conoscere altri titoli, visitate http://www.microsoft.com/mspress. Se state sviluppando un’applicazione lato-server con altre tecnologie come lo stack LAMP (Linux, Apache, MySQL, Perl/PHP/Python), cercare tutorial sul web è probabilmente il modo più semplice per iniziare velocemente a sviluppare per questa piattaforma. Il libro Learning Perl (O’Reilly, 2005) è una valida risorsa per imparare i fondamenti del linguaggio di programmazione Perl. Nota Se vi piace il mio stile di scrittura, ho scritto anche il libro Beginning Perl Web Development (Apress, 2005), che tratta l’utilizzo di Perl per lavorare con le applicazioni web. Il sito web principale di PHP (http://www.php.net) è un ottimo punto di partenza per informazioni su PHP; per Python date un’occhiata al relativo sito web (http://www.python.org). Le informazioni sono in inglese. L’oggetto XMLHttpRequest L’oggetto XMLHttpRequest ha un ruolo centrale per la creazione di un’applicazione AJAX. Sebbene le implementazioni di JavaScript siano differenti, l’ECMAScript e il World Wide Web Consortium (W3C) hanno standardizzato molti aspetti di esso, a parte l’oggetto XMLHttpRequest, che non è mai stato sottoposto a un processo di standardizzazione. Nonostante questo, dal rilascio di Windows Internet Explorer 7, l’oggetto XMLHttpRequest si utilizza allo stesso modo su tutti i principali browser. Microsoft ha implementato in origine l’oggetto XMLHttpRequest in Microsoft Internet Explorer 5.0. Se un visitatore utilizza una precedente versione del browser, le applicazioni che includono XMLHttpRequest non funzioneranno. Nelle versioni di Internet Explorer precedenti la 7, l’oggetto XMLHttpRequest era istanziato come un oggetto ActiveXObject, ma altri browser hanno implementato l’oggetto XMLHttpRequest come un oggetto JavaScript incorporato nel browser. Questo significa che se le vostre applicazioni devono lavorare con versioni di Internet Explorer precedenti la 7, dovete istanziare l’oggetto XMLHttpRequest per quei browser in un modo diverso, come vi mostrerò più avanti in questo capitolo. La sezione successiva, “Istanziare l’oggetto XMLHttpRequest”, vi mostra come testare l’esistenza di XMLHttpRequest e come istanziarlo in tutte le versioni di Internet Explorer. Istanziare l’oggetto XMLHttpRequest Internet Explorer 7 e versioni successive, e tutti gli altri browser principali che supportano XMLHttpRequest, istanziano l’oggetto XMLHttpRequest nello stesso modo: var req = new XMLHttpRequest(); 19 Java PpP.indd 346 28/04/11 16:02 Capitolo 19 Un tocco di AJAX 347 Per le versioni di Internet Explorer precedenti la 7, dovete istanziare invece un ActiveXObject. Il modo in cui lo fate varia però a seconda della versione della libreria XMLHTTP installata sul client. Perciò dovete fare un po’ di giochetti con il codice per istanziare un oggetto XMLHttpRequest in queste vecchie versioni di Internet Explorer. Il codice del listato 19.1 è una funzione compatibile con più browser che istanzia un oggetto XMLHttpRequest su più browser. LISTATO19.1 Istanziare un oggetto XMLHttpRequest su più browser. function readyAJAX() { try { return new XMLHttpRequest(); } catch(e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { return "A newer browser is needed."; } } } } La funzione nel listato 19.1 utilizza più livelli di blocchi try/catch per istanziare un XMLHttpRequest, indipendentemente dal fatto che il visitatore utilizzi Internet Explorer o un altro browser. Se la chiamata nativa di XMLHttpRequest fallisce, questo significa che il visitatore sta utilizzando un browser Internet Explorer precedente la versione 7. In tal caso l’errore è intercettato e viene tentato uno dei metodi di istanziazione di XMLHttpRequest basati su ActiveXObject. Se nessuno di questi metodi ha successo, la ragione più probabile è che il browser sia troppo vecchio per supportare XMLHttpRequest. L’articolo “About Native XMLHTTP” su MSDN descrive vari aspetti relativi alla storia e alla sicurezza dell’oggetto XMLHttpRequest in Internet Explorer. Questo articolo è disponibile all’indirizzo http://msdn2.microsoft.com/en-us/library/ms537505.aspx (le informazioni sono in inglese). Per chiamare la funzione readyAJAX() mostrata nel listato 19.1 si procede così: var requestObj = readyAJAX(); La variabile requestObj ora contiene l’oggetto XMLHttpRequest restituito dalla funzione oppure, se la funzione non è riuscita a creare l’oggetto, la variabile requestObj contiene la stringa “A newer browser is needed”. 19 Java PpP.indd 347 28/04/11 16:02 348 Parte IV AJAX e l’integrazione lato-server Inviare una richiesta AJAX Con un nuovo oggetto XMLHttpRequest fra le mani, potete inviare richieste al server web e ottenere risposte. Per inviare la richiesta, utilizzate una combinazione dei metodi open() e send() dell’oggetto XMLHttpRequest. Ci sono due modi fondamentalmente diversi per inviare richieste AJAX: sincrono e asincrono. Quando è inviato in un modo asincrono, il codice di richiesta si limita ad attendere la risposta, un processo chiamato blocco. Per una richiesta sincrona perciò il codice di richiesta si bloccherà, impedendo così l’ulteriore elaborazione o esecuzione di altro JavaScript mentre lo script attende la risposta dal server web. Questo processo presenta ovvi svantaggi quando la risposta va persa in transito o semplicemente è lenta. Con le richieste asincrone il codice di richiesta non viene bloccato. Il chiamante può controllare lo stato della richiesta per vedere quando la richiesta è completata. Ulteriori informazioni sulle richieste asincrone sono riportate più avanti in questo capitolo; è più facile iniziare dalle richieste sincrone. Per poter inviare una richiesta, dovete prima crearla. Per farlo, utilizzate il metodo open, che presenta tre argomenti: il metodo di richiesta (GET, POST, HEAD o altri), lo Uniform Resource Locator (URL) a cui la richiesta sarà inviata e un boolean true o false, indicante se volete inviare la richiesta rispettivamente in modo asincrono o sincrono. Presupponendo che il vostro oggetto richiesta sia stato recuperato utilizzando la funzione readyAJAX() e inserito in una variabile denominata requestObj, una tipica chiamata asincrona del metodo open potrebbe essere questa: var url = "http://www.braingia.org/getdata.php"; requestObj.open("GET", url, true); La stessa chiamata, inviata in modo sincrono, è questa: var url = "http://www.braingia.org/getdata.php"; requestObj.open("GET", url, false); La richiesta viene inviata effettivamente con il metodo send, come segue: requestObj.send(); Nota Se i parametri inviati con la richiesta includono caratteri speciali, come spazi o altri caratteri riservati della URI RFC, dovete prima effettuarne l'escape tramite la notazione %. L'argomento è trattato nei dettagli nella RFC 3986, che potete trovare all'indirizzo ftp://ftp. rfc-editor.org/in-notes/rfc3986.txt (le informazioni sono in inglese). Ulteriori informazioni sono disponibili anche all'indirizzo http://msdn2.microsoft.com/en-us/library/aa226544(sql.80).aspx (le informazioni sono in inglese). 19 Java PpP.indd 348 28/04/11 16:02 Capitolo 19 Un tocco di AJAX 349 Come funziona il web in meno di 500 parole L’Hypertext Transfer Protocol (HTTP) è il linguaggio del web. L’HTTP, attualmente definito dalla RFC 2616, descrive un protocollo per lo scambio di informazioni utilizzando richieste provenienti dai client e risposte provenienti dai server. Le richieste dei client come i browser web contengono un determinato set di intestazioni che definiscono il metodo utilizzato per il recupero, l’oggetto recuperato e la versione del protocollo da utilizzare. Altre intestazioni contengono il nome host del server web, le lingue richieste, il nome del browser e altre informazioni che il client ritiene rilevanti per la richiesta. Segue una semplice richiesta in HTTP versione 1.1 che mostra soltanto la più importante di queste intestazioni: GET / HTTP/1.1 Host: www.braingia.org Questa richiesta specifica il metodo GET per recuperare il documento che si trova nella posizione di directory / (root) utilizzando HTTP versione 1.1. La seconda riga, chiamata comunemente intestazione Host, è l’URL http://www.braingia.org. Questa intestazione dice al server web quale sito web è richiesto. In una richiesta possono essere utilizzati molti diversi metodi; i tre più comuni sono GET, POST e HEAD. Il client e il server scambiano anche cookie HTTP come parte delle intestazioni. I cookie sono inviati nella richiesta e altri potrebbero essere ricevuti nella risposta. Quando il server web per http://www.braingia.org riceve una richiesta come questa, invia intestazioni di risposta per indicare come ha gestito la richiesta. In questo caso il server web invia intestazioni di risposta simili alle seguenti: HTTP/1.1 200 OK Date: Sat, 12 Mar 2011 01:04:34 GMT Server: Apache/1.3.33 (Debian GNU/Linux) mod_perl/1.29 PHP/4.3.10-22 Transfer-Encoding: chunked Content-Type: text/html; charset=iso-8859-1 Il documento richiesto segue le intestazioni di risposta. La prima e più importante intestazione indica lo stato della risposta. Nell’esempio la risposta è 200, che significa OK. Altre comuni risposte sono 404 (che indica che il documento richiesto non è stato trovato), 302 (che indica una redirezione) e 500 (che indica che si è verificato un errore del server). Conoscere queste nozioni di base di HTTP è importante per capire come costruire richieste AJAX e come risolvere problemi relativi a queste richieste quando qualcosa va male. Potete trovare ulteriori informazioni su HTTP, compresi vari codici di risposta, nella RFC 2616 all’indirizzo ftp://ftp.rfc-editor.org/in-notes/rfc2616.txt (le informazioni sono in inglese). 19 Java PpP.indd 349 28/04/11 16:02 350 Parte IV AJAX e l’integrazione lato-server Elaborare una risposta AJAX È più facile lavorare con la risposta quando la richiesta è inviata in modo sincrono, perché l’esecuzione dello script si arresta mentre attende la risposta. La variabile requestObj fornisce utili metodi per elaborare una risposta, fra cui consentire l’accesso ai codici di stato e al testo dello stato inviato dal server. Indipendentemente dal fatto che la richiesta sia sincrona o asincrona, dovreste valutare il codice di stato per assicurarvi che la risposta abbia avuto successo (situazione indicata solitamente dal codice di stato 200). Il metodo responseText contiene il testo della risposta ricevuta dal server web. Immaginate per esempio che un’applicazione server restituisca la somma di due numeri. La chiamata dell’applicazione per sommare i numeri 2 e 56 è questa: http://www.braingia.org/addtwo.php?num1=2&num2=56 Ecco una chiamata asincrona e il recupero della risposta: requestObj.open("GET", "http://www.braingia.org/addtwo.php?num1=2&num2=56", false); requestObj.send(); if (requestObj.status == 200) { alert(requestObj.responseText); } else { alert(requestObj.statusText); } In questo esempio presupponete che il requestObj sia creato utilizzando la funzione readyAJAX() che avete visto in precedenza. Il codice precedente chiama quindi il metodo open utilizzando una richiesta GET all’URL specificato (http://www.braingia.org/addtwo. php?num1=2&num2=56). La richiesta viene inviata in modo sincrono perché l’ultimo argomento del metodo open è false. Quindi il codice chiama il metodo send, che effettivamente invia la richiesta al server web. Quando il client riceve la risposta dal server web, chiama il metodo status per controllare il valore di stato. Se il codice di risposta è 200, che indica successo, viene mostrato il responseText, che contiene la risposta proveniente dal server. Se il codice di stato della risposta è diverso da 200, viene visualizzato il testo di stato. Elaborare una risposta asincrona è un po’ più complicato. Quando una richiesta è inviata in modo asincrono, l’esecuzione dello script continua. Perciò non è possibile prevedere quando sarà notificato allo script che la risposta è stata ricevuta. Per conoscere lo stato della risposta, potete utilizzare l’evento onreadystatechange per attivare il codice che controlla la proprietà readyState dell’evento al fine di determinare lo stato del ciclo richiesta/risposta. Ricorderete dal capitolo 17, “JavaScript e XML”, che la proprietà readyState ha cinque stati, descritti nella tabella 19.1. 19 Java PpP.indd 350 28/04/11 16:02 Capitolo 19 Un tocco di AJAX Tabella 19.1 Valori 351 della proprietà readyState Valore Descrizione 0 Non inizializzato. Aperto ma non ancora chiamato. 1 Aperto. Inizializzato ma non ancora inviato. 2 Inviato. La richiesta è stata inviata. 3 In ricezione. La risposta è in fase di ricezione. 4 Caricato. La risposta è stata completamente ricevuta. Per scopi pratici, l’unico stato che conta per i programmatori JavaScript e AJAX è lo stato 4—Loaded (caricato). Tentando di elaborare una risposta che presenta un valore readyState diverso da 4 viene generato un errore. Tipicamente si utilizza una funzione anonima per gestire l’evento onreadystatechange per le chiamate AJAX asincrone. La funzione controlla per vedere se la proprietà readyState ha raggiunto il valore 4, quindi controlla per assicurarsi che lo stato sia 200, che indica successo. Il codice presenta questo formato: requestObj.onreadystatechange = function() { if (requestObj.readyState == 4) { if (requestObj.status == 200) { alert(requestObj.responseText); } else { alert(requestObj.statusText); } } } Nel successivo esercizio creerete un oggetto XMLHttpRequest e invierete una richiesta a un server web per recuperare il titolo di un libro in base al suo ISBN. Avete bisogno di un server web e del codice per il server web per stampare la risposta, in quanto le richieste inviate utilizzando XMLHttpRequest sono soggette al criterio JavaScript della stessa origine. Il criterio della stessa origine prevede che le richieste vadano soltanto verso i server dello stesso dominio da cui lo script chiamante è stato caricato. In altre parole, poiché sto eseguendo lo script in questo esempio direttamente dal mio server web all’indirizzo http:// www.braingia.org, il mio script è in grado di chiamare quel server e recuperare una risposta. Se invece avete tentato di chiamare un URL su un altro server web, il criterio della stessa origine impedisce che lo script recuperi la risposta. Nota Un modo per aggirare la funzionalità di sicurezza della stessa origine è utilizzare un proxy HTTP o scrivere il programma lato-server in modo che invii una richiesta per conto del programma chiamante; questo argomento esula però dallo scopo di questo libro. Per il successivo esercizio lo script o programma eseguito sul server deve restituire la frase “JavaScript Step by Step” quando riceve una richiesta GET con un argomento nome/valore con il seguente valore: 19 Java PpP.indd 351 28/04/11 16:02 352 Parte IV AJAX e l’integrazione lato-server isbn=9780735624498 Nella sua versione più semplice per esempio il programma lato-server potrebbe essere il seguente quando è implementato all’interno di una pagina Active Server Pages (ASP) basata su VBScript: <% dim isbn isbn=Request.QueryString("isbn") If isbn<>"" Then If isbn=="9780735624498" Then Response.Write("JavaScript Step by Step") End If End If %> Un programma funzionalmente simile scritto in PHP sarebbe il seguente: <?php $isbn = $_GET['isbn']; if (! $isbn) { print "That request was not understood."; } else if ($isbn == "9780735624498") { print "JavaScript Step by Step"; } ?> Nel seguente esercizio l’URL a cui la richiesta è inviata è predefinito, tuttavia dovete sostituire quell’URL con l’URL in cui si trova il vostro programma lato-server. A causa del criterio della stessa origine, il programma lato-server deve trovarsi all’interno dello stesso dominio della pagina che lo chiama. Inviare e ricevere con XMLHttpRequest 1. Create il vostro programma lato-server in modo che restituisca il titolo del libro quando riceve l’argomento isbn mostrato in precedenza. Potete farlo nel linguaggio che preferite (se ne avete bisogno, osservate i due esempi mostrati in precedenza). 2. Utilizzando Microsoft Visual Studio, Eclipse o un altro editor, modificate il file isbn.htm nella cartella Chapter19 dei file di esempio. 3. Nella pagina web sostituite il commento TODO con il codice in grassetto riportato di seguito (potete trovare il codice anche in isbn.txt fra i file di esempio): assicuratevi di sostituire la variabile url con l’URL appropriato per il vostro programma lato-server: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>ISBN</title> </head> 19 Java PpP.indd 352 28/04/11 16:02 Capitolo 19 Un tocco di AJAX 353 <body> <div id="data"></div> <script type="text/javascript"> function readyAJAX() { try { return new XMLHttpRequest(); } catch(e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { return "A newer browser is needed."; } } } } var requestObj = readyAJAX(); var url = "http://www.braingia.org/isbn.php?isbn=9780735624498"; requestObj.open("GET",url,true); requestObj.send(); requestObj.onreadystatechange = function() { if (requestObj.readyState == 4) { if (requestObj.status == 200) { alert(requestObj.responseText); } else { alert(requestObj.statusText); } } } </script> </body> </html> 4. Salvate e visualizzate in un browser web. Dovreste ricevere un avviso come il seguente: Congratulazioni! Avete elaborato il vostro primo XMLHttpRequest. 19 Java PpP.indd 353 28/04/11 16:02 354 Parte IV AJAX e l’integrazione lato-server Elaborare risposte XML Gli esempi di AJAX visti finora utilizzano tutti risposte in normale Hypertext Markup Language (HTML) e testo provenienti dal server web, perciò potreste recuperarle utilizzando il metodo responseText dell’oggetto XMLHttpRequest. Le applicazioni server invece possono anche restituire risposte XML, che potete elaborare nativamente utilizzando il metodo responseXML. In precedenza in questo capitolo, nel riquadro “Come funziona il Web in meno di 500 parole”, abbiamo visto un esempio di risposta del server web. La risposta del server conteneva questa intestazione Content-Type: Content-Type: text/html; charset=iso-8859-1 Per recuperare una risposta utilizzando il metodo responseXML, il server web deve inviare un Content-Type text/xml o application/xml come segue: Content-Type: application/xml Quando l’oggetto XMLHttpRequest riceve XML nativo come risposta, potete utilizzare i metodi del Document Object Model (DOM) per elaborare la risposta. Il metodo responseXML storicamente ha creato problemi e utilizzarlo può generare comportamenti inaspettati, a seconda del browser e del sistema operativo. Inoltre responseXML non è ampiamente supportato quanto altri metodi JavaScript. Utilizzare responseXML significa combinare le tecniche XMLHttpRequest già viste in questo capitolo con le tecniche di analisi XML descritte nel capitolo 17. Considerate per esempio questo documento XML (chiamatelo book.xml): <?xml version="1.0" encoding="ISO-8859-1"?> <book> <title>JavaScript Step by Step</title> <isbn>9780735624498</isbn> </book> La combinazione dell’oggetto XMLHttpRequest e dell’analisi XML porta al seguente codice, che recupera e visualizza l’ISBN del documento book.xml: var requestObj = readyAJAX(); var url = "http://www.braingia.org/book.xml"; requestObj.open("GET",url,false); requestObj.send(); if (requestObj.status == 200) { var xmldocument = requestObj.responseXML; alert(xmldocument.getElementsByTagName("isbn")[0].childNodes[0].nodeValue); } else { alert(requestObj.statusText); } 19 Java PpP.indd 354 28/04/11 16:02 Capitolo 19 Un tocco di AJAX 355 Quando la richiesta viene completata con successo, requestObj.responseXML contiene il documento XML richiesto (book.xml). Il codice xmldocument.getElementsByTagName(“isbn”) recupera un array di tag <isbn> nel documento. In questo documento ce n’è uno solo; lo [0] indica il primo. La porzione .childNodes[0] del codice recupera il primo nodo figlio da quel tag <isbn>. In questo caso quello è il nodo di testo, che contiene il numero ISBN. Infine la porzione .nodeValue del codice recupera il valore di quel nodo di testo, l’ISBN, che il precedente codice visualizza in una chiamata ad alert. Lavorare con JSON JavaScript Object Notation (JSON) è un modo per passare i dati nella forma di oggetti e array JavaScript nativi, anziché codificare i dati all’interno di risposte XML (o HTML). JSON rappresenta un modo più efficiente di passare dati dal server al client. L’analisi dell’XML tramite il DOM è più complessa e perciò più lenta, mentre l’analisi dei dati con codifica JSON si esegue direttamente in JavaScript. Richiamate alla mente il documento book.xml di un precedente esempio di questo capitolo. Gli stessi dati in JSON si presentano come segue: { "book": { "title": "JavaScript Step by Step", "isbn": "9780735624498" } } Recuperare un singolo elemento è un po’ più facile con JSON che non con XML. Per analizzare la risposta con formattazione JSON utilizzerete la funzione JavaScript eval(). Ecco per esempio il codice per recuperare e visualizzare il titolo del libro: var requestObj = readyAJAX(); var url = "http://www.braingia.org/json.php"; requestObj.open("GET",url,false); requestObj.send(); if (requestObj.status == 200) { var xmldocument = eval('(' + requestObj.responseText + ')'); alert(xmldocument.book.title); } else { alert(requestObj.statusText); } L’utilizzo di JSON è rischioso dal punto di vista della sicurezza, in quanto impiega la funzione eval() per analizzare la risposta. La funzione eval() esegue essenzialmente il codice JavaScript ricevuto, perciò se il codice è malevolo, sarebbe comunque eseguito nel contesto dell’applicazione. È vostra responsabilità assicurare che i dati che la vostra applicazione sta utilizzando con JSON siano puliti e liberi da codice malevolo che potrebbe causare problemi quando viene eseguito utilizzando eval(). 19 Java PpP.indd 355 28/04/11 16:02 356 Parte IV AJAX e l’integrazione lato-server L’impiego di un framework JavaScript come jQuery vi allevia in gran parte questo problema, come anche l’aggiunta del JSON nativo in ECMA-262 versione 5. Imparerete come utilizzare jQuery per elaborare JSON nel capitolo 22, “Introduzione a jQuery”. Elaborare le intestazioni Il metodo HTTP HEAD restituisce soltanto le intestazioni di risposta dal server, anziché le intestazioni e il body come il metodo GET. Il metodo HEAD è utile a volte per determinare se una data risorsa è stata aggiornata o modificata. Un’intestazione HTTP inviata di frequente è Expires, che indica quando il client dovrebbe richiedere una copia aggiornata di un documento anziché leggerlo dalla cache del client. Se il server invia l’intestazione Expires, il metodo HEAD è un modo efficiente per visualizzare e analizzare l’intestazione Expires perché il metodo HEAD recupera l’intestazione di risposta anziché l’intero body della risorsa richiesta. Per richiedere solo le intestazioni di risposta da un server, impiegando una richiesta HEAD o qualsiasi altro tipo di richiesta come GET o POST, utilizzate il metodo getAllResponseHeaders() dell’oggetto XMLHttpRequest, come segue: requestObj.getAllResponseHeaders(); Il listato 19.2 mostra per esempio come recuperare le intestazioni di risposta dalla pagina default del mio sito web. LISTATO19.2 Recuperare le intestazioni. T<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Response Headers</title> </head> <body> <div id="data"></div> <script type="text/javascript"> function readyAJAX() { try { return new XMLHttpRequest(); } catch(e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { return "A newer browser is needed."; } 19 Java PpP.indd 356 28/04/11 16:02 Capitolo 19 Un tocco di AJAX 357 } } } var requestObj = readyAJAX(); var url = "http://www.braingia.org/"; requestObj.open("HEAD",url,true); requestObj.send(); requestObj.onreadystatechange = function() { if (requestObj.readyState == 4) { if (requestObj.status == 200) { alert(requestObj.getAllResponseHeaders()); } else { alert(requestObj.statusText); } } } </script> </body> </html> Soluzionedeiproblemi Il criterio della stessa origine che avete incontrato durante l’esercizio precedente si applica allo stesso modo al metodo HEAD del listato 19.2. Quando ho scritto il listato 19.2 non mi sono ricordato del criterio della stessa origine e ho impostato la variabile url su http://www.microsoft.com/, pensando che avrei ottenuto la pagina default del sito. Ma dopo aver ricevuto un errore, mi sono accorto del problema e ho cambiato la variabile url in modo che corrispondesse al dominio su cui lo script era eseguito (il mio sito). Anche voi avete buone probabilità di incontrare lo stesso problema. Ricordate di cambiare la variabile url nel vostro server di origine quando tentate di eseguire il codice del listato 19.2. Utilizzare il metodo POST Gli esempi visti finora utilizzavano i metodi GET e HEAD per recuperare dati dal server. Per inviare query tramite HTTP, si utilizza spesso il metodo POST. Utilizzare il metodo POST con XMLHttpRequest è un po’ più complesso che non utilizzare i metodi GET o HEAD. Il metodo POST offre tuttavia due vantaggi specifici rispetto al metodo GET. Prima di tutto i parametri che inviate con una richiesta POST sono contenuti nel body della richiesta anziché nell’URL, come con il metodo GET, e perciò è meno probabile che li veda l’osservatore occasionale che tenta di trovare modi per entrare nella vostra applicazione. In secondo luogo il metodo POST supporta richieste di maggiori dimensioni. Alcuni server limitano la quantità o la dimensione di una richiesta GET a un determinato numero di caratteri, e sebbene questi server potrebbero anche limitare la dimensione di una richiesta POST, il limite per le richieste POST è quasi sempre molto maggiore. Il metodo HTTP POST richiede di impostare un’intestazione aggiuntiva nella richiesta. Questa intestazione aggiuntiva si imposta con il metodo setRequestHeader(): 19 Java PpP.indd 357 28/04/11 16:02 358 Parte IV AJAX e l’integrazione lato-server requestObj.setRequestHeader(header, value); Per impostare per esempio l’intestazione Content-Type per un web form, come fareste per una richiesta POST, potreste scrivere: requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); Quando avete visto le richieste AJAX inviate in precedenza utilizzando il metodo GET, l’URL includeva i parametri o le coppie nome/valore per l’applicazione, come segue: http://www.braingia.org/books/javascriptsbs/isbn.php?isbn=9780735624498 Nel precedente esempio il parametro isbn ha il valore 9780735624498. Quando invece si lavora con le richieste POST, l’URL contiene solo il documento o risorsa richiesta: non contiene alcun parametro. Perciò dovete inviare i parametri come parte del metodo send(). Il listato 19.3 presenta una richiesta AJAX che utilizza il metodo POST, riportata in grassetto. Utilizza due parametri: provate a vedere se riuscite a individuarli. LISTATO19.3 Costruire una richiesta POST. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Post</title> </head> <body> <div id="xmldata"></div> <script type="text/javascript"> function readyAJAX() { try { return new XMLHttpRequest(); } catch(e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { return "A newer browser is needed."; } } } } 19 Java PpP.indd 358 28/04/11 16:02 Capitolo 19 Un tocco di AJAX 359 var requestObj = readyAJAX(); var url = "http://www.braingia.org/books/javascriptsbs/post.php"; var params = "num1=2&num2=2"; requestObj.open("POST",url,true); requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); requestObj.send(params); requestObj.onreadystatechange = function() { if (requestObj.readyState == 4) { if (requestObj.status == 200) { alert(requestObj.responseText); } else { alert(requestObj.statusText); } } } </script> </body> </html> Il listato 19.3 crea due parametri inseriti in una variabile chiamata params: var params = "num1=2&num2=2"; Dopo la costruzione dell’oggetto richiesta (requestObj), i parametri sono passati come argomento al metodo send(): requestObj.send(params); Casodistudio:ricercaeaggiornamentolive Esistono molti esempi di ricerca progressiva basata sulla digitazione (o predittiva) che usano JavaScript, come quello mostrato nel capitolo 18, “Applicazioni JavaScript”. Un esempio è un form che cerca indirizzi email che sono stati messi in whitelist o in blacklist da un filtro spam. La ricerca per whitelist/blacklist utilizza AJAX per importare un file XML e fornisce risultati basati sull’input dell’amministratore. Potete facilmente adattare questa applicazione in modo che fornisca risultati di ricerca live o segnalibri live. Il capitolo 20, “Qualche approfondimento su AJAX”, utilizza una porzione di quell’applicazione del capitolo 18 per creare un form di ricerca live, mentre la sezione successiva introduce un adattamento dell’applicazione per creare un feed segnalibri ricercabile live utilizzando XML. Mi capita spesso di dover accedere a segnalibri su browser web da più computer. Tenendo presente questo, ecco un’applicazione AJAX che fornisce una pagina di segnalibri. La pagina gestisce i segnalibri utilizzando un file XML che risiede in una posizione centrale. Il codice recupera il file e crea una pagina web che estrae i segnalibri e fornisce un’interfaccia di ricerca. 19 Java PpP.indd 359 28/04/11 16:02 360 Parte IV AJAX e l’integrazione lato-server L’applicazione dei segnalibri è mostrata nella figura 19.1. Anche se visualizza soltanto 3 segnalibri, può funzionare altrettanto bene anche con 300; ne utilizziamo pochi per rendere più semplice la spiegazione. Figura 19.1 Una visualizzazione dell’applicazione per segnalibri live. La casella di ricerca funziona restringendo l’elenco dei segnalibri visualizzati mentre l’utente digita nella casella di testo. Digitando per esempio la lettera m nella casella di testo, la pagina cambia immediatamente e mostra solo i segnalibri che iniziano con la lettera m, come si vede nella figura 19.2. Figura 19.2 Digitando la lettera m sono visualizzarti soltanto i segnalibri che iniziano per m. Continuando a digitare, per esempio aggiungendo una i, in modo da avere mi, i segnalibri disponibili si riducono sempre di più, come nella figura 19.3. 19 Java PpP.indd 360 28/04/11 16:02 Capitolo 19 Un tocco di AJAX 361 Figura 19.3 Aggiungere altri caratteri per restringere ulteriormente i risultati. Quando l’utente elimina il testo nella casella di testo, la pagina Bookmarks torna al suo aspetto predefinito (mostrato nella figura 19.1). Ecco l’XML per questa applicazione (potete trovare questo codice anche in bookmark.xml fra i file di esempio): <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <bookmarks xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <bookmark> <title>Steve Suehring's Home Page</title> <url>http://www.braingia.org/</url> </bookmark> <bookmark> <title>MSDN</title> <url>http://msdn.microsoft.com/</url> </bookmark> <bookmark> <title>Microsoft Press</title> <url>http://www.microsoft.com/mspress</url> </bookmark> </bookmarks> L’applicazione, insieme alla pagina web, è mostrata di seguito ed è disponibile anche in bookmark.htm fra i file di esempio: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Search</title> </head> <body> <form name="nameform" id="nameform" action="" method="post"> Bookmark Search: <input id="textname" type="text" name="textname"> </form> <div id="data"></div> <script type="text/javascript" src="ehandler.js"></script> <script type="text/javascript"> 19 Java PpP.indd 361 28/04/11 16:02 362 Parte IV AJAX e l’integrazione lato-server function textSearch() { var textName = document.getElementById("textname"); var dataNode = document.getElementById("data"); while (dataNode.hasChildNodes()) { dataNode.removeChild(dataNode.firstChild); } listName(textName.value); } function readyAJAX() { try { return new XMLHttpRequest(); } catch(e) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { return "A newer browser is needed."; } } } } function listName(text) { var xmlEl = AJAXresponse.getElementsByTagName("bookmark"); elLength = xmlEl.length; for (i = 0; i < elLength; i++) { var div = document.createElement("div"); // Create the row elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } var url = new RegExp("http"); if (! xmlEl[i].childNodes[j].firstChild.nodeValue.match(url)) { var pattern = "^" + text; var title = xmlEl[i].childNodes[j].firstChild.nodeValue; var nameRegexp = new RegExp(pattern, "i"); var existDiv = document.getElementById(title); if (! existDiv) { if (title.match(nameRegexp)) { var anchor = document.createElement("a"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild. nodeValue); var urls = AJAXresponse.getElementsByTagName("url"); anchor.setAttribute("href", urls[i].firstChild.nodeValue); anchor.appendChild(xmlData); div.appendChild(anchor); } } } } 19 Java PpP.indd 362 28/04/11 16:02 Capitolo 19 Un tocco di AJAX 363 document.getElementById("data").appendChild(div); } } var requestObj = readyAJAX(); var url = "http://www.braingia.org/books/javascriptsbs/bookmark.xml"; requestObj.open("GET",url,true); requestObj.send(); var AJAXresponse; requestObj.onreadystatechange = function() { if (requestObj.readyState == 4) { if (requestObj.status == 200) { AJAXresponse = requestObj.responseXML; listName(""); } else { alert(requestObj.statusText); } } } var textEl = document.getElementById("textname"); EHandler.add(textEl,"keyup", function() { textSearch(); } ); </script> </body> </html> La porzione JavaScript del codice è suddivisa in diverse funzioni, di cui parlerò fra breve. Prima di tutto il codice chiama in causa lo script di gestione eventi ehandler.js, che avete incontrato nel capitolo 11, “Gli eventi di JavaScript e il browser”: <script type="text/javascript" src="ehandler.js"></script> L’HTML per la pagina consiste di poche righe. Ecco il web form: <form name="nameform" id="nameform" action="" method="post"> Bookmark Search: <input id="textname" type="text" name="textname"> </form> Ed ecco il div che conterrà i segnalibri: <div id="data"></div> La porzione JavaScript del codice dichiara varie funzioni ed esegue il codice seguente all’interno del blocco principale. Questo codice è in gran parte già stato visto in questo capitolo: utilizza la funzione readyAJAX() e invia una richiesta AJAX per un file XML di segnalibri al server. Quando viene ricevuta la risposta, il codice chiama la funzione listName(). Oltre al codice AJAX, un gestore di evento è associato alla casella di testo del web form. L’evento da gestire è keyup, che rileva quando un tasto viene premuto e rilasciato nella casella di testo. Il codice diventa così: var requestObj = readyAJAX(); 19 Java PpP.indd 363 28/04/11 16:02 364 Parte IV AJAX e l’integrazione lato-server var url = "http://www.braingia.org/books/javascriptsbs/bookmark.xml"; requestObj.open("GET",url,true); requestObj.send(); var AJAXresponse; requestObj.onreadystatechange = function() { if (requestObj.readyState == 4) { if (requestObj.status == 200) { AJAXresponse = requestObj.responseXML; listName(""); } else { alert(requestObj.statusText); } } } var textEl = document.getElementById("textname"); EHandler.add(textEl,"keyup", function() { textSearch(); } ); Il gestore di evento che gestisce la pressione dei tasti nel form di ricerca risiede in due funzioni: textSearch e listName. La funzione textSearch è responsabile di rimuovere i segnalibri dall’elenco. Chiama la funzione listName(). function textSearch() { var textName = document.getElementById("textname"); var dataNode = document.getElementById("data"); while (dataNode.hasChildNodes()) { dataNode.removeChild(dataNode.firstChild); } listName(textName.value); } Infine la funzione listName() contiene il codice per visualizzare solo i segnalibri che corrispondono almeno parzialmente al testo che è stato digitato nella casella di testo. Se nella casella di testo non c’è nessun testo, mostra tutti i segnalibri: function listName(text) { var xmlEl = AJAXresponse.getElementsByTagName("bookmark"); elLength = xmlEl.length; for (i = 0; i < elLength; i++) { var div = document.createElement("div"); // Create the row elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } var url = new RegExp("http"); if (! xmlEl[i].childNodes[j].firstChild.nodeValue.match(url)) { var pattern = "^" + text; var title = xmlEl[i].childNodes[j].firstChild.nodeValue; var nameRegexp = new RegExp(pattern, "i"); var existDiv = document.getElementById(title); if (! existDiv) { if (title.match(nameRegexp)) { 19 Java PpP.indd 364 28/04/11 16:02 Capitolo 19 Un tocco di AJAX 365 var anchor = document.createElement("a"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild. nodeValue); var urls = AJAXresponse.getElementsByTagName("url"); anchor.setAttribute("href", urls[i].firstChild.nodeValue); anchor.appendChild(xmlData); div.appendChild(anchor); } } } } document.getElementById("data").appendChild(div); } } Esercizi 1. Quale dei metodi di richiesta HTTP trattati in questo capitolo in è il più sicuro? Perché? 2. Descrivete le differenze fra una richiesta/risposta XMLHttpRequest con HTML, XML e JSON. 3. Costruite un programma lato-server per restituire la somma di due numeri che il programma riceve come parametri. Chiamate il programma utilizzando un oggetto XMLHttpRequest asincrono. 19 Java PpP.indd 365 28/04/11 16:02 19 Java PpP.indd 366 28/04/11 16:02 Capitolo 20 Qualche approfondimento su AJAX Dopo aver letto questo capitolo, sarete in grado di: n Comprendere come Asynchronous JavaScript and XML (AJAX) e Cascading Style Sheets (CSS) possono essere utilizzati insieme. n Comprendere meglio la relazione fra il Document Object Model (DOM), AJAX e CSS. n Utilizzare AJAX e CSS per creare e stilizzare una tabella Hypertext Markup Language (HTML) con dati Extensible Markup Language (XML). n Creare una casella di testo a discesa basata su AJAX utilizzando CSS. Nel capitolo precedente abbiamo visto come utilizzare l’oggetto XMLHttpRequest per inviare, ricevere ed elaborare richieste, e infine come creare un’applicazione AJAX. In questo capitolo vedremo come utilizzare CSS per visualizzare i dati recuperati con AJAX. La relazione fra JavaScript e CSS è stata trattata nel capitolo 15, “JavaScript e CSS”. Avete imparato che potete cambiare gli stili del documento da programma utilizzando JavaScript. Nel capitolo 17, “JavaScript e XML”, avete appreso come visualizzare dati XML nella forma di tabella HTML. Nel capitolo 19, “Un tocco di AJAX”, avete visto come creare una pagina web di segnalibri ricercabile live utilizzando CSS e il DOM. Questo capitolo mostra come utilizzare CSS per stilizzare la tabella del capitolo 17 ed espandere e rivedere l’applicazione dei segnalibri del capitolo 19, ancora con l’aiuto di CSS e JavaScript. Spero di riuscire a trasmettervi che AJAX è davvero facile da usare. Recuperare e analizzare informazioni von XMLHttpRequest è la parte più semplice, ciò che importa è quello che fate con quei dati. E qui entrano in gioco CSS e il DOM! AJAX è dove mettete insieme tutto il JavaScript che avete imparato in questo libro per creare applicazioni più grandi. Creare una tabella HTML con XML e CSS Il capitolo 17 ha presentato un esempio che recupera XML e utilizza i suoi dati come parte di una tabella HTML, come mostrato nella figura 20.1. Il codice per creare questa tabella è stato sviluppato nel capitolo 17 e ampliato per mostrare non solo i dati ma anche le intestazioni di colonna. Il risultato del codice alla fine del capitolo 17 era il seguente: 20 Java PpP.indd 367 367 28/04/11 16:03 368 Parte IV AJAX e l’integrazione lato-server Figura 20.1 Visualizzare dati XML in una tabella HTML. Il codice del capitolo 17 utilizza metodi XML per ottenere i dati direttamente. Il successivo esercizio converte il codice in modo che recuperi l’XML utilizzando XMLHttpRequest. Come l’esercizio del capitolo 19, il seguente esercizio richiede che il file XML sia memorizzato su un server web. Utilizzare XMLHttpRequest per recuperare e visualizzare dati XML 1. Utilizzate il file books.xml che avete creato nel capitolo 17 oppure, se non l’avete creato o salvato, create un file denominato books.xml con i seguenti dati (potete trovare questo codice anche in books.xml fra i file di esempio). Copiate il file sullo stesso server web del file HTML che creerete al passo successivo. <books> <book> <title>JavaScript Step by Step</title> <author>Steve Suehring</author> <isbn>9780735624498</isbn> <publisher>Microsoft Press</publisher> </book> <book> <title>MySQL Bible</title> <author>Steve Suehring</author> <isbn>9780764549328</isbn> <publisher>Wiley Publishing Inc.</publisher> </book> </books> 2. Utilizzando Microsoft Visual Studio, Eclipse o un altro editor, modificate il file ajaxbooks.htm nella cartella Chapter20 dei file di esempio. 3. In ajaxbooks.htm aggiungete il seguente codice riportato in grassetto (potete trovare questo codice anche in ajaxbooks.txt fra i file di esempio), sostituendo i commenti TODO. Assicuratevi di sostituire lo Uniform Resource Locator (URL) segnaposto YOUR SERVER HERE con il corretto URL del server web. Notate che state cambiando soltanto la definizione della funzione e la prima riga della funzione displayData() rispetto alla versione originale del capitolo 18. 20 Java PpP.indd 368 28/04/11 16:03 Capitolo 20 Qualche approfondimento su AJAX 369 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict. dtd"> <html> <head> <title>Booksx</title> </head> <body> <div id="xmldata"></div> <script type="text/javascript"> function readyAJAX() { try { return new XMLHttpRequest(); } catch(e) { try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) { try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) { return "A newer browser is needed."; } } } } var requestObj = readyAJAX(); var url = "http://YOUR SERVER HERE/books.xml"; requestObj.open("GET",url,true); requestObj.send(); var AJAXresponse; requestObj.onreadystatechange = function() { if (requestObj.readyState == 4) { if (requestObj.status == 200) { AJAXresponse = requestObj.responseXML; displayData(AJAXresponse); } else { alert(requestObj.statusText); } } } function displayData(response) { var xmlEl = response.getElementsByTagName("book"); var table = document.createElement("table"); table.border = "1"; var tbody = document.createElement("tbody"); // Append the body to the table table.appendChild(tbody); var row = document.createElement("tr"); // Append the row to the body tbody.appendChild(row); for (colHead = 0; colHead < xmlEl[0].childNodes.length; colHead++) { 20 Java PpP.indd 369 28/04/11 16:03 370 Parte IV AJAX e l’integrazione lato-server if (xmlEl[0].childNodes[colHead].nodeType != 1) { continue; } var tableHead = document.createElement("th"); var colName = document.createTextNode(xmlEl[0].childNodes[colHead].nodeName); tableHead.appendChild(colName); row.appendChild(tableHead); } tbody.appendChild(row); // Create table row for (i = 0; i < xmlEl.length; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild.nodeValue); td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); } document.getElementById("xmldata").appendChild(table); } </script> </body> </html> 4. Visualizzate la pagina in un browser web. Dovreste vedere una pagina come questa: 20 Java PpP.indd 370 28/04/11 16:03 Capitolo 20 Qualche approfondimento su AJAX 371 Questo esempio combina il codice degli ultimi due capitoli per mostrare come recuperare e visualizzare dati XML con l’oggetto xmlHttpRequest associato con applicazioni AJAX. Sebbene l’applicazione XML originale presentata nel capitolo 18 sia stata convertita per l’uso di xmlHttpRequest, la tabella che visualizza è comunque piuttosto sgradevole. E qui entra in gioco la stilizzazione CSS. Stilizzare la tabella con CSS La funzione principale che visualizza la tabella nel precedente esercizio è displayData(). In questa funzione potete applicare stili CSS per rendere la tabella più simile a quelle che si possono vedere nelle applicazioni web moderne. Nota L’approccio all’utilizzo degli stili in questo capitolo si basa sul modificare gli attributi di stile direttamente nel JavaScript, ma dovreste sapere che questo approccio è presentano soltanto per scopi didattici. Non si tratta infatti dell’approccio preferito nel mondo reale in quanto può rendere difficile la risoluzione dei problemi riguardanti il perché un determinato attributo di stile è applicato a un dato elemento, poiché le informazioni possono cambiare sia in CSS sia nel codice JavaScript. Un altro modo per lavorare con CSS, illustrato nel capitolo 22, “Introduzione a jQuery”, applica cambiamenti di stile alterando gli stili CSS applicati agli elementi HTML. Questo è il modo preferito per lavorare con CSS in JavaScript, in quanto mantiene la separazione fra la visualizzazione (CSS) e il comportamento (codice JavaScript). Cambiare gli attributi di stile con JavaScript Una delle prime operazioni da eseguire è rimuovere il bordo eliminando la seguente riga nella parte superiore della funzione displayData(): table.border = "1"; Nella funzione displayData() sono presenti due loop primari: uno per visualizzare le intestazioni di colonna e uno per visualizzare i dati stessi. Il primo loop mostra le intestazioni di colonna e si presenta come segue: for (colHead = 0; colHead < xmlEl[0].childNodes.length; colHead++) { if (xmlEl[0].childNodes[colHead].nodeType != 1) { continue; } var tableHead = document.createElement("th"); var colName = document.createTextNode(xmlEl[0].childNodes[colHead].nodeName); tableHead.appendChild(colName); row.appendChild(tableHead); } tbody.appendChild(row); Il secondo loop, che visualizza i dati effettivi, è il seguente: for (i = 0; i < xmlEl.length; i++) { 20 Java PpP.indd 371 28/04/11 16:03 372 Parte IV AJAX e l’integrazione lato-server var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild.nodeValue); td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); } La maggior parte delle modifiche apportate alla visualizzazione della tabella saranno eseguite in questi loop. Spiegherò le modifiche quando saranno eseguite. Un altro aspetto che potreste voler cambiare è il font (da parte mia ho sempre avuto un debole per l’Arial). Lo fate utilizzando la proprietà di stile fontFamily in JavaScript. Questo cambiamento deve essere eseguito all’interno di ciascun loop per stilizzare tutto il testo della tabella con il font Arial. Dopo aver aggiunto il codice, i loop si presentano come segue (osservate le due nuove righe in grassetto): for (colHead = 0; colHead < xmlEl[0].childNodes.length; colHead++) { if (xmlEl[0].childNodes[colHead].nodeType != 1) { continue; } var tableHead = document.createElement("th"); var colName = document.createTextNode(xmlEl[0].childNodes[colHead].nodeName); tableHead.style.fontFamily = "Arial"; tableHead.appendChild(colName); row.appendChild(tableHead); } tbody.appendChild(row); for (i = 0; i < xmlEl.length; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild.nodeValue); td.style.fontFamily = "Arial"; td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); } 20 Java PpP.indd 372 28/04/11 16:03 Capitolo 20 Qualche approfondimento su AJAX 373 I risultati di queste modifiche e la rimozione del bordo della tabella generano una tabella come quella nella figura 20.2. Figura 20.2 Prime stilizzazioni della tabella con CSS. Un po’ di colore sarebbe certamente utile per rendere la tabella più leggibile, specialmente se si mostrano molte righe di dati o molte centinaia di righe. È possibile migliorare la leggibilità anche applicando colori alle righe alterne e cambiando il titolo della tabella in un colore diverso. Ecco come si presentano i due loop dopo l’aggiunta di alcune proprietà di stile backgroundColor. Anche in questo caso le modifiche sono riportate in grassetto. for (colHead = 0; colHead < xmlEl[0].childNodes.length; colHead++) { if (xmlEl[0].childNodes[colHead].nodeType != 1) { continue; } var tableHead = document.createElement("th"); var colName = document.createTextNode(xmlEl[0].childNodes[colHead].nodeName); tableHead.style.fontFamily = "Arial"; tableHead.style.backgroundColor = "#aaabba"; tableHead.appendChild(colName); row.appendChild(tableHead); } tbody.appendChild(row); for (i = 0; i < xmlEl.length; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild.nodeValue); if (i % 2) { td.style.backgroundColor = "#aaabba"; } 20 Java PpP.indd 373 28/04/11 16:03 374 Parte IV AJAX e l’integrazione lato-server td.style.fontFamily = "Arial"; td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); } Questo codice utilizza l’operatore modulo (%) per assegnare un’ombreggiatura grigio chiaro alle righe alterne della tabella. In questa tabella sono presenti soltanto due righe di dati, perciò solo alla seconda riga viene applicata la sfumatura. La figura 20.3 mostra il risultato dopo l’aggiunta del colore. Potete trovare la versione completa di questa pagina nella directory CompletedCode in Chapter20 fra i file di esempio. Figura 20.3 Aggiungere colore alla tabella con CSS. Creare una casella a discesa dinamica Potete utilizzare una variante dell’applicazione dei segnalibri mostrata nel capitolo 19 per creare una casella a discesa live per qualsiasi tipo di dati di elenco testuali. Questo tipo di casella a discesa è chiamato a volte casella con suggerimenti durante la digitazione in quanto, mentre si digita, l’interfaccia utente mostra i valori inseriti di frequente in un elenco a discesa, facilitando il completamento dell’immissione. Google Suggest è un’applicazione di questo tipo. Un’altra implementazione di questo stesso principio è una casella a discesa che mostra elementi comuni (come gli stati USA) mentre il visitatore digita. La chiave per questa variante è che il sottoinsieme dei dati che possono essere recuperati per popolare velocemente la casella a discesa live sia maneggevole. È possibile recuperare per esempio un sottoinsieme di stati da un elenco dei 50 stati USA mentre un visitatore digita una query in una casella di testo, ma se lavorate con 1.000.000 di record di database, recuperarne un sottoinsieme probabilmente non sarebbe possibile in un tempo che possa dare all’utente finale l’impressione di un’applicazione che sta rispondendo. Come ulteriore esempio potreste utilizzare un’applicazione come questa in un’azienda per recuperare un elenco di dipendenti per una directory della società. 20 Java PpP.indd 374 28/04/11 16:03 Capitolo 20 Qualche approfondimento su AJAX 375 Ecco una dimostrazione di questa applicazione. Utilizzando l’oggetto xmlHttpRequest, l’applicazione recupera un elenco dei 50 stati USA. Quando un utente inserisce la lettera w, l’applicazione recupera tutti gli stati che iniziano con quella lettera, come nella figura 20.4. Figura 20.4 Recuperare un elenco di stati che iniziano con la lettera w. Spostando il mouse sui vari stati, cambia il colore di sfondo dello stato, come si vede nella figura 20.5, in cui ho spostato il mouse sul Wisconsin (il puntatore del mouse non è visibile nella figura). Figura 20.5 Spostando il mouse sugli stati, il loro colore di sfondo cambia. Infine facendo clic su uno dei nomi di stati, il nome viene copiato nella casella di testo. Il risultato di questa azione è mostrato nella figura 20.6. Da qui il form potrebbe essere inviato, eseguendo qualsiasi azione appropriata per l’applicazione in base all’input. 20 Java PpP.indd 375 28/04/11 16:03 376 Parte IV AJAX e l’integrazione lato-server Figura20.6 Spostare uno stato nella casella di testo. Questo codice funziona allo stesso modo di quello dell’applicazione dei segnalibri del capitolo 19, in quanto il visitatore può continuare a digitare per restringere la ricerca a una specifica selezione. Considerate il caso in cui il visitatore abbia digitato la lettera n. Così facendo vengono mostrati gli otto stati che iniziano con la lettera n. Continuando a digitare, per esempio digitando la parola new, la ricerca si restringe a quattro stati, e digitando ulteriori lettere i risultati si restringono ancora di più. Il codice per questa applicazione è riportato nel listato 20.1. LiSTaTO20.1 Un’applicazione di ricerca. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd"> <html> <head> <title>State Search</title> <script type="text/javascript" src="ehandler.js"></script> </head> <body> <form name="nameform" id="nameform" action="" method="post"> Enter State: <input id="textname" type="text" name="textname"> </form> <div id="data"></div> <script type="text/javascript"> function textSearch() { var textName = document.getElementById("textname"); var dataNode = document.getElementById("data"); while (dataNode.hasChildNodes()) { dataNode.removeChild(dataNode.firstChild); } if (textName.value != "") { listName(textName.value); } } 20 Java PpP.indd 376 28/04/11 16:03 Capitolo 20 Qualche approfondimento su AJAX 377 function readyAJAX() { try { return new XMLHttpRequest(); } catch(e) { try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) { try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) { return "A newer browser is needed."; } } } } function listName(text) { var nameList = AJAXresponse.split(","); var pattern = "^" + text; var nameRegexp = new RegExp(pattern, "i"); for (var i = 0; i < nameList.length; i++) { var existDiv = document.getElementById(nameList[i]); if (! existDiv) { if (nameList[i].match(nameRegexp)) { var displayDiv = document.getElementById("data"); var newDiv = document.createElement("div"); if (window.attachEvent) { newDiv.attachEvent("onclick",function(e) { document.forms["nameform"].textname.value = e.srcElement.firstChild.nodeValue;}); newDiv.attachEvent("onmouseover",function(e) { e.srcElement.style.background = "#FFFFFF"; }); newDiv.attachEvent("onmouseout",function(e) { e.srcElement.style.background = "#aaabba"; }); } else { newDiv.addEventListener("click",function () { document.forms["nameform"].textname.value = this.firstChild.nodeValue; },false); newDiv.addEventListener("mouseover",function() { this.style.background = "#FFFFFF"; },false); newDiv.addEventListener("mouseout",function() { this.style.background = "#aaabba"; },false); } newDiv.setAttribute("id",nameList[i]); newDiv.style.background = "#aaabba"; newDiv.style.color = "#000000"; newDiv.style.border = "solid 1px"; newDiv.style.display = "block"; newDiv.style.width = "175px"; newDiv.appendChild(document.createTextNode(nameList[i])); displayDiv.appendChild(newDiv); } } } } 20 Java PpP.indd 377 28/04/11 16:03 378 Parte IV AJAX e l’integrazione lato-server var requestObj = readyAJAX(); var url = "http://YOUR SERVER HERE/statelist.php"; requestObj.open("GET",url,true); requestObj.send(); var AJAXresponse; requestObj.onreadystatechange = function() { if (requestObj.readyState == 4) { if (requestObj.status == 200) { AJAXresponse = requestObj.responseText; } else { alert(requestObj.statusText); } } } var textEl = document.getElementById("textname"); EHandler.add(textEl,"keyup", function() { textSearch(); } ); </script> </body> </html>Avete già visto la maggior parte di questo codice nel listato 20.1 in altri punti del libro, ma lo spiegherò di nuovo brevemente qui. Il codice recupera l’elenco degli stati chiamando un file esterno basato su server, statelist.php. Questo file restituisce un semplice elenco di stati separato dalla virgola, come il seguente: Alabama,Alaska,Arizona,California,Colorado,Delaware,Florida,Georgia, ... Il file divide questo elenco di stati in corrispondenza della virgola di delimitazione e inserisce i nomi in un array chiamato nameList, come segue: var nameList = AJAXresponse.split(","); Nel codice sono presenti alcune aggiunte alle applicazioni che avete visto negli ultimi due capitoli, per creare piccole caselle a discesa cliccabili con stile CSS. Quel codice è finito nella funzione listName() che avete visto nel capitolo 19. Applica listener di evento e stili CSS a questi elementi HTML DIV nella funzione listName, mostrata di seguito con il codice aggiunto riportato in grassetto: function listName(text) { var nameList = AJAXresponse.split(","); var pattern = "^" + text; var nameRegexp = new RegExp(pattern, "i"); for (var i = 0; i < nameList.length; i++) { var existDiv = document.getElementById(nameList[i]); 20 Java PpP.indd 378 28/04/11 16:03 Capitolo 20 Qualche approfondimento su AJAX 379 if (! existDiv) { if (nameList[i].match(nameRegexp)) { var displayDiv = document.getElementById("data"); var newDiv = document.createElement("div"); if (window.attachEvent) { newDiv.attachEvent("onclick",function(e) { document.forms["nameform"].textname.value = e.srcElement.firstChild.nodeValue;}); newDiv.attachEvent("onmouseover",function(e) { e.srcElement.style.background = "#FFFFFF"; }); newDiv.attachEvent("onmouseout",function(e) { e.srcElement.style.background = "#aaabba"; }); } else { newDiv.addEventListener("click",function () { document.forms["nameform"].textname.value = this.firstChild.nodeValue; },false); newDiv.addEventListener("mouseover",function() { this.style.background = "#FFFFFF"; },false); newDiv.addEventListener("mouseout",function() { this.style.background = "#aaabba"; },false); } newDiv.setAttribute("id",nameList[i]); newDiv.style.background = "#aaabba"; newDiv.style.color = "#000000"; newDiv.style.border = "solid 1px"; newDiv.style.display = "block"; newDiv.style.width = "175px"; newDiv.appendChild(document.createTextNode(nameList[i])); displayDiv.appendChild(newDiv); } } } } Accettare input dall’utente e AJAX Il passo logico successivo nello sviluppo di applicazioni AJAX è accettare l’input dall’utente e fare qualcosa con quell’input. Creare un’applicazione AJAX significa creare un’applicazione altamente interattiva basata sulle azioni dell’utente. Sfortunatamente per fare giustizia a questo argomento dovrei entrare nei dettagli della creazione delle applicazioni lato-server che gestiscono l’input, e questo esula dallo scopo di un libro rivolto a principianti dedicato a JavaScript. Con un po’ di fortuna scriverò un altro libro di livello intermedio su JavaScript o sulla creazione di applicazioni JavaScript che mostrerà sia il JavaScript sia gli aspetti server di AJAX. 20 Java PpP.indd 379 28/04/11 16:03 380 Parte IV AJAX e l’integrazione lato-server Spero tuttavia di essere riuscito, anche con questa trattazione limitata, a farvi comprendere che le applicazioni AJAX non fanno nulla di più che fornire ai visitatori modi amichevoli e interattivi per utilizzare le applicazioni e che gran parte di questa attività riguarda la progettazione intorno a JavaScript, e non solo XMLHttpRequest. L’oggetto XMLHttpRequest è fondamentalmente un corriere, un meccanismo di consegna, per inserire i dati nel programma. Il livello su cui XMLHttpRequest opera è molto al di sotto del livello presentazione su cui la pagina è costruita. Gli utenti perciò non vedono mai l’elaborazione di XMLHttpRequest in background, ma solo il design che avete creato sul front-end dell’applicazione. Gli ultimi due capitoli del libro si basano su tutto ciò che avete appreso finora, ma con l’aiuto della libreria jQuery di JavaScript. Esercizi 1. Create un gestore di evento submit per l’esempio degli stati mostrato in questo capitolo tale che lo stato inviato sia mostrato all’utente quando invia il form. 2. Create un’applicazione che utilizza XMLHttpRequest per restituire un elenco di nomi (come una directory di dipendenti). Potete utilizzare sia normale testo sia XML per i dati di origine. 20 Java PpP.indd 380 28/04/11 16:03 Parte V jQuery Capitolo 21: Introduzione alle librerie e ai framework JavaScript Capitolo 22: Introduzione a jQuery Capitolo 23: Effetti e plug-in di jQuery 21 Java PpP.indd 381 381 28/04/11 16:03 21 Java PpP.indd 382 28/04/11 16:03 Capitolo 21 Introduzione alle librerie e ai framework JavaScript Dopo aver letto questo capitolo, sarete in grado di: n Comprendere il ruolo delle librerie e dei framework di programmazione JavaScript. n Comprendere come definire vostre librerie. n Comprendere il ruolo delle librerie e dei framework JavaScript di terze parti e come trovare ulteriori informazioni su esse. Comprendere le librerie di programmazione In termini di programmazione, una libreria è un raggruppamento di codice che fornisce funzionalità comuni o aggiuntive. Tipicamente le librerie consistono di uno o più file che espongono oggetti e funzioni. In un programma uno sviluppatore include o chiama la libreria per utilizzare questi oggetti e funzioni aggiuntive. In questo modo le librerie e i framework JavaScript sono utili perché evitano di dover mantenere e sviluppare funzioni aggiuntive e migliorate. Contribuiscono a facilitare le attività di programmazione comuni e possono anche aiutare ad attenuare le differenze e la varietà di sfumature dello sviluppo per più browser. Questo capitolo esplora le librerie di JavaScript, compresa la procedura per definire librerie personalizzate, ed esamina alcune delle più diffuse librerie e framework JavaScript. Definire una propria libreria JavaScript Gli sviluppatori in qualsiasi linguaggio eseguono spesso funzioni comuni in modo ripetitivo nella loro attività di programmazione, perciò diventa molto utile creare una libreria o un raggruppamento personalizzato di funzioni comuni utilizzabile per i progetti futuri. Lo script di gestione eventi sviluppato nel capitolo 11, ehandler.js, mostra come creare una libreria creando uno spazio dei nomi per essa: var EHandler = {}; In quello spazio dei nomi la libreria EHandler aggiunge due funzioni. Ecco la prima: EHandler.add = ... Ed ecco la seconda: 21 Java PpP.indd 383 EHandler.remove = ... 383 28/04/11 16:03 384 Parte V jQuery Sebbene sia breve, EHandler è una vera libreria. Come potete vedere, le librerie non devono necessariamente essere grandi per poter essere utili. Avete visto molti esempi di utilizzo di EHandler in capitoli precedenti del libro, e tenendo presente il concetto della libreria EHandler, in questo esempio successivo creerete una vostra libreria. Creare una libreria 1. Utilizzando Microsoft Visual Studio, Eclipse o un altro editor, aprite il file library.js nella cartella Chapter21 fra i file di esempio. 2. In library.js aggiungete il seguente codice (sostituendo il commento TODO) per creare uno spazio dei nomi, e poi aggiungete una funzione: var MyLibrary = {}; MyLibrary.sendAlert = function(mesg, elm) { alert(mesg); }; 3. Salvate il file e chiudetelo. 4. Aprite il file librarypage.htm. In librarypage.htm aggiungete il codice riportato di seguito in grassetto (per sostituire il commento TODO): <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict. dtd"> <html> <head> <title>A Basic Example</title> <script type="text/javascript" src="library.js"></script> </head> <body> <script type="text/javascript"> MyLibrary.sendAlert("hello, this is the message"); </script> </body> </html> 5. Visualizzate la pagina librarypage.htm in un browser web. Dovreste ricevere un avviso come questo: 21 Java PpP.indd 384 28/04/11 16:03 Capitolo 21 Introduzione alle librerie e ai framework JavaScript 385 Soluzione dei problemi Se non ricevete un avviso come questo, assicuratevi di aver spe- cificato correttamente il percorso al file library.js. L’esempio mostrato nel precedente codice librarypage.htm presuppone che il file JavaScript library.js si trovi nella stessa directory del file HTML. Fate attenzione quando definite e utilizzate le vostre librerie, in modo da non creare sovrapposizioni o collisioni con funzioni esistenti e parole riservate della specifica ECMA-262. Inoltre, se utilizzare una libreria o un framework esterno come jQuery o YUI, dovete assicurarvi che la vostra libreria non collida con le convenzioni di denominazione utilizzate per essi. Librerie e framework JavaScript diffusi Le librerie e i framework per JavaScript pubblicamente disponibili sono molti. Il loro scopo è facilitare le attività difficili ai programmatori che sviluppano applicazioni web incentrate su JavaScript. Gli sviluppatori Web dedicano molto del loro tempo ad attività volte a ottenere pagine che abbiano lo stesso aspetto e funzionamento su più browser. Un importante vantaggio dato dall’uso di molte librerie o framework JavaScript è che rimuovono i problemi della compatibilità fra browser. Tutte le diffuse librerie e framework JavaScript includono il codice per far operare le loro rispettive funzioni su tutti i browser che supportano. jQuery jQuery offre un ricco insieme di funzionalità, opzioni potenti, estensibilità ed eccellente supporto da parte della comunità. Utilizzando jQuery, contenuto in un solo file JavaScript, potete aggiungere effetti alle pagine web, migliorarne l’usabilità e facilitare l’elaborazione dei dati con AJAX. Microsoft inoltre include jQuery in Visual Studio 2010. Il capitolo 22, “Introduzione a jQuery”, e il capitolo 23, “Effetti e plug-in di jQuery”, esaminano jQuery in ulteriori dettagli. Potete trovare informazioni su jQuery all’indirizzo http://jquery.com (le informazioni sono in inglese). Yahoo! User Interface Yahoo! User Interface (YUI) offre sia JavaScript sia Cascading Style Sheets (CSS), e semplifica lo sviluppo di applicazioni web. Come jQuery, YUI include funzionalità per migliorare l’usabilità e ottimizzare le applicazioni web. Inoltre la documentazione di YUI è eccellente. Potete trovare informazioni su YUI all’indirizzo http://developer.yahoo.com/yui/ (le informazioni sono in inglese). 21 Java PpP.indd 385 28/04/11 16:03 386 Parte V jQuery MooTools MooTools è una piccola libreria JavaScript altamente ottimizzata. MooTools differisce da YUI e jQuery perché si concentra sull’ottimizzazione dell’elaborazione di JavaScript, mentre YUI e jQuery si concentrano sugli effetti, CSS e le interazioni dirette con l’esperienza utente. Questo non significa che MooTools non abbia effetti, anche MooTools infatti offre molti degli stessi effetti (come accordion e slider) che potete trovare in YUI e jQuery. MooTools è consigliato per i programmatori JavaScript di livello intermedio e avanzato ed è disponibile all’indirizzo http://mootools.net/. Altre librerie Molte altre librerie e framework sono disponibili per JavaScript, troppi per essere trattati e persino menzionati in un libro. Un utile punto da cui iniziare è http://en.wikipedia.org/wiki/ Comparison_of_JavaScript_frameworks dove potete scoprire ulteriori informazioni sui framework JavaScript. Esercizi 1. Esaminate ciascuna delle librerie e framework illustrati in questo capitolo. Quale pensate sia il più semplice da imparare per i nuovi programmatori in JavaScript? Perché? 2. Create una vostra libreria JavaScript con un file JavaScript esterno. Includete il file in una pagina HTML e chiamatelo. 21 Java PpP.indd 386 28/04/11 16:03 Capitolo 22 Introduzione a jQuery Dopo aver letto questo capitolo, sarete in grado di: n Comprendere come includere jQuery nell’HTML. n Comprendere importanti concetti e la sintassi di jQuery. n Utilizzare jQuery con le pagine web. Presentazione di jQuery jQuery è un framework JavaScript diffuso e facile da usare, che facilita le attività JavaScript difficili, spesso eliminando i problemi della compatibilità con più browser. L’intera libreria jQuery consiste di un solo file JavaScript, il che ne semplifica l’inclusione nel nostro JavaScript. Anche la sintassi di jQuery è facile da imparare; utilizza un semplice spazio dei nomi e funzionalità coerenti. Impiegato insieme al componente aggiuntivo jQuery User Interface (UI) (trattato nel capitolo 23, “Effetti e plug-in di jQuery”), vi permette di creare applicazioni web potenti e altamente interattive. Questo capitolo presenta un’introduzione a jQuery, compreso come scaricarlo e utilizzarlo nel vostro JavaScript. Utilizzare jQuery Potete ottenere jQuery da http://www.jquery.com/. In questa sezione vedrete come scaricare jQuery e integrarlo in una pagina web. I due download di jQuery Sulla home page di jQuery sono disponibili due download: una versione di produzione e una versione di sviluppo. Se non progettate di sviluppare plug-in di jQuery o esaminare il suo interno, dovreste scaricare e utilizzare la versione di produzione minificata. Come altra possibile opzione, specialmente per svolgere gli esercizi proposti in questo capitolo, potreste utilizzare una content delivery network (CDN) per accedere a una versione hosted di jQuery. Google offre in hosting jQuery e altre librerie tramite il suo sito web API. Questo significa che potete includere jQuery nelle vostre pagine web e programmi JavaScript senza dover ospitare il file localmente sul vostro server. Visitate http://code. google.com/apis/libraries/devguide.html per ulteriori informazioni (le informazioni sono in inglese). 22 Java PpP.indd 387 387 28/04/11 16:02 388 Parte V jQuery Nota Per quasi tutti gli scenari in cui lavorate con jQuery, consiglio di scaricare e ospitare il file jQuery localmente. Utilizzare la versione locale può essere più veloce e affidabile che non utilizzare la versione CDN. Se per esempio utilizzate una versione ospitata su CDN e il server CDN va giù, tutti gli elementi del vostro sito che utilizzano la libreria non funzioneranno! Tuttavia, per le attività di sviluppo proposte in questo capitolo, va benissimo utilizzare file ospitati su CDN. Per svolgere gli esercizi e seguire le procedure di questo capitolo occorre aver scaricato jQuery nel computer di sviluppo locale o essere connessi a esso da una CDN. Includere jQuery Per includere jQuery in una pagina web si procede esattamente come con qualsiasi altro file JavaScript esterno, con un tag <script> che punta al file di origine. Considerate il codice del listato 22.1. liSTaTO22.1 Includere jQuery in una pagina web. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd"> <html> <head> <title>Adding jQuery</title> <script type="text/javascript" src="jquery-1.4.3.min.js"></script> </head> <body> </body> </html> Ora che avete scaricato jQuery o lo avete referenziato da un sito CDN, e avete visto l’esempio precedente che mostra come includere jQuery in un file, possiamo passare alla sintassi di jQuery. importante La versione 1.4.3 è l’ultima rilasciata al momento della stesura di questo libro, tuttavia sarà quasi certamente diversa quando leggerete il testo, perciò dovrete cambiare l’attributo src in base alla versione dello script jQuery che avete scaricato. Sintassi jQuery di base Quando includete la libreria jQuery in una pagina, jQuery aggiunge una funzione chiamata jquery(). Potreste pensare di dover effettuare tutte le chiamate alle funzioni di jQuery tramite questa interfaccia jquery(), tuttavia esiste una scorciatoia per accedere alla funzione jquery(): $(). Anziché digitare jquery ogni volta, accedete alla libreria jQuery utilizzando un segno di dollaro seguito da due parentesi, come mostrato negli esempi della tabella 22.1. 22 Java PpP.indd 388 28/04/11 16:02 Capitolo 22 Introduzione a jQuery Tabella 22.1 Alcuni 389 selettori jQuery Sintassi Descrizione $(“a”) Tutti gli elementi <a> nel documento. $(document) L ’intero documento, utilizzata di frequente per accedere alla funzione ready() descritta più avanti in questo capitolo. $(“#elementID”) L’elemento identificato dall’ID elementID. $(“.className”) L’elemento o gli elementi con la classe className. Vedrete altri selettori e funzioni correlate più avanti in questo capitolo. Come il codice JavaScript, le istruzioni jQuery dovrebbero terminare con un punto e virgola. Inoltre potete utilizzare indifferentemente le virgolette singole o doppie come selettori in jQuery. Entrambe queste istruzioni sono infatti ugualmente valide: $("a") $('a') Quando vedrete esempi dell’utilizzo di jQuery nel mondo reale (non che questo libro non faccia parte del mondo reale!), scoprirete che sono utilizzate le virgolette sia singole sia doppie. Gli esempi di questo capitolo utilizzano un misto dei due per farvi acquisire familiarità con entrambi i casi; tuttavia, nella programmazione reale, e preferibile scegliere uno stile e utilizzarlo in modo coerente. Collegare jQuery all’evento load Uno dei modi più comuni per lavorare con jQuery è collegando elementi durante l’evento load (o onload) della pagina (gli eventi e le funzioni sono trattate in maggiori dettagli più avanti in questo capitolo). In jQuery lo fate attraverso la funzione di utilità .ready() dell’elemento document. Come abbiamo visto nel breve esempio della sezione precedente, jQuery accede agli elementi con la sintassi $(). Tenendo presente questo, potete accedere all’elemento document come segue: $(document) Quindi potete accedere alla funzione ready() così: $(document).ready() Il seguente esercizio richiede che abbiate scaricato jQuery nel computer di sviluppo locale o che utilizziate un CDN. L’esempio si basa sulla versione 1.4.3 di jQuery, ma questo numero di versione sarà probabilmente diverso quando eseguirete l’esercizio. 22 Java PpP.indd 389 28/04/11 16:02 390 Parte V jQuery Utilizzare document ready 1. Utilizzando Microsoft Visual Studio, Eclipse o un altro editor, modificate il file docready.html nella cartella Chapter22 dei file di esempio. 2. Nel file aggiungete il seguente codice riportato in grassetto al posto del commento TODO: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Document Ready</title> <script type="text/javascript" src="jquery-1.4.3.min.js"></script> </head> <body> <script type="text/javascript"> $(document).ready(alert('hi')); </script> </body> </html> 3. Salvate il file e visualizzate la pagina in un browser web. Riceverete un avviso come questo: Il codice di questo esercizio combina jQuery tramite la funzione $(document).ready() e anche il normale vecchio JavaScript, rappresentato dalla funzione alert() in questo esempio. Questo misto di jQuery e JavaScript è un concetto importante da comprendere: si utilizza jQuery come supplemento al normale JavaScript. jQuery facilita molte delle attività difficoltose, così tanto in effetti che potete dedicare il vostro tempo a creare funzionalità anziché a preoccuparvi delle differenze fra i browser. La funzione $(document).ready() elimina l’esigenza di utilizzare l’evento load del browser per inserire una chiamata di funzione nell’evento load. Con $(document).ready() tutti gli elementi del Document Object Model (DOM) sono disponibili prima della funzione .ready(). Suggerimento La funzione $(document).ready() è centrale per gran parte della programmazione che si esegue con jQuery. 22 Java PpP.indd 390 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 391 Utilizzare i selettori I selettori sono la chiave per lavorare con jQuery e il DOM. Potete utilizzare i selettori per identificare e raggruppare gli elementi su cui una funzione jQuery è eseguita. Come si vede nella tabella 22.1, i selettori sono utilizzati per raccogliere tutti gli elementi con un certo tag, ID o classe applicata. Potete anche utilizzare i selettori in modi molto più potenti, come per selezionare un determinato numero di elementi oppure per selezionare solo elementi che hanno particolari relazioni con altri, per esempio solo i tag <p> che seguono un tag <div>. Questa sezione descrive i selettori in maggiori dettagli. Suggerimento I selettori e il modo in cui funzionano in jQuery sono basati sui selettori in CSS. Se siete a vostro agio con il loro utilizzo in CSS (trattato nel capitolo 15, “JavaScript e CSS”), vi sentirete a casa con questo modello. Selezionare elementi tramite l’ID L’esempio nella tabella 22.1 ha mostrato la sintassi generale per selezionare un elemento tramite il suo attributo ID: $("#elementID") Considerate per esempio questa porzione di HTML: <a href="#" id="linkOne">Link</a> Con il normale JavaScript accedete a questo elemento come segue: getElementById("linkOne") Con jQuery accedete all’elemento così: $("#linkOne") Selezionare elementi tramite la classe Per selezionare elementi tramite la classe dovete far precedere un punto (.) al nome della classe. La sintassi è questa: $(".className") Ecco per esempio un div con una classe applicata: <div class="specialClass"> 22 Java PpP.indd 391 28/04/11 16:02 392 Parte V jQuery Potreste accedere a quell’elemento tramite jQuery come segue: $(".specialClass") Tenete presente che potreste non accedere a un solo elemento; il selettore di classe accede a tutti gli elementi a cui la classe specificata è applicata. In altre parole se molti elementi della pagina hanno applicata la classe speciale “specialClass”, jQuery accede a tutti utilizzando il selettore $(“.specialClass”). Approfondiremo l’argomento più avanti quando lavoreremo con le funzioni che iterano su ogni elemento recuperato con un tale selettore. Selezionare elementi tramite il tipo Potete anche utilizzare i selettori per accedere agli elementi per tipo, come tutti gli elementi <div>, tutti gli elementi <a> e così via. Potreste per esempio accedere a tutti gli elementi <div> in un documento come segue: $('div') Analogamente per accedere a tutti gli elementi <a>, scriverete: $('a') Utilizzando un selettore di tipo è possibile accedere a tutti gli elementi del tipo specificato sulla pagina. Come il selettore di classe, i selettori di tipo possono restituire più elementi. Selezionare elementi tramite la gerarchia Come abbiamo detto in precedenza, potete selezionare gli elementi in base alla loro posizione in relazione ad altri elementi della pagina. Per selezionare per esempio tutti gli elementi <a> che si trovano all’interno di elementi <div>, utilizzate questa sintassi: $("div a") E potete essere ancora più specifici. Se per esempio desiderate tutte le àncore che seguono solo un determinato div, combinate il selettore di tipo con la sintassi del selettore di ID. Considerate questo HTML: <div id="leftNav"> <a href="link1.html">Link 1</a> <a href="link2.html">Link 2</a> </div> Ecco la sintassi del selettore di jQuery per recuperare i due elementi anchor nel div leftNav: $("#leftNav a") Più genericamente, se desiderate soltanto i discendenti diretti di un elemento, utilizzate il segno di maggiore: 22 Java PpP.indd 392 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 393 $("div > p") Questa sintassi recupera tutti gli elementi <p> che sono discendenti diretti di un div ma non include alcun elemento <p> interno agli elementi <p> selezionati. Potete anche scegliere il figlio ennesimo in un insieme con il selettore :nth-child(). Questo esempio sceglie il terzo figlio: $("p:nth-child(3)") Esistono molti altri selettori gerarchici. Per ulteriori informazioni, consultate la documentazione di riferimento sui selettori di jQuery all’indirizzo http://api.jquery.com/ category/selectors/ (le informazioni sono in inglese). Selezionare elementi tramite la posizione Come avete visto, i selettori di jQuery sono voraci. La sintassi $(‘a’) seleziona per esempio tutti i tag anchor. jQuery offre molti modi per selezionare elementi più specifici in un gruppo. Uno di questi metodi è utilizzare i selettori first e last. Il seguente codice seleziona il primo <p> della pagina: $("p:first") Analogamente, l’ultimo elemento si seleziona come segue: $("p:last") Potete anche selezionare gli elementi in base alla loro posizione diretta. Come ulteriore esempio, considerate questo HTML: <p>First P</p> <p>Second P</p> <p>Third P</p> Per selezionare il secondo elemento <p>, utilizzate questa sintassi: $("p")[1] Notate che l’indice dell’array inizia da 0 per questo tipo di selettore, perciò il primo elemento è l’indice 0, il secondo è l’indice 1 e così via. Utilizzare questa sintassi è un po’ pericoloso perché fa affidamento sul rigido posizionamento degli elementi nella gerarchia. Se qualcuno aggiunge un altro tag <p> alla pagina prima dell’elemento che state tentando di selezionare, questa aggiunta fa cambiare l’indice dell’array, perciò il selettore sceglie l’elemento sbagliato. Quando è possibile, è meglio utilizzare un selettore di ID per scegliere un elemento singolo o specifico che non fare affidamento sulla posizione dell’elemento. Un modo alternativo di selezionare utilizzando l’indice è impiegare la sintassi :eq. Per scegliere per esempio il terzo paragrafo, potreste scrivere: $("p:eq(3)") 22 Java PpP.indd 393 28/04/11 16:02 394 Parte V jQuery Infine altri selettori di posizione che a volte tornano utili sono even e odd, che selezionano gli elementi alterni di un gruppo: $("p:even") I selettori even e odd sono molto utili quando si lavora con dati tabellari per alternare i colori delle righe. Il listato 22.2 mostra un esempio che utilizza il selettore oddper differenziare il colore di sfondo delle righe alterne di una tabella. Nota Il codice del listato 22.2 utilizza due elementi che non sono ancora stati introdotti for- malmente: una funzione definita dall’utente e la funzione .css() Ma non preoccupatevene adesso. Le vedremo nei dettagli più avanti in questo capitolo. liSTaTO22.2 Dati tabellari e jQuery. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd"> <html> <head> <title>Table Test</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> </head> <body> <table> <tr> <td>Row 1 Column 1 of the table</td> <td>Row 1 Column 2 of the table</td> </tr> <tr> <td>Row 2 Column 1 of the table</td> <td>Row 2 Column 2 of the table</td> </tr> <tr> <td>Row 3 Column 1 of the table</td> <td>Row 3 Column 2 of the table</td> </tr> <tr> <td>Row 4 Column 1 of the table</td> <td>Row 4 Column 2 of the table</td> </tr> <tr> <td>Row 5 Column 1 of the table</td> <td>Row 5 Column 2 of the table</td> </tr> <tr> <td>Row 6 Column 1 of the table</td> <td>Row 6 Column 2 of the table</td> </tr> </table> 22 Java PpP.indd 394 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 395 <script type="text/javascript"> $(document).ready(function() { $('tr:odd').css("background-color", "#abacab"); }); </script> </body> </html> Questa porzione principale del codice è contenuta nella sezione JavaScript all’interno del body dell’HTML: $(document).ready(function() { $('tr:odd').css("background-color", "#abacab"); }); Il codice utilizza la funzione $(document).ready() insieme al selettore :odd per impostare il colore di sfondo al valore esadecimale #abacab, un grigio chiaro. La figura 22.1 mostra un esempio dell’output. FigUra22.1 Una tabella colorata con l’aiuto di jQuery. Avetevistoalcunideipiùcomuniselettoridiposizione,macenesonomoltialtridisponibili. Visitatehttp://api.jquery.com/category/selectors/perulterioriinformazioni(leinformazioni sonoininglese). 22 Java PpP.indd 395 28/04/11 16:02 396 Parte V jQuery Selezionare elementi tramite un attributo Come potreste immaginare considerando il selettore di classe che avete già visto, jQuery vi permette di selezionare gli elementi che contengono semplicemente un attributo o quelli che contengono un attributo con un determinato valore. Per selezionare per esempio tutte le immagini che hanno un attributo alt, scriverete quanto segue: $("img[alt]") Per selezionare solo le immagini che hanno un attributo alt impostato su un determinato valore, scriverete: $("img[alt='alternate text']") Il codice precedente seleziona un’immagine soltanto se il testo alt è la parola alternate text. Notate in questo esempio l’utilizzo alternato delle virgolette singole e delle virgolette doppie. Il selettore è racchiuso fra virgolette doppie mentre il selettore di attributo alt interno è racchiuso fra virgolette singole, tuttavia avremmo potuto fare l’inverso: virgolette singole per il selettore img e virgolette doppie per il selettore di attributo alt: $('img[alt="alternate text"]') Potreste anche utilizzare le stesse virgolette per entrambi, ma in questo caso dovete effettuare l’escape delle virgolette interne, come segue: $("img[alt=\"alternate text\"]") È importante osservare che questo tipo di selettore si aspetta una corrispondenza esatta. In questo esempio l’attributo alt deve essere la stringa “alternate text”. Qualsiasi minima differenza, come “alternate text 2” o “ alternate text “ determinerà una non corrispondenza. jQuery include caratteri jolly di selezione che non richiedono una corrispondenza esatta sugli attributi. Considerate gli esempi nella tabella 22.2. Tabella 22.2 Corrispondenza 22 Java PpP.indd 396 dei selettori di attributi Sintassi Descrizione attribute*=value Seleziona gli elementi che contengono l’attributo il cui valore include il valore specificato come sottostringa. attribute~=value Seleziona gli elementi che contengono l’attributo il cui valore include il valore specificato come intera parola. attribute!=value Seleziona gli elementi che o non contengono l’attributo o che contengono l’attributo ma con un valore non corrispondente al valore specificato. attribute$=value S eleziona gli elementi che contengono l’attributo specificato con un valore che termina con la stringa specificata. attribute^=value S eleziona gli elementi che contengono l’attributo specificato con un valore che inizia con la stringa specificata. 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 397 Selezionare elementi dei form jQuery contiene selettori nativi correlati ai web form. La tabella 22.3 elenca qualcuno di questi selettori, alcuni dei quali sono utilizzati nella parte rimanente di questo capitolo. Tabella 22.3 Selettori correlati ai form Selettore Descrizione :checkbox Seleziona tutte le caselle di controllo :checked Seleziona tutti gli elementi che sono attivati, come le caselle ci controllo :input Seleziona tutti gli elementi di input sulla pagina :password Seleziona tutti gli input password :radio Seleziona tutti gli input pulsanti di opzione :reset Seleziona tutti i tipi di input reset :selected Seleziona tutti gli elementi attualmente selezionati :submit Seleziona tutti i tipi di input submit :text Seleziona tutti i tipi di input text Altri selettori jQuery dispone di molti altri selettori, come quelli che selezionano tutti gli elementi nascosti (:hidden) o visibili (:visible) oppure gli elementi abilitati, disabilitati e altri. Visitate http:// api.jquery.com/category/selectors/ per vedere l’elenco completo e aggiornato dei selettori di jQuery. Suggerimento Anziché escogitare una sintassi complessa e fragile per un selettore in modo da raggiungere un determinato elemento, consultate la guida di riferimento ai selettori di jQuery (http://api.jquery.com/category/selectors/, le informazioni sono in inglese) per vedere se qualcuno ha già risolto il problema. Funzioni Finora avete visto molti esempi che selezionano elementi con jQuery, ma soltanto un paio che mostrano cosa potete fare con quegli elementi dopo averli selezionati. jQuery utilizza le funzioni per eseguire azioni sugli elementi selezionati. Le funzioni possono essere predefinite in jQuery o definite dall’utente. Quasi sempre utilizzerete entrambi i tipi contemporaneamente. 22 Java PpP.indd 397 28/04/11 16:02 398 Parte V jQuery Attraversare il DOM La natura della programmazione sul web utilizzando JavaScript e ora jQuery richiede di frequente l’esecuzione di loop o l’iterazione su molti elementi, per esempio la funzione .each() prende un elenco di elementi selezionati ed esegue un’iterazione su ciascuno di essi, facendo qualcosa (o nulla) a ciascuno mentre compie il loop sull’elenco. jQuery contiene numerose funzioni per eseguire loop e iterazioni. Questo processo è chiamato attraversamento nel gergo di jQuery. Per ulteriori informazioni sulle funzioni correlate all’attraversamento, visitate http://api.jquery.com/category/traversing/ (le informazioni sono in inglese). Quando utilizzate le funzioni di attraversamento, quasi sempre lo fate con l’aiuto di una funzione wrapper definita dall’utente insieme al selettore $(this). Analogamente alla parola chiave this nella programmazione a oggetti, il selettore $(this) si riferisce all’oggetto corrente, in questo caso l’elemento attualmente attraversato. Qui potrebbe essere utile un esempio. L’HTML che segue crea una pagina con le classifiche relative a un torneo fittizio di volleyball: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict. dtd"> <html> <head> <title>Iteration Test</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> </head> <body> <table> <th>Team Name</th> <th>W-L Record</th> <th>Win Percentage</th> <tr> <td>Team 1</td> <td>12-8</td> <td class="percentage">.600</td> </tr> <tr> <td>Team 5</td> <td>11-9</td> <td class="percentage">.550</td> </tr> <tr> <td>Team 4</td> <td>10-10</td> <td class="percentage">.500</td> </tr> <tr> <td>Team 2</td> <td>9-11</td> <td class="percentage">.450</td> </tr> <tr> <td>Team 6</td> <td>6-14</td> <td class="percentage">.300</td> 22 Java PpP.indd 398 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 399 </tr> <tr> <td>Team 3</td> <td>2-18</td> <td class="percentage">.100</td> </tr> </table> <script type="text/javascript"> $(document).ready(function() { $('tr:odd').css("background-color", "#abacab"); }); </script> </body> </html> Quando è visualizzata in un browser web, si presenta come quella nella figura 22.2. Figura 22.2 Pagina con le classifiche relative a un torneo fittizio di volleyball. Questo esempio esegue un’iterazione su tutti gli elementi che contengono l’attributo class percentage, una classe applicata alle celle della colonna Win/Loss Percentage della tabella. Per qualsiasi squadra la cui Win/Loss percentage sia maggiore o uguale a .500 (ovvero che ha vinto almeno la metà delle partite), questo esempio applica il grassetto al campo. Potete ottenere questo con il seguente codice jQuery, aggiunto subito sotto l’altro codice jQuery già presente nella pagina: $('.percentage').each(function() { if ($(this).text() >= .5) { $(this).css('font-weight', 'bold'); } }); 22 Java PpP.indd 399 28/04/11 16:02 400 Parte V jQuery Questo codice utilizza un selettore per raccogliere tutti gli elementi a cui è applicata la classe percentage. Quindi accede a ciascuno di questi elementi utilizzando la funzione .each() di jQuery. Nella funzione .each(), una funzione definita dall’utente esegue un condizionale per determinare se il valore nella colonna WinPercentage è maggiore o uguale a .5. Se è così, il codice chiama la funzione .css() per aggiungere una proprietà font-weight impostata a bold per quell’elemento. Dopo aver aggiunto questo codice alla pagina, il risultato è quello del listato 22.3. liSTaTO22.3 Aggiungere jQuery alla pagina del torneo di volleyball. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd"> <html> <head> <title>Iteration Test</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> </head> <body> <table> <th>Team Name</th> <th>W-L Record</th> <th>Win Percentage</th> <tr> <td>Team 1</td> <td>12-8</td> <td class="percentage">.600</td> </tr> <tr> <td>Team 5</td> <td>11-9</td> <td class="percentage">.550</td> </tr> <tr> <td>Team 4</td> <td>10-10</td> <td class="percentage">.500</td> </tr> <tr> <td>Team 2</td> <td>9-11</td> <td class="percentage">.450</td> </tr> <tr> <td>Team 6</td> <td>6-14</td> <td class="percentage">.300</td> </tr> <tr> <td>Team 3</td> <td>2-18</td> <td class="percentage">.100</td> </tr> </table> 22 Java PpP.indd 400 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 401 <script type="text/javascript"> $(document).ready(function() { $('tr:odd').css("background-color", "#abacab"); $('.percentage').each(function() { if ($(this).text() >= .5) { $(this).css('font-weight', 'bold'); } }); }); </script> </body> </html> Quando visualizzate questa pagina nel browser, vedete che la colonna Win Percentage è in grassetto per le squadre che hanno vinto almeno metà delle partite, come si vede nella figura 22.3. FigUra22.3 La colonna Win Percentage ora è in grassetto grazie all’aiuto di jQuery. Esaminando l’output della figura 22.3, potete vedere che sarebbe stato anche meglio applicare il grassetto all’intera riga della tabella anziché solo alla colonna Win Percentage. Fare questo potrebbe sembrarvi difficile, perché dal punto di vista logico il codice ha già superato quella riga della tabella HTML quando viene applicato il test per trovare la percentuale di vincite. Fortunatamente jQuery dispone di una funzione che può essere d’aiuto: .parent() (in effetti ci sono molti modi per fare questo e la funzione .parent()e soltanto uno di essi). Con la funzione parent() l’esecuzione si sposta essenzialmente verso l’alto nella struttura ad albero del DOM per trovare il tag <tr> che racchiude questo particolare elemento <td>. Applicando il cambiamento di stile CSS all’elemento <tr>, potete rendere l’intera riga in grassetto. Il nuovo codice è il seguente, e la modifica è riportata in grassetto: 22 Java PpP.indd 401 28/04/11 16:02 402 Parte V jQuery $('.percentage').each(function() { if ($(this).text() >= .5) { $(this).parent().css('font-weight', 'bold'); } }); Quando viene aggiunto al codice del listato 22.3, l’output è simile a quello della figura 22.4. Figura 22.4 Applicare lo stile CSS a livello di riga nella tabella. Nota Potete trovare il codice modificato anche in listing22-4.html fra i file di esempio. L’utilizzo della funzione .parent() introduce un nuovo concetto chiamato concatenamento. Il concatenamento è un potente costrutto di jQuery che permette livelli di selezione aggiuntivi e l’applicazione multilivello delle funzioni. In questo esempio il selettore $(this) è concatenato alla funzione .parent(), che seleziona anche il padre di $(this). Solo allora il codice esegue la funzione .css(). Insito nel concatenamento tuttavia c’è un grosso pericolo, quello di ottenere codice difficile da leggere e mantenere. Inoltre il concatenamento può creare codice fragile quando gli elementi in un selettore concatenato cambiano. Il concatenamento è potente e consiglio di utilizzarlo tutte le volte che è possibile, ma andrà a discapito della facilità di lettura e manutenzione. Gli esempi mostrati finora erano tutti basati sull’accesso e la modifica diretta del CSS tramite JavaScript. Come abbiamo detto nel capitolo 15, cambiare lo stile o gli aspetti di presentazione di un una pagina web tramite JavaScript è sconsigliato, ed è preferibile applicare o rimuovere gli stili tramite CSS anziché cambiare gli attributi direttamente. Esistono 22 Java PpP.indd 402 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 403 molti metodi per lavorare con le classi di stili CSS utilizzando jQuery, fra cui .hasClass(), .addClass(), .removeClass() e .toggleClass(). Visitate http://api.jquery.com/category/css/ per ulteriori informazioni su come lavorare con le classi utilizzando queste e altre funzioni (le informazioni sono in inglese). Lavorare con gli attributi Oltre alle funzioni di attributo correlate alle classi, jQuery dispone di funzioni per lavorare con gli attributi del DOM. La più generica di queste è .attr(), sebbene anche altre, come .html() e .val(), siano altrettanto utili. Questa sezione esamina la funzione .attr(), e lascia .html(), .val() e altre funzioni alla sezione successiva. La funzione .attr() si utilizza sia per recuperare sia per impostare attributi. Potete per esempio recuperare e impostare l’attributo alt di un’immagine utilizzando la seguente sintassi: // Get the alt attribute: $("#myImageID").attr("alt") // Set the alt attribute: $("#myImageID").attr("alt", "new text") Nota Recuperare il valore dell'elemento prima di impostarlo non è necessario. Modificare il testo e l’HTML Potete riscrivere completamente una pagina utilizzando funzioni come .text() e .val(). Il fatto che sia possibile farlo non significa che sia una buona idea, anche se potrebbe capitarvi di dover riscrivere porzioni dell’HTML di una pagina oppure cambiare testo o valori. La funzione .html() recupera o modifica l’intero HTML di un elemento selezionato. Osservate per esempio questo HTML: <div id="myDiv">Here is a div, it's quite nice</div> Ed ecco il jQuery: $("#myDiv").html('<span class="redStyle">This is the new content of the div</span>'); Il risultato di questa piccola porzione di jQuery è che il <div> identificato da myDiv ora contiene un elemento <span> con il nuovo testo, come si vede nell’esempio di codice. Questo esempio è piuttosto semplicistico, ma immaginate se <div> includesse un’intera sezione di contenuto. Utilizzando jQuery, potete essenzialmente riscrivere l’intera sezione, HTML e tutto il testo. Come la funzione .html(), anche text() supporta sia il recupero sia l’impostazione del testo in un elemento selezionato. Diversamente dall’HTML, la funzione .text() cambia solo il testo, perciò non permette di modificare l’HTML nell’elemento selezionato. 22 Java PpP.indd 403 28/04/11 16:02 404 Parte V jQuery <div id="myDiv">Here is a div, it's quite nice</div> $("#myDiv").text('This is the new content of the div'); Nel precedente esempio è stato cambiato soltanto il testo; il codice non ha aggiunto alcuno span o applicato stili. Inserire elementi Potete utilizzare con facilità jQuery per aggiungere elementi a una pagina. Due funzioni principali per fare questo sono :after() e :before(). Come i loro nomi suggeriscono, esse aggiungono elementi rispettivamente dopo o prima di un elemento selezionato. Ecco per esempio lo stesso div: <div id="myDiv">Here is a div, it's quite nice</div> Ed ecco il jQuery che inserisce un altro div prima di questo: $("#myDiv").before("<div>This is a new div</div>"); La funzione :after() opera in modo simile: $("#myDiv").after("<div>This is a new div, it appears after myDiv</div>"); Quando è eseguita, la pagina contenente questo codice avrà tre elementi <div>: <div>This is a new div</div> <div id="myDiv">Here is a div, it's quite nice</div> <div>This is a new div, it appears after myDiv</div> Gli esempi mostrati inseriscono elementi <div> aggiuntivi, ma naturalmente potreste utilizzare qualsiasi elemento valido in queste funzioni. Funzioni callback In alcuni casi dovrete eseguire una funzione quando un’altra funzione o parte di essa viene completata, un costrutto chiamato funzione callback. Una funzione callback si esegue dopo che la sua funzione padre è stata completata. jQuery utilizza molto le funzioni callback, specialmente in AJAX. Avete già visto un esempio di funzione callback quando abbiamo eseguito l’iterazione utilizzando la funzione .each(). Per ulteriori informazioni sulle funzioni callback, visitate http://docs.jquery.com/Tutorials:How_jQuery_Works (le informazioni sono in inglese). Vedrete altri esempi di funzioni più avanti in questo capitolo. Per i programmatori JavaScript di livello principiante o intermedio, è importante non pensare troppo alle funzioni callback. Sono semplicemente raggruppamenti di codice che vengono chiamati in un’altra funzione. 22 Java PpP.indd 404 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 405 Eventi Finora abbiamo visto molti esempi di selettori e ci siamo limitati a scalfire la superficie delle funzioni di jQuery. La parte finale di questa introduzione a jQuery riguarda gli eventi. Esattamente come la gestione degli eventi che avete già visto in JavaScript, jQuery permette ai vostri programmi di rispondere ai clic del mouse, agli invii dei form, alle digitazioni da tastiera e altro. Diversamente da JavaScript, in jQuery la gestione degli eventi compatibile con più browser è molto facile. jQuery convive perfettamente con un ambiente multibrowser. Questo è vero specialmente nella gestione degli eventi, che vi risparmia di dover tentare di indovinare come ogni browser risponderà a determinate funzioni. Associare e disassociare La funzione .bind() associa un gestore di evento a un evento, come un clic del mouse: .bind(event, data, handler) In questo caso event è l’evento a cui volete rispondere, data è un oggetto opzionale contenente i dati da passare al gestore di evento e handler è la funzione che desiderate eseguire in risposta all’evento. Per esempio: <a href="/link1.html" id="myLink">A link</a> $("#myLink").bind("click", function() { alert("clicked the link"); }); Il risultato di questo codice è che dopo l’intercettazione dell’evento click per il tag anchor, la pagina mostra un avviso. Notate che questo esempio non utilizza il parametro opzionale data nella chiamata di .bind(). Potete associare i seguenti eventi con la funzione .bind(): n beforeunload n hover n mouseout n blur n keydown n mouseover n change n keypress n mouseup n click n keyup n resize n dblclick n load n scroll n error n mousedown n select n focus n mouseenter n submit n focusin n mouseleave n toggle focusout n mousemove n unload n 22 Java PpP.indd 405 28/04/11 16:02 406 Parte V jQuery Nei capitoli precedenti avete intercettato eventi utilizzando lo script ehandler.js sviluppato nel capitolo 11, “Gli eventi di JavaScript e il browser”. Lo script ehandler.js era un gestore di evento generico compatibile con più browser. La funzione .bind() di jQuery possiede la stessa capacità. La differenza è che la funzione .bind() di jQuery è molto migliore nella gestione degli eventi compatibile con più browser e molto più potente dello script ehandler.js. Sebbene possiate utilizzare .bind() per la gestione degli eventi, jQuery offre anche funzioni scorciatoia che eseguono la stessa operazione di .bind(). Anziché scrivere .bind(“click”,function())… potete scrivere semplicemente .click(function()…. Potreste per esempio riscrivere il precedente esempio di .bind() come segue: $("#myLink").click(function() { alert("clicked the link"); }); Non solo potete rispondere a eventi come il clic su un collegamento, ma potete anche attivare eventi. Osservate per esempio il codice del listato 22.5: liSTaTO22.5 Rispondere a eventi. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Trigger Test</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> </head> <body> <div id="myDiv"> Here is some text.<br> It goes inside this div<br> </div> <p> <a id="braingiaLink" href="http://www.braingia.org">Steve Suehring</a> </p> <script type="text/javascript"> $(document).ready(function() { $('#braingiaLink').click(function() { alert("hello"); return true; }); $('#myDiv').click(function() { $('#braingiaLink').click(); }); }); </script> </body> </html> 22 Java PpP.indd 406 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 407 Quando questa pagina viene caricata in un browser web, facendo clic ovunque nel <div> si attiva l’evento click per l’anchor come se fosse stato fatto clic sull’anchor stesso. Per smettere di rispondere agli eventi, potete disassociarli utilizzando la funzione .unbind(), che accetta due argomenti: .unbind(event, function) L’argomento event è l’evento a cui desiderate smettere di rispondere, mentre l’argomento function è la funzione attualmente associata all’evento. Nota Potete associare più gestori di evento allo stesso evento chiamando .bind() più volte per quell’evento. Eventi del mouse e hover Avete già visto come associare e gestire l’evento click nei precedenti esempi, ma potete anche lavorare con gli eventi del mouse come mouseover e mouseout. Una cosa divertente da fare è far scomparire gli elementi quando l’utente sposta il mouse su essi (questo però genererà frustrazione negli utenti, perciò non fatelo su un sito live). Il listato 22.6 mostra il codice che fa scomparire un anchorquando il mouse viene spostato sul paragrafo che lo contiene. liSTaTO22.6 Lavorare con gli eventi del mouse. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Trigger Test</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <style type="text/css"> #braingiaLink { border: solid 1px black; padding: 3px; } #wrapperP { padding: 50px; } </style> </head> <body> <div id="myDiv"> Here is some text.<br> It goes inside this div<br> </div> <p id="wrapperP"> <a id="braingiaLink" href="http://www.braingia.org">Steve Suehring</a> </p> 22 Java PpP.indd 407 28/04/11 16:02 408 Parte V jQuery <script type="text/javascript"> $(document).ready(function() { $('#braingiaLink').click(function() { alert("hello"); return true; }); $('#myDiv').click(function() { $('#braingiaLink').click(); }); $('#wrapperP').mouseover(function() { $('#braingiaLink').hide(); }); $('#wrapperP').mouseout(function() { $('#braingiaLink').show(); }); }); </script> </body> </html> Gli elementi chiave di questo codice sono i gestori di evento .mouseover() e .mouseout(), che a loro volta utilizzano due funzioni jQuery aggiuntive, .hide() e .show(). Gli eventi .mouseover() e .mouseout() sono connessi al paragrafo con l’ID wrapperP. Quando il mouse entra in questo paragrafo, l’anchor identificato da braingiaLink scompare e riappare solo quando il mouse esce dall’area del paragrafo. Non ha importanza il fatto che il collegamento può anche essere attivato utilizzando la navigazione da tastiera. Tenete sempre presente che per creare un determinato effetto su una pagina web esistono sempre più modi. jQuery dispone della funzione .hover() che ha un effetto molto simile agli eventi .mouseover() e .mouseout(). Visitate http://api.jquery.com/hover/ per ulteriori informazioni sulla funzione .hover() (le informazioni sono in inglese). Altri gestori di evento Come l’elenco sopra mostra, jQuery dispone di molti altri gestori di evento, troppi per essere trattati in un capitolo introduttivo su jQuery. Consiglio di consultare l’eccellente documentazione sugli eventi di jQuery disponibile all’indirizzo http://api.jquery.com/category/ events/ (le informazioni sono in inglese). 22 Java PpP.indd 408 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 409 AJAX e jQuery I due capitoli precedenti hanno mostrato come scrivere e utilizzare il codice AJAX. Come potreste aspettarvi dopo la lettura delle precedenti sezioni di questo capitolo, jQuery dispone di propri metodi per lavorare con AJAX. E analogamente ad altre attività correlate a JavaScript, jQuery facilita anche l’utilizzo di AJAX. Questa sezione illustra come utilizzare AJAX con jQuery. jQuery offre molte funzioni per lavorare con i dati provenienti da un server e per inviare dati a un server. Fra queste compaiono .load(), .post() e .get(). jQuery include anche una funzione specifica di AJAX, chiamata appunto .ajax(). Con la funzione .ajax() potete impostare molti parametri, fra cui il metodo HTTP che la chiamata dovrebbe utilizzare (GET o POST), il timeout e cosa fare quando si verifica un errore (e naturalmente anche quando il codice ha successo). Ulteriori informazioni Visitate http://api.jquery.com/jQuery.ajax/ per un elenco completo dei parametri disponibili per l’uso con la funzione ajax(). La sintassi di base della funzione ajax() è questa: $.ajax({ parameter: value }); Potete passare alla funzione .ajax() numerose coppie parametro: valore, ma tipicamente specificherete il metodo, l’URL e la funzione callback. È comune anche specificare il tipo di dati che deve essere restituito, se la risposta va messa in cache, i dati da passare al server e cosa fare quando si verifica un errore. Nota La funzione .ajaxSetup() vi permette di impostare valori predefiniti per i parametri correlati ad AJAX, come il caching, i metodi, la gestione degli errori e altri. Ecco un esempio reale della funzione .ajax() in azione: $.ajax({ url: "testajax.aspx", success: function(data) { alert("Successful load"); } }); 22 Java PpP.indd 409 28/04/11 16:02 410 Parte V jQuery jQuery include anche una funzione chiamata .getJSON() che esegue essenzialmente la stessa operazione di altre funzioni correlate ad AJAX, ma lavora specificamente con dati con codifica JSON provenienti dal server. La funzione .getJSON() equivale a chiamare la funzione .ajax() con l’aggiunta del parametro dataType: ‘json’. Osservate per esempio questo elenco con codifica JSON che riporta alcuni stati: ["Wisconsin","California","Colorado","Illinois","Minnesota","Oregon","Washington","New York","New Jersey","Nevada","Alabama","Tennessee","Iowa","Michigan"] Per questo esempio immaginate che i dati con codifica JSON siano restituiti quando il file json.php viene chiamato sul server locale. L’utilizzo seguente della funzione .ajax() recupera i dati e chiama una funzione denominata showStates quando ha successo: $.ajax({ type: "GET", url: "json.php", dataType: "json", success: showStates }); La funzione showStates crea un elenco e lo aggiunge alla casella a discesa <select> del form. Utilizzare AJAX con jQuery Per completare questo esercizio avete bisogno di un file denominato json.php disponibile nella stessa directory del file che utilizzerete nella procedura (potete trovare json.php fra i file di esempio). Come gli esempi dei capitoli precedenti su AJAX, il file json.php deve risiedere nello stesso dominio del file che esegue la richiesta AJAX. 1. Modificate il file ajax.html (che potete trovare fra i file di esempio) utilizzando un qualsiasi editor. 2. Nel file inserite il codice riportato in grassetto di seguito (potete trovare questo codice anche in ajax.txt fra i file di esempio), sostituendo il commento TODO: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd"> <html> <head> <title>AJAX Test</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> 22 Java PpP.indd 410 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 411 </head> <body> <div id="states"> </div> <script type="text/javascript"> $(document).ready(function() { $.ajax({ type: "GET", url: "json.php", dataType: "json", success: showStates }); function showStates(data,status) { $.each(data, function(item) {; $("#states").append("<div>" + data[item] + "</div>"); }); } }); </script> </body> </html> 3. Salvate il file e visualizzatelo in un browser web. Vedrete un elenco di stati, come il seguente: 22 Java PpP.indd 411 28/04/11 16:02 412 Parte V jQuery Errori e timeout AJAX La funzione .ajax() vi permette di gestire con grazia gli errori e i timeout. Oltre al gestore del caso di successo, potete specificare un gestore di errore con il parametro error. Il valore del parametro error è di solito una funzione callback. Ecco un esempio, con il nuovo parametro error in grassetto: $.ajax({ type: "GET", url: "json.php", dataType: "json", success: successFunction, error: errorFunction }); La funzione callback utilizzata per la gestione degli errori (errorFunction nel precedente esempio di codice) riceve tre argomenti: l’oggetto XMLHTTPRequest, una stringa che rappresenta l’errore che si è verificato e un oggetto exception se si è verificata un’eccezione. Perciò una funzione di gestione errori dovrebbe accettare questi tre argomenti e poi fare qualcosa con i risultati. Questo esempio mostra un avviso: function errorFunction(xhr, statusMessage, exceptionObj) { alert("An error was encountered " + statusMessage); } Potrebbe essere necessario impostare un timeout per una richiesta AJAX. Potete impostare un valore di timeout AJAX generico tramite il valore predefinito $.ajaxSetup, ma potete anche specificare un valore di timeout per qualsiasi singola chiamata utilizzando il parametro timeout. Ecco un esempio: $.ajax({ type: "GET", url: "json.php", dataType: "json", success: successFunction, error: errorFunction, timeout: 5000 }); È importante sapere che il timeout è espresso in millisecondi. Perciò l’esempio mostrato imposta il timeout a su secondi. Inviare dati al server Non solo avrete bisogno di ricevere dati da un server in una chiamata AJAX, ma anche di inviare dati a un server e ricevere una risposta. Per questo si usa il parametro data della funzione .ajax(), inviando dati tramite GET o POST. 22 Java PpP.indd 412 28/04/11 16:02 Capitolo 22 Introduzione a jQuery 413 Potete formattare i dati come coppie chiave=valore separate dal carattere & (chiave1=valo re1&chiave2=valore2) o come coppie mappate {chiave1: valore1, chiave2: valore2}. Questo esempio utilizza l’opzione chiave=valore, chiamata anche opzione della stringa di query. Questo esempio chiama un programma lato-server denominato statefull.php che, data un’abbreviazione di due lettere dello stato, restituisce il nome completo dello stato. $.ajax({ type: "POST", url: "statefull.php", dataType: "json", success: successFunction, data: "state=WI" }); Altre opzioni importanti La funzione .ajax() presenta numerose opzioni. Avete già visto come utilizzare molti di esse, ma vorrei descriverne altre due: n async n cache L’opzione async, che è true per impostazione predefinita, informa lo script se deve attendere (e blocca l’ulteriore input nel browser) mentre la transazione AJAX è inviata, ricevuta ed elaborata. Quando è impostata a true, la transazione AJAX viene eseguita in modo asincrono, affinché non si blocchi. L’impostazione cache, che assume per impostazione predefinita il valore true nella maggior parte dei casi, controlla se jQuery metterà in cache la transazione AJAX. Questo è utile quando i dati ricevuti non cambiano spesso, perché caching accelera la transazione, ma il caching può causare problemi quando l’applicazione utilizza i vecchi dati in cache che sono cambiati sul server. Ho scoperto che è utile impostare questa opzione su false in modo che la risposta non venga messa in cache, specialmente nei casi in cui incontrate problemi quando i dati in apparenza non vengono aggiornati. Altro codice jQuery Finora avete visto solo una piccola parte di ciò che jQuery può fare. Continuando nell’apprendimento di JavaScript e di come può essere utile per attivare i vostri siti web, prendete in considerazione l’utilizzo di jQuery o di un’altra libreria JavaScript come aiuto per il lavoro di sviluppo. Per ulteriori informazioni su jQuery, materiali per l’apprendimento e di riferimento, consultate le risorse all’indirizzo http://www.jquery.com (le informazioni sono in inglese). 22 Java PpP.indd 413 28/04/11 16:02 414 Parte V jQuery Esercizi 1. Utilizzando come base il codice in ajax.html (dell’esercizio “Utilizzare Ajax con jQuery”), aggiungete uno stile CSS per far diventare blu il colore di sfondo del singolo <div> dello stato quando il mouse passa su uno degli stati dell’elenco. Vi do un indizio: è possibile farlo in vari modi. 2. Create un programma lato-server per restituire dati quando passate parametri utilizzando la funzione $.ajax(). Elaborate questi dati in qualche modo, utilizzando un avviso o scrivendo sulla pagina. Potreste per esempio implementare un programma lato-server per restituire la somma di due numeri o, come l’esempio mostrato, restituire il nome completo dello stato se il programma riceve l’abbreviazione dello stato. 22 Java PpP.indd 414 28/04/11 16:02 Capitolo 23 Effetti e plug-in di jQuery Dopo aver letto questo capitolo, sarete in grado di: n Comprendere e utilizzare gli effetti jQuery nativi. n Comprendere jQuery UI. n Utilizzare jQuery UI. Funzionalità centrali per migliorare l’usabilità Effetti e miglioramenti dell’usabilità come drag-and-drop, dissolvenza degli elementi in ingresso e in uscita e scorrimento degli elementi sono facili da implementare con l’aiuto di jQuery. E se queste funzionalità non sono sufficienti per farvi amare il prodotto, sappiate che jQuery è estendibile e gode di un ampio supporto da parte della comunità. Fra le funzionalità a cui la comunità di jQuery contribuisce ci sono i plug-in. I plug-in di jQuery forniscono funzionalità aggiuntive non incluse nel pacchetto jQuery principale. Potete ottenere ulteriori informazioni sui plug-in e un elenco di quelli disponibili attualmente sul sito web jQuery Plugins, all’indirizzo http://plugins.jquery.com/ (le informazioni sono in inglese). Questo capitolo fornisce una panoramica di alcuni effetti inclusi nel prodotto principale jQuery oltre che in jQuery UI. Effetti nativi Come abbiamo detto nell’introduzione a questo capitolo, jQuery include varie funzioni che possono migliorare l’usabilità dell’applicazione web, come mostrare e nascondere gli elementi e dissolvere gli elementi in ingresso e in uscita. Questa sezione esamina alcuni degli effetti nativi inclusi in jQuery. Al momento della stesura del presente testo jQuery e jQuery UI sono in fase di aggiornamento per poter funzionare con Windows Internet Explorer 9, perciò alcuni degli esempi mostrati in questo capitolo non funzioneranno con la beta corrente di Internet Explorer 9. Ci sono tuttavia buone probabilità che, per quando leggerete questo capitolo, jQuery e jQuery UI saranno stati aggiornati e Internet Explorer 9 rilasciato. Mostrare, nascondere e alternare Le funzioni .show() e .hide() mostrano e nascondono rispettivamente gli elementi sulla pagina. Queste funzioni impostano la proprietà display di Cascading Style Sheets (CSS). Per nascondere un elemento, dovete impostare la proprietà display a none. Notate che 23 Java PpP.indd 415 415 28/04/11 16:02 416 Parte V jQuery impostando display a none non si rimuove l’elemento dal DOM, perciò potete comunque mostrare l’elemento utilizzando la funzione .show(). Il listato 23.1 riporta un esempio della funzione .hide(). LISTaTO23.1 Nascondere un elemento. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Hide</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <style type="text/css"> .removeBtn { color: #0000CC; } </style> </head> <body> <ul> <li id="option1">Option 1 <span class="removeBtn" id="remove1">(x)</span></li> <li id="option2">Option 2 <span class="removeBtn" id="remove2">(x)</span></li> <li id="option3">Option 3 <span class="removeBtn" id="remove3">(x)</span></li> <li id="option4">Option 4 <span class="removeBtn" id="remove4">(x)</span></li> </ul> <script type="text/javascript"> $(document).ready(function() { $('#option1').click(function() $('#option1').hide(); }); $('#option2').click(function() $('#option2').hide(); }); $('#option3').click(function() $('#option3').hide(); }); $('#option4').click(function() $('#option4').hide(); }); { { { { }); </script> </body> </html> Sfortunatamente l’esempio del listato 23.1 non è molto ottimizzato perché richiede l’aggiunta della gestione per ogni elemento individualmente (non aspettatevi di vedere questo tipo di programmazione in un programma in produzione live, tuttavia è utile per scopi illustrativi). Una soluzione migliore è gestire le opzioni utilizzando le loro funzioni. Il listato 23.2 mostra un modo migliore per ottenere la stessa funzionalità utilizzando jQuery e senza specificare le opzioni nel codice. 23 Java PpP.indd 416 28/04/11 16:02 Capitolo 23 Effetti e plug-in di jQuery 417 LISTaTO23.2 Nascondere un elemento: tecnica migliorata con jQuery. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Hide</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <style type="text/css"> .removeBtn { color: #0000CC; } </style> </head> <body> <ul> <li id="option1">Option 1 <span class="removeBtn" id="remove1">(x)</span></li> <li id="option2">Option 2 <span class="removeBtn" id="remove2">(x)</span></li> <li id="option3">Option 3 <span class="removeBtn" id="remove3">(x)</span></li> <li id="option4">Option 4 <span class="removeBtn" id="remove4">(x)</span></li> </ul> <script type="text/javascript"> $(document).ready(function() { $('.removeBtn').each(function(elm) { $(this).click(function() { $(this).parent().hide(); }); }); }); </script> </body> </html> L’unica differenza nel codice del listato 23.2 è all’interno del JavaScript: $('.removeBtn').each(function() { $(this).click(function() { $(this).parent().hide(); }); }); Questo JavaScript applica una funzione a ogni elemento con la classe removeBtn che imposta l’evento click su quell’elemento. Chiama la funzione .hide() ma poiché, quando l’evento si attiva, $(this) referenzia l’elemento removeBtn (in questo caso l’elemento <span>), dovete percorrere la gerarchia verso l’alto per trovare il nodo padre, che in questo caso è il <li>. La funzione .toggle() mostra o nasconde un elemento in base al suo stato corrente. Quando per esempio un elemento è attualmente visibile, chiamando .toggle() lo si nasconde. Analogamente, quando un elemento è nascosto, diventa visibile se chiamate .toggle(). 23 Java PpP.indd 417 28/04/11 16:02 418 Parte V jQuery Tutte e tre le funzioni .show(), .hide() e .toggle() accettano due argomenti: una durata e una funzione callback. Nel codice dei listati 23.1 e 23.2 notate che, quando l’elemento viene nascosto, scompare istantaneamente. Aggiungendo una durata alla funzione .hide(), l’elemento scompare alla velocità specificata. Come altre funzioni di jQuery, la durata è specificata in millisecondi. In alternativa potete utilizzare le stringhe “fast” e “slow”, che rappresentano rispettivamente 200 e 600 millisecondi. La funzione callback esegue un’azione dopo che la procedura di mostrare o nascondere l’elemento è stata completata. Un possibile utilizzo del callback è per visualizzare un pulsante Undo dopo che un elemento è stato nascosto per consentire agli utenti di rivisualizzare l’elemento che hanno appena nascosto. Aggiungere una durata 1. Utilizzando un editor come Microsoft Visual Studio, Eclipse o altro, aprite il file duration.html, che potete trovare nella cartella Chapter23 fra i file di esempio. 2. Nel file aggiungete il codice riportato in grassetto di seguito: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Hide</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <style type="text/css"> .removeBtn { color: #0000CC; } </style> </head> <body> <ul> <li id="option1">Option 1 <span class="removeBtn" id="remove1">(x)</span></li> <li id="option2">Option 2 <span class="removeBtn" id="remove2">(x)</span></li> <li id="option3">Option 3 <span class="removeBtn" id="remove3">(x)</span></li> <li id="option4">Option 4 <span class="removeBtn" id="remove4">(x)</span></li> </ul> <script type="text/javascript"> $(document).ready(function() { $('.removeBtn').each(function(elm) { $(this).click(function() { $(this).parent().hide(500); }); }); }); </script> </body> </html> 23 Java PpP.indd 418 28/04/11 16:02 Capitolo 23 Effetti e plug-in di jQuery 419 3. Salvate il file e visualizzate la pagina in un browser web. Dovreste vedere una pagina come questa: 4. Ora fate clic sulla (x) accanto a uno qualsiasi degli elementi. L’elemento scompare dalla pagina e viene visualizzata una pagina come questa: 5. Se state utilizzando un browser con un debugger, come Firefox con Firebug, potete fare clic destro su una delle altre opzioni e scegliere Inspect Element per vedere che la proprietà display è stata impostata su none per l’elemento nascosto. Dissolvenza in entrata e in uscita Aggiungendo una durata alle funzioni .show(), .hide() e .toggle(), l’opacità dell’elemento cambia fino a quando non è completamente visualizzato o nascosto. Funzionalità simili sono disponibili tramite le funzioni .fadeIn() e .fadeOut(). Visitate http://api.jquery.com/category/effects/fading/ per ulteriori informazioni su queste funzioni e sulla funzione .fadeTo(); le informazioni sono in inglese. 23 Java PpP.indd 419 28/04/11 16:02 420 Parte V jQuery Scorrimento Un altro metodo per impostare la proprietà display su none è utilizzare le funzioni .slideUp() e .slideDown(). Queste funzioni creano un effetto scorrimento che fa sembrare che l’elemento di sposti prima di scomparire o prima di apparire. Utilizzate la funzione .slideUp() per far scomparire un elemento e .slideDown() per farlo riapparire. Il codice che avete visto in precedenza nel capitolo, modificato in modo che utilizzi .slideUp() anziché hide, si presenta come segue: $('.removeBtn').each(function(elm) { $(this).click(function() { $(this).parent().slideUp(); }); }); Nota Non lasciatevi ingannare pensando di poter scegliere in che modo far scorrere l'elemento, verso l'alto o verso il basso, a seconda del nome delle funzioni. La funzione .slideUp() fa sempre scomparire gli elementi, mentre .slideDown() li fa sempre apparire. jQuery UI jQuery UI si basa su jQuery e fornisce funzionalità estese legate all’interfaccia utente. Molti componenti di jQuery UI forniscono specifici widget o azioni, fra cui un selettore di data, una funzionalità accordion e il completamento automatico. Questa sezione esamina alcuni dei widget di jQuery UI. Ulteriori informazioni Visitate http://jqueryui.com/ per ulteriori informazioni su tutti i widget disponibili per jQuery UI (le informazioni sono in inglese). Utilizzare jQuery UI jQuery UI richiede di includere un file JavaScript separato nel codice. Potete ottenere questo file da http://jqueryui.com/, da dove potete scaricare la release completa e stabile o creare un download personalizzato con i soli componenti di cui avete bisogno per il sito. Questo capitolo utilizza la release completa di jQuery UI, ma per la maggior parte dei siti consiglio di personalizzare il download di jQuery UI in base alle esigenze, includendo soltanto i componenti specifici necessari per gli effetti che volete applicare al sito. 23 Java PpP.indd 420 28/04/11 16:02 Capitolo 23 Effetti e plug-in di jQuery 421 Il download di jQuery UI è un file zip contenente sia il core di jQuery sia il core di jQuery UI con i file CSS correlati a jQuery UI. Occorre decomprimere il file in una posizione adeguata per renderlo disponibile per il server web, come la directory httpdocs o public_html. In sostanza i file devono trovarsi nella stessa posizione del resto del JavaScript e dell’HTML con cui avete lavorato in questo libro. Nota L’utilizzo delle funzioni di jQuery UI potrebbe comportare implicazioni a livello di accessibilità a meno che forniate un mezzo alternativo per eseguire la stessa funzione. Drag-and-drop jQuery UI include funzioni per spostare gli elementi tramite il drag-and-drop: si tratta di .draggable() e .droppable(). Chiamando .draggable() gli utenti possono utilizzare il mouse per spostare un elemento sulla pagina. Considerate il codice del listato 23.3. LISTaTO23.3 La funzione .draggable() in azione. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Drag</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <script type="text/javascript" src="js/jquery-ui-1.8.4.custom.min.js"></script> <style type="text/css"> #container span { border: solid 1px black; padding: 3px; } </style> </head> <body> <div id="container"> <span>Drag me around</span> </div> <script type="text/javascript"> $(document).ready(function() { $('#container > span').draggable(); }); </script> </body> </html> 23 Java PpP.indd 421 28/04/11 16:02 422 Parte V jQuery Questo codice imposta un elemento <p> che poi può essere trascinato con la chiamata della funzione .draggable(): $('#container > span').draggable(); Nota Il codice del listato 23.3 si basa sul presupposto che abbiate scaricato jQuery e che i file jQuery UI siano presenti nella directory di lavoro corrente, la stessa directory in cui risiede l'HTML del listato 23.3. Il codice di jQuery UI viene quindi caricato da una subdirectory js/. Provate a eseguire il codice del listato 23.3 in un browser. Vedrete che è possibile fare clic e trascinare l’elemento spostandolo. Potete utilizzare la funzione .droppable() insieme a .draggable() per creare un target per un elemento trascinato, al fine di consentire a qualcuno di utilizzare un’operazione di dragand-drop per lavorare con gli elementi visivamente sullo schermo. Il listato 23.4 è espanso sull’esempio di .draggable() del listato 23.3 per fornire un <div> come target di rilascio: LISTaTO23.4 La funzione .droppable() in azione. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Drop</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <script type="text/javascript" src="js/jquery-ui-1.8.4.custom.min.js"></script> <style type="text/css"> #container span { border: solid 1px black; padding: 3px; } #targetContainer { height: 200px; width: 200px; border: solid 1px black; background-color: #abacab; margin: 50px; } </style> </head> <body> <div id="container"> <span>Drag me and drop me</span> </div> <div id="targetContainer"> </div> <script type="text/javascript"> $(document).ready(function() { $('#container > span').draggable(); 23 Java PpP.indd 422 28/04/11 16:02 Capitolo 23 Effetti e plug-in di jQuery 423 $('#targetContainer').droppable({ drop: function(event,ui) { alert("Dropped Element: " + ui.draggable.text()); } }); }); </script> </body> </html> La chiave di questo codice è l’utilizzo della funzione .droppable() impostata sul <div> con l’ID targetContainer: $('#targetContainer').droppable({ drop: function(event,ui) { alert("Dropped Element: " + ui.draggable.text()); } }); La funzione .droppable() gestisce numerosi eventi, permettendovi di rispondere quando un elemento è trascinato sopra l’elemento di rilascio (over), all’esterno dell’elemento di rilascio (out), è rilasciato (drop, mostrato nell’esempio) e quando un elemento draggable valido è selezionato o deselezionato (activate e deactivate). Visitate http://jqueryui.com/demos/droppable/ per vedere esempi di questi eventi. Accordion Creare un effetto accordion, in cui le opzioni sembrano arrotolarsi e srotolarsi, è possibile utilizzando jQuery UI. La chiave per ottenere un accordion che funziona correttamente è utilizzare HTML ben formato e un layout adeguato. Un buon candidato per un accordion è un gruppo di voci o opzioni simili. Il listato 23.5 riporta l’HTML e il JavaScript per creare un semplice accordion. 23 Java PpP.indd 423 28/04/11 16:02 424 Parte V jQuery LISTaTO23.5 Un accordion jQuery. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Accordion</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <script type="text/javascript" src="js/jquery-ui-1.8.4.custom.min.js"></script> <style type="text/css"> #container { border: solid 1px black; padding: 3px; } .optionHead { border: solid 1px black; background-color: #abacab; } .optionDiv { border-bottom: dotted 1px black; } </style> </head> <body> <div id="container"> <h3 class="optionHead">Option 1</h3> <div class="optionDiv" id="option1"> <p>Text of option 1</p> </div> <h3 class="optionHead">Option 2</h3> <div class="optionDiv" id="option2"> <p>Text of option 2</p> </div> <h3 class="optionHead">Option 3</h3> <div class="optionDiv" id="option3"> <p>Text of option 3</p> </div> </div> <script type="text/javascript"> $(document).ready(function() { $('#container').accordion(); }); </script> </body> </html> 23 Java PpP.indd 424 28/04/11 16:02 Capitolo 23 Effetti e plug-in di jQuery 425 Caricando il codice del listato 23.5 in un browser web si ottiene una pagina simile a quella nella figura 23.1. Figura 23.1 Un semplice accordion jQuery. Utilizzando un accordion jQuery, noterete che la prima opzione è sempre espansa al caricamento della pagina. A seconda delle esigenze di layout e di come l’accordion è utilizzato, potreste scoprire che sarebbe preferibile espandere un’altra opzione al caricamento della pagina o avere tutte le opzioni compresse. La funzione .accordion() include molte opzioni che controllano il suo comportamento. L’opzione active, quando è utilizzata insieme a collapsible true, avvia l’accordion in uno stato compresso o con una determinata opzione selezionata. Nel successivo esercizio vedrete un accordion in una pagina web e imposterete uno stato predefinito per l’accordion. Impostare lo stato predefinito per un accordion 1. Aprite il file accordion.html utilizzando un editor come Microsoft Visual Studio o Eclipse (potete trovare questo file fra i file di esempio). 2. In accordion.html aggiungete il codice riportato in grassetto di seguito: 23 Java PpP.indd 425 28/04/11 16:02 426 Parte V jQuery <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Accordion</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <script type="text/javascript" src="js/jquery-ui-1.8.4.custom.min.js"></script> <style type="text/css"> #container { border: solid 1px black; padding: 3px; } .optionHead { border: solid 1px black; background-color: #abacab; } .optionDiv { border-bottom: dotted 1px black; } </style> </head> <body> <div id="container"> <h3 class="optionHead">Option 1</h3> <div class="optionDiv" id="option1"> <p>Text of option 1</p> </div> <h3 class="optionHead">Option 2</h3> <div class="optionDiv" id="option2"> <p>Text of option 2</p> </div> <h3 class="optionHead">Option 3</h3> <div class="optionDiv" id="option3"> <p>Text of option 2</p> </div> </div> <script type="text/javascript"> $(document).ready(function() { $('#container').accordion({ collapsible: true, active: false }); }); </script> </body> </html> 23 Java PpP.indd 426 28/04/11 16:02 Capitolo 23 Effetti e plug-in di jQuery 427 3. Salvate il file e visualizzate la pagina in un browser. Notate che l’accordion è avviato in forma compressa, come si vede nella figura che segue: 4. Cambiate l’opzione active su 2 anziché false. Il codice dovrebbe presentarsi come segue: $('#container').accordion({ collapsible: true, active: 2 }); 5. Ricaricate la pagina nel browser. Notate che la terza opzione sullo schermo è espansa. Questo si verifica perché l’indice inizia con 0, rendendo perciò l’indice della prima opzione (Option 1 sullo schermo) pari a 0. Visitate http://jqueryui.com/demos/accordion/ per ulteriori informazioni sulle opzioni e gli eventi disponibili per il widget accordion (le informazioni sono in inglese). Ulteriori informazioni su jQuery UI jQuery UI è un argomento infinitamente più complesso di quanto sia stato possibile trattare qui, che include sofisticate capacità di applicazione di temi CSS con le quali potete scegliere le combinazioni di colori per gli effetti e i widget utilizzati in jQuery UI. Su jQuery UI sono stati scritti interi libri. Visitate http://jqueryui.com/themeroller/ per ulteriori informazioni sui temi CSS e jQuery UI (le informazioni sono in inglese). Visitate anche http://jqueryui.com per ulteriori informazioni e tutorial su jQuery UI (le informazioni sono in inglese). 23 Java PpP.indd 427 28/04/11 16:02 428 Parte V jQuery Esercizi 1. Utilizzando il codice del listato 23.2 come base, aggiungere un collegamento o un pulsante che ripristina tutte le opzioni utilizzando la funzione .show(). 2. Applicando ciò che avete imparato in questo e nei capitoli precedenti, create un accordion jQuery che include opzioni create dinamicamente caricate attraverso AJAX. 23 Java PpP.indd 428 28/04/11 16:02 Appendice Soluzioni degli esercizi Questa appendice riporta le soluzioni e le spiegazioni degli esercizi proposti nel libro. In molti casi esistono più modi per risolvere un problema, perciò, se la domanda non richiede di utilizzare un determinato modo per risolvere il problema, qualsiasi implementazione funzionante è accettabile. I nomi delle vostre funzioni possono essere diversi da quelli presenti in questa appendice. Capitolo 1 1. Falso. Sebbene JavaScript sia definito da un ente per gli standard, ECMA International, non è supportato su tutti i browser web. Inoltre il supporto esistente varia (a volte ampiamente) da un browser all’altro. 2. Falso. Ci sono molte ragioni per cui un visitatore del vostro sito web potrebbe avere JavaScript disattivato. Il browser del visitatore potrebbe non supportarlo, nel computer potrebbero essere installati software speciali che non lo supportano o disattivare JavaScript potrebbe essere semplicemente una preferenza del visitatore. Dovreste fare in modo che il vostro sito funzioni anche senza JavaScript o almeno fare in modo che fallisca con grazia per i visitatori che non hanno JavaScript abilitato. 3. Un tipico blocco di definizione di JavaScript si presenta come segue: <script type="text/javascript"> // JavaScript code goes here </script> 4. Falso. La versione di JavaScript non è inserita nella definizione DOCTYPE. In effetti è piuttosto insolito dichiarare la versione di JavaScript in uso. 5. Vero. Il codice JavaScript può apparire sia nell’head sia nel body di un documento Hypertext Markup Language (HTML). 24 Java PpP.indd 429 429 28/04/11 16:03 430 Soluzioni degli esercizi Capitolo 2 1. Il codice di mysecondpage.htm è simile a questo, anche se il vostro potrebbe differire leggermente (e naturalmente conterrà il vostro nome anziché il mio!): <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>My Second Page</title> <script type="text/javascript"> alert("Steve Suehring"); </script> </head> <body> <p>My Second Page</p> </body> </html> 2. Ecco il nuovo codice, con le modifiche riportate in grassetto: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>My Second Page</title> <script type="text/javascript"> function callAlert() { alert("Steve Suehring"); } </script> </head> <body> <script type="text/javascript"> callAlert(); </script> <p>My Second Page</p> </body> </html> 3. Ho creato un file denominato 3.htm e un file denominato 3.js, mostrati di seguito (il riferimento in 3.htm a 3.js è riportato in grassetto). 3.js: function callAlert() { alert("Steve Suehring"); } 3.htm: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> 24 Java PpP.indd 430 28/04/11 16:03 Soluzioni degli esercizi 431 <head> <title>My Second Page</title> <script type="text/javascript" src="3.js"> </script> </head> <body> <script type="text/javascript"> callAlert(); </script> <p>My Second Page</p> </body> </html> Capitolo 3 1. Le istruzioni valide sono a, b, c, d. L’unica istruzione non valida è la e, perché utilizza una parola riservata, case, come nome di variabile. 2. Falso. Non tutte le istruzioni JavaScript richiedono un punto e virgola finale. In effetti il punto e virgola di solito è opzionale. 3. La variabile orderTotal è modificata dopo che il visitatore è avvisato della quantità ordinata per ogni articolo ma prima che il valore sia restituito dalla funzione. Questo vi insegna che dovete fare attenzione a non alterare il valore o il contenuto delle variabili inavvertitamente. Il visitatore si aspetta di ordinare una determinata quantità, ma il codice cambia quella quantità dopo aver mostrato il numero al visitatore! Capitolo 4 1. Dichiarazioni di variabili: var first = 120; var second = "5150"; var third = "Two Hundred Thirty"; 2. Array (i vostri valori sono probabilmente diversi, ma la parte importante sono i tipi di dati e la sintassi): var newArray = new Array(10, 20, 30, "first string", "second string"); 3. Stringa con escape: alert("Steve's response was \"Cool!\""); 4. La risposta a questo esercizio sta al lettore: non esiste una soluzione giusta o sbagliata. 24 Java PpP.indd 431 28/04/11 16:03 432 Soluzioni degli esercizi Capitolo 5 1. Array (i vostri valori sono probabilmente diversi, ma la parte importante sono i tipi di dati e la sintassi): var num1 = 1; var num2 = 1; var num3 = 19; var fourthvar = "84"; var name1 = "Jakob"; var name2 = "Edward"; alert(num1 + num2); alert(num3 + fourthvar); alert(name1 + name2); 2. Postfisso: var theNum = 1; alert(theNum); alert(theNum++); alert(theNum); Prefisso: var theNum = 1; alert(theNum); alert(++theNum); alert(theNum); 3. Codice: var num1 = 1; var num2 = 1; var num3 = 19; var fourthvar = "84"; var name1 = "Jakob"; var name2 = "Edward"; alert(typeof num1); alert(typeof num2); alert(typeof num3); alert(typeof fourthvar); alert(typeof name1); alert(typeof name2); Dovrebbero essere visualizzati tre avvisi con la parola number seguiti da altri tre con la parola string. 4. Falso. Gli operatori unari appaiono piuttosto spesso in JavaScript, specialmente nei loop for che incrementano una variabile utilizzando l’operatore ++ postfisso. 5. Falso. Sebbene risparmiare byte sia utile, specialmente per le applicazioni web, è quasi sempre preferibile spendere questi stessi byte per rendere il codice leggibile e facile da mantenere. Comunque è una questione di stile personale e di standard di scrittura del codice. In uno dei capitoli successivi apprenderete jQuery. La tipica versione “minimizzata” di questa libreria è un esempio di estremizzazione del risparmio di byte. 24 Java PpP.indd 432 28/04/11 16:03 Soluzioni degli esercizi 433 Capitolo 6 1. Sostituite YOUR NAME nel seguente codice con il contenuto appropriato: var inputName = prompt("Please enter your name:"); switch(inputName) { case "YOUR NAME": alert("Welcome " + inputName); break; case "Steve": alert("Go Away"); break; default: alert("Please Come Back Later " + inputName); } 2. Ecco il codice: var temp = prompt("Please enter the current temperature"); if (temp > 100) { alert("Please cool down"); } else if (temp < 20) { alert("Better warm up"); } Notate che sarebbe una buona idea fornire un’azione predefinita nel caso la temperatura fosse fra 20 e 100! 3. Questo esercizio è impossibile da eseguire nel modo indicato. Poiché gli operatori ternari si aspettano una singola condizione di test e l’esercizio 2 richiede due condizioni, un operatore ternario non può essere utilizzato per eseguire esattamente la stessa attività. Il codice che segue crea un avviso che dice al visitatore di raffreddare quando la temperatura è maggiore di 100 e scaldare quando è minore o uguale a 100: var temp = prompt("Please enter the current temperature"); temp > 100 ? alert("Please cool down") : alert("Better warm up"); 4. Ecco il codice: for (var i = 1; i < 101; i++) { if (i == 99) { alert("The number is " + i); } } Notate che poiché la variabile i ha iniziato il conteggio da 1 (come richiede l’esercizio), il contatore deve arrivare a 101 per soddisfare il requisito di contare da 1 a 100. 5. Ecco il codice: var i = 1; while (i < 101) { if (i == 99) { alert("The number is " + i); 24 Java PpP.indd 433 28/04/11 16:03 434 Soluzioni degli esercizi } i++; } Notate il posizionamento dell’incremento postfisso della variabile i nel loop. Potreste anche utilizzare i=i+1, ma l’operatore postfisso è preferibile. Capitolo 7 1. È importante notare che questo codice utilizza la funzione isNaN per controllare se l’input è un numero. Questa è una best practice che potrebbe non essere sempre ovvia. Un altro modo per ottenere il valore return finale qui è utilizzare invece return theNumber++; come return finale, come mostrato. Ecco il codice: <head> <title>Chapter 7 Exercise 1</title> <script type = "text/javascript" > function incrementNum(theNumber) { if (isNaN(theNumber)) { alert("Sorry, " + theNumber + " isn't a number."); return; } return theNumber + 1; } </script> </head> <body> <script type = "text/javascript" > alert(incrementNum(3)); </script> </body> 2. Ecco il codice: function addNums(firstNum,secondNum) { if ((isNaN(firstNum)) || (isNaN(secondNum))) { alert("Sorry, both arguments must be numbers."); return; } else if (firstNum > secondNum) { alert(firstNum + " is greater than " + secondNum); } else { return firstNum + secondNum; } } 3. Questo esercizio intende dimostrare alcuni problemi relativi all’area di validità delle variabili. Notate che il valore della variabile result cambia all’esterno della funzione, sebbene il cambiamento sia eseguito soltanto all’interno della funzione. Le due posizioni per gli alert sono mostrate in grassetto nel seguente codice: 24 Java PpP.indd 434 28/04/11 16:03 Soluzioni degli esercizi 435 function addNumbers() { firstNum = 4; secondNum = 8; result = firstNum + secondNum; return result; } result = 0; alert(result); result = addNumbers(); alert(result); 4. Ecco il codice: <head> <title>Chapter 7 Exercise 4</title> <script type="text/javascript"> var stars = ["Polaris","Aldebaran","Deneb","Vega","Altair","Dubhe","Regulus"]; var constells = ["Ursa Minor","Taurus","Cygnus","Lyra","Aquila","Ursa Major","Leo"]; function searchStars(star) { var starLength = stars.length; for (var i = 0; i < starLength; i++) { if (stars[i] == star) { return constells[i]; } } return star + " Not Found."; } </script> </head> <body> <script type = "text/javascript" > var inputStar = prompt("Enter star name: "); alert(searchStars(inputStar)); </script> <p>Stars</p> </body> Capitolo 8 1. Ecco il codice: var star = ["Polaris", "Deneb", "Vega", "Altair"]; var starLength = star.length; for (var i = 0; i < starLength; i++) { alert(star[i]); } 2. Un modo è questo: function Song(artist,length,title) { this.artist = artist; this.length = length; this.title = title; 24 Java PpP.indd 435 28/04/11 16:03 436 Soluzioni degli esercizi } song1 = new Song("First Artist","3:30","First Song Title"); song2 = new Song("Second Artist","4:11","Second Song Title"); song3 = new Song("Third Artist","2:12","Third Song Title"); 3. Presupponendo che stiate utilizzando il codice dato nell’esercizio, questo codice nel body concatenerebbe tutti i nomi in una sola lunga stringa, come segue: var names = new Array; for (var propt in star) { names += propt; } alert(names); Il codice per delimitare i nomi con la virgola sarebbe questo: var names = new Array; for (var propt in star) { if (names != "") { names += "," + propt; } else { names = propt; } } alert(names); Capitolo 9 1. Ecco il codice: if (screen.availHeight < 768) { alert("Available Height: " + screen.availHeight); } if (screen.availWidth < 1024) { alert("Available Width: " + screen.availWidth); } 2. Qui è riportato il codice completo, incluso quello dell’esercizio, e il codice aggiuntivo per questo esercizio è in grassetto. Notate l’utilizzo della funzione unescape() per rimuovere il carattere con codifica URL %20 (spazio) dal nome del paese. Questo è necessario perché il nome del paese “Great Britain” specificato in questo esercizio deve avere l’escape dell’URL per le richieste HTTP GET. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Location, Location, Location</title> </head> 24 Java PpP.indd 436 28/04/11 16:03 Soluzioni degli esercizi 437 <body> <script type="text/javascript"> var body = document.getElementsByTagName("body")[0]; for (var prop in location) { var elem = document.createElement("p"); var text = document.createTextNode(prop + ": " + location[prop]); elem.appendChild(text); body.appendChild(elem); } if (location.search) { var querystring = location.search.substring(1); var splits = querystring.split('&'); for (var i = 0; i < splits.length; i++) { var splitpair = splits[i].split('='); var elem = document.createElement("p"); var text = document.createTextNode(splitpair[0] + ": " + splitpair[1]); if (splitpair[0] == "country") { switch(unescape(splitpair[1])) { case "Brazil": alert("Obrigado"); break; case "Great Britain": alert("Thank You"); break; } } elem.appendChild(text); body.appendChild(elem); } } </script> </body> </html> 3. Questo esercizio non ha una soluzione che possa essere riportata qui. Potete installare lo User Agent Switcher per completare l’esercizio. Capitolo 10 1. Ecco il codice: var newelement = document.createElement("p"); newelement.setAttribute("id","pelement"); document.body.appendChild(newelement); newelement.appendChild(document.createTextNode("This is a paragraph, albeit a short one.")); var anchorelem = document.createElement("a"); anchorelem.setAttribute("id","aelement"); anchorelem.setAttribute("href","http://www.braingia.org/"); document.body.appendChild(anchorelem); anchorelem.appendChild(document.createTextNode("Go To Steve Suehring's Web Site.")); 24 Java PpP.indd 437 28/04/11 16:03 438 Soluzioni degli esercizi 2. Ecco il codice: // create the initial elements (if you use an existing HTML file, you won't need to do this) var newelement = document.createElement("p"); newelement.setAttribute("id","pelement"); document.body.appendChild(newelement); newelement.appendChild(document.createTextNode("This is a paragraph, albeit a short one.")); var anchorelem = document.createElement("a"); anchorelem.setAttribute("id","aelement"); anchorelem.setAttribute("href","http://www.braingia.org/"); document.body.appendChild(anchorelem); anchorelem.appendChild(document.createTextNode("Click Here")); // make the change var existingp = document.getElementById("pelement"); existingp.firstChild.nodeValue="This is the new text."; var newanchor = document.getElementById("aelement"); newanchor.setAttribute("href","http://www.microsoft.com/"); 3. Ecco il codice: <head> <title>Chapter 10 Exercises</title> </script> </head> <body> <div id="thetable"></div> <script type = "text/javascript" > var table = document.createElement("table"); table.border = "1"; var tbody = document.createElement("tbody"); // Append the body to the table table.appendChild(tbody); var row = document.createElement("tr"); // Create table row for (i = 1; i < 3; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 1; j < 3; j++) { // Insert the actual text/data from the XML document. var td = document.createElement("td"); var data = document.createTextNode("Hello - I'm Row " + i + ", Column " + j); td.appendChild(data); row.appendChild(td); } tbody.appendChild(row); } document.getElementById("thetable").appendChild(table); </script> </body> 24 Java PpP.indd 438 28/04/11 16:03 Soluzioni degli esercizi 439 Capitolo 11 1. Ecco il codice: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Onclick</title> <script type="text/javascript"> function handleclick() { alert("You Clicked Here"); return false; } </script> </head> <body> <p><a href="#" onclick="return handleclick();">Click Here</a></p> </body> </html> 2. Ecco il codice: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Onclick</title> <script type="text/javascript" src="ehandler.js"></script> <script type="text/javascript"> function handleclick() { alert("You Clicked Here"); return false; } </script> </head> <body> <p><a href="#" id="clickMe">Click Here</a></p> <script type="text/javascript"> var aLink = document.getElementById("clickMe"); EHandler.add(aLink, "click", function() { handleclick(); }); </script> </body> </html> 3. Per questo esercizio non serve codice JavaScript. Il codice HTML è il seguente: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>New Tab</title> </head> <body> 24 Java PpP.indd 439 28/04/11 16:03 440 Soluzioni degli esercizi <p><a target="Microsoft" href="http://www.microsoft.com" id="mslink">Go To Microsoft </a></p> </body> </html> Capitolo 12 1. Una variante di un esempio del capitolo: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Hello Cookie</title> <script type = "text/javascript"> var cookName = "cookie1"; var cookVal = "testvalue"; var date = new Date(); date.setTime(date.getTime()+86400000); // one day, in milliseconds var expireDate = date.toGMTString(); var myCookie = cookName + "=" + cookVal + ";expires=" + expireDate; document.cookie = myCookie; </script> </head> <body> <p>Hello</p> </body> </html> 2. Questo codice è fondamentalmente lo stesso dell’esercizio 1, e le righe modificate sono mostrate in grassetto: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Hello Cookie</title> <script type = "text/javascript"> var cookName = "cookie2"; var cookVal = "testvalue"; var date = new Date(); date.setTime(date.getTime()+86400000); // one day, in millseconds var expireDate = date.toGMTString(); var myCookie = cookName + "=" + cookVal + ";expires=" + expireDate + ";secure"; document.cookie = myCookie; </script> </head> <body> <p>Hello</p> </body> </html> 3. Se non utilizzate una connessione Secure Sockets Layer (SSL), non potete leggere un cookie con il flag secure impostato. 24 Java PpP.indd 440 28/04/11 16:03 Soluzioni degli esercizi 441 4. Nell’esercizio 1 ho impostato un cookie denominato cookie1; perciò quello è l’unico che desidero visualizzare per questo esercizio. Il codice è il seguente: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Reading Cookie</title> <script type = "text/javascript"> var incCookies = document.cookie.split(";"); for (var c = 0; c < incCookies.length; c++) { var splitCookies = incCookies[c].split("="); if (splitCookies[0] == "cookie1") { alert(incCookies[c]); } } </script> </head> <body> <p>Hello</p> </body> </html> Capitolo 13 1. Fate riferimento al listato 13.2 del capitolo 13 per un esempio di questo esercizio. 2. Fate riferimento al listato 13.2 di questo capitolo per un esempio di pre-caricamento di immagini. Applicherete la stessa logica del codice alla mappa immagine creata per questo esercizio. Capitolo 14 1. Consultate la sezione “Lavorare con le caselle di selezione” nel capitolo 11 per un esempio di soluzione per questo esercizio. 2. In base all’esempio pizza.htm, la porzione <head> del codice ora si presenta così, con le aggiunte mostrate in grassetto: <head> <title>Pizza</title> <script type = "text/javascript"> function prepza() { var checkboxes = document.forms["pizzaform"].toppingcheck.length; var crusttype = document.forms["pizzaform"].crust; var size = document.forms["pizzaform"].size; var crustlength = crusttype.length; var sizelength = crusttype.length; var newelement = document.createElement("p"); newelement.setAttribute("id","orderheading"); document.body.appendChild(newelement); 24 Java PpP.indd 441 28/04/11 16:03 442 Soluzioni degli esercizi newelement.appendChild(document.createTextNode("This pizza will have:")); for (var c = 0; c < crustlength; c++) { if (crusttype[c].checked) { var newelement = document.createElement("p"); newelement.setAttribute("id","crustelement" + i); document.body.appendChild(newelement); newelement.appendChild(document.createTextNode( crusttype[c].value + " Crust")); } } for (var s = 0; s < sizelength; s++) { if (size[s].checked) { var newelement = document.createElement("p"); newelement.setAttribute("id","sizeelement" + i); document.body.appendChild(newelement); newelement.appendChild(document.createTextNode(size[s].value + " Size")); } } for (var i = 0; i < checkboxes; i++) { if (document.forms["pizzaform"].toppingcheck[i].checked) { var newelement = document.createElement("p"); newelement.setAttribute("id","newelement" + i); document.body.appendChild(newelement); newelement.appendChild(document.createTextNode( document.forms["pizzaform"].toppingcheck[i].value)); } } } </script> </head> L’HTML segue. Questa particolare soluzione utilizza una tabella a tre colonne, sebbene ciò non sia tecnicamente richiesto per la correttezza di questa risposta: questo è solo uno dei modi possibili. Anche in questo codice le aggiunte sono in grassetto: <form id="pizzaform" action="#"> <table> <tr><td>Toppings</td><td>Crust</td><td>Size</td></tr> <tr> <td><input type="checkbox" id="topping1" value="Sausage" name="toppingcheck" />Sausage</td> <td><input type="radio" name="crust" value="Regular" checked="checked" id="radio1" />Regular</td> <td><input type="radio" name="size" value="Small" checked="checked" id="radiosize1" />Small</td> </tr> 24 Java PpP.indd 442 28/04/11 16:03 Soluzioni degli esercizi 443 <tr> <td><input type="checkbox" id="topping2" value="Pepperoni" name="toppingcheck" />Pepperoni</td> <td><input type="radio" name="crust" value="Deep Dish" id="radio2" />Deep Dish</td> <td><input type="radio" name="size" value="Medium" id="radiosize2" />Medium</td> </tr> <tr> <td><input type="checkbox" id="topping3" value="Ham" name="toppingcheck" />Ham</td> <td><input type="radio" name="crust" value="Thin" id="radio3" />Thin</td> <td><input type="radio" name="size" value="Large" id="radiosize3" />Large</td> </tr> <tr> <td><input type="checkbox" id="topping4" value="Green Peppers" name="toppingcheck" />Green Peppers</td> <td></td> <td></td> </tr> <tr> <td><input type="checkbox" id="topping5" value="Mushrooms" name="toppingcheck" />Mushrooms</td> <td></td> <td></td> </tr> <tr> <td><input type="checkbox" id="topping6" value="Onions" name="toppingcheck" />Onions </td> <td></td> <td></td> </tr> <tr> <td><input type="checkbox" id="topping7" value="Pineapple" name="toppingcheck">Pineapple</td> <td></td> <td></td> </tr> </table> <p><input type="submit" id="prepBtn" name="prepBtn" value="Prep Pizza"></p> </form> 3. Aggiungete il seguente codice alla porzione <head> dell’applicazione pizza dal precedente esercizio: function flip(pizzatype) { if (pizzatype == "veggiespecial") { document.getElementById("peppers").checked = "true"; document.getElementById("onions").checked = "true"; document.getElementById("mushrooms").checked = "true"; } else if (pizzatype == "meatspecial") { document.getElementById("sausage").checked = "true"; document.getElementById("pepperoni").checked = "true"; document.getElementById("ham").checked = "true"; } else if (pizzatype == "hawaiian") { document.getElementById("ham").checked = "true"; document.getElementById("pineapple").checked = "true"; } } 24 Java PpP.indd 443 Utilizzate il seguente form HTML (notate l’aggiunta dei tre pulsanti e la modifica dell’attributo id di ogni ingrediente). 28/04/11 16:03 444 Soluzioni degli esercizi <form id="pizzaform" action="#"> <p> <input type="button" id="veggiespecial" name="veggiespecial" value="Veggie Special" /> <input type="button" id="meatspecial" name="meatspecial" value="Meat Special" /> <input type="button" id="hawaiian" name="hawaiian" value="Hawaiian" /> </p> <table> <tr><td>Toppings</td><td>Crust</td><td>Size</td></tr> <tr> <td><input type="checkbox" id="sausage" value="Sausage" name="toppingcheck" />Sausage</td> <td><input type="radio" name="crust" value="Regular" checked="checked" id="radio1" />Regular</td> <td><input type="radio" name="size" value="Small" checked="checked" id="radiosize1" />Small</td> </tr> <tr> <td><input type="checkbox" id="pepperoni" value="Pepperoni" name="toppingcheck" />Pepperoni</td> <td><input type="radio" name="crust" value="Deep Dish" id="radio2" />Deep Dish</td> <td><input type="radio" name="size" value="Medium" id="radiosize2" />Medium</td> </tr> <tr> <td><input type="checkbox" id="ham" value="Ham" name="toppingcheck" />Ham</td> <td><input type="radio" name="crust" value="Thin" id="radio3" />Thin</td> <td><input type="radio" name="size" value="Large" id="radiosize3" />Large</td> </tr> <tr> <td><input type="checkbox" id="peppers" value="Green Peppers" name="toppingcheck" />Green Peppers</td> <td></td> <td></td> </tr> <tr> <td><input type="checkbox" id="mushrooms" value="Mushrooms" name="toppingcheck" />Mushrooms</td> <td></td> <td></td> </tr> <tr> <td><input type="checkbox" id="onions" value="Onions" name="toppingcheck" />Onions</ td> <td></td> <td></td> </tr> <tr> <td><input type="checkbox" id="pineapple" value="Pineapple" name="toppingcheck" />Pineapple</td> <td></td> <td></td> </tr> </table> <p><input type="submit" id="prepBtn" name="prepBtn" value="Prep Pizza" onclick="prepza();" /></p> </form> 24 Java PpP.indd 444 28/04/11 16:03 Soluzioni degli esercizi 445 Aggiungete gestori alla sezione JavaScript all’interno del <body> della pagina: var veggieBtn = document.getElementById("veggiespecial"); EHandler.add(veggieBtn,"click",function() { flip("veggiespecial"); }); var meatBtn = document.getElementById("meatspecial"); EHandler.add(meatBtn,"click",function() { flip("meatspecial"); }); var hawaiiBtn = document.getElementById("hawaiispecial"); EHandler.add(hawaiiBtn,"click",function() { flip("hawaiian"); }); Capitolo 15 1. Ecco una pagina di esempio; ci sono molti modi per completare questo esercizio correttamente: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>CSS</title> <link href="exercise1.css" rel="stylesheet" type="text/css"> </head> <body> <h1 id="h1element">The Title</h1> <p id="firstelement">The first element.</p> <p id="secondelement">The second element.</p> </body> </html> Ecco il foglio di stile exercise1.css: #h1element { background-color: #abacab; } #firstelement { color: red; } #secondelement { color: blue; } 2. Questo codice cambia l’elemento denominato firstelement in modo che il suo colore di font sia il blu: <script type="text/javascript"> var element1 = document.getElementById("firstelement"); element1.style.color = "#0000FF"; </script> 3. Questo codice nasconde tutti gli elementi <p> utilizzando la proprietà visibility di Cascading Style Sheets (CSS) : <script type="text/javascript"> var pelements = document.getElementsByTagName("p"); var pelmLength = pelements.length; 24 Java PpP.indd 445 28/04/11 16:03 446 Soluzioni degli esercizi for (var i = 0; i < pelmLength; i++) { pelements[i].style.visibility = "hidden"; } </script> 4. Questo codice mostra l’impostazione di visibilità sia prima sia dopo che è stata impostata nello script. Quando eseguite il codice, notate che l’alert è vuoto prima che la proprietà sia impostata. <script type="text/javascript"> var pelements = document.getElementsByTagName("p"); var pelmLength = pelements.length; for (var i = 0; i < pelmLength; i++) { alert(pelements[i].style.visibility); pelements[i].style.visibility = "hidden"; alert(pelements[i].style.visibility); } </script> Capitolo 16 1. Il listato 16.3 del capitolo 16 fornisce una soluzione per questo esercizio. 2. Un alert fornisce un feedback visivo e questo può essere una soluzione al problema. Potete trovare modi migliori per fornire feedback visivo nella soluzione all’esercizio 5 del capitolo 15, mostrato in precedenza, che utilizza un nuovo elemento. Ecco la soluzione di base a questo problema: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Try/Catch</title> <script type="text/javascript"> </script> </head> <body> <form name="formexample" id="formexample" action="#"> <div id="citydiv">Enter a City: <input id="city" name="city"></div> <div><input id="submit" type="submit"></div> </form> <script type="text/javascript"> function checkValid() { try { var cityField = document.forms[0]["city"]; if (cityField.value != "Stockholm") { throw "It's not Stockholm"; } } catch(errorObject) { alert(errorObject); } } 24 Java PpP.indd 446 28/04/11 16:03 Soluzioni degli esercizi 447 function init() { document.forms[0].onsubmit = function() { return checkValid() }; } window.onload = init; </script> </body> </html> 3. Questo è un possibile metodo per svolgere l’esercizio. Esistono altri metodi, compreso l’uso dello script ehandler.js: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Try/Catch</title> <script type="text/javascript"> </script> </head> <body> <form name="formexample" id="formexample" action="#"> <div id="citydiv">Enter a Number Between 1 and 100: <input id="num" name="num"></div> <div><input id="submit" type="submit"></div> </form> <script type="text/javascript"> function checkValid() { try { var numField = document.forms[0]["num"]; if (isNaN(numField.value)) { throw "it's not a number"; } if ((numField.value > 100) || (numField.value < 1)) { numField.style.background = "#FF0000"; return false; } else { numField.style.background = "#FFFFFF"; return true; } } catch(errorObject) { alert(errorObject); } finally { alert("Thank you for playing."); } } function init() { document.forms[0].onsubmit = function() { return checkValid() }; } window.onload = init; </script> </body> </html> 24 Java PpP.indd 447 28/04/11 16:03 448 Soluzioni degli esercizi Capitolo 17 1. Questa soluzione richiede i file books.htm e books.xml utilizzati nel capitolo 17. La soluzione modifica soltanto books.htm. Le modifiche al file sono riportate in grassetto. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="ehandler.js"></script> <title>Books</title> </head> <body> <div id="xmldata"></div> <p><a href="#" id="displaytable">Display Table</a></p> <script type="text/javascript"> function displayData() { var xmlEl = docObj.getElementsByTagName("book"); var table = document.createElement("table"); table.border = "1"; var tbody = document.createElement("tbody"); // Append the body to the table table.appendChild(tbody); var row = document.createElement("tr"); for (colHead = 0; colHead < xmlEl[0].childNodes.length; colHead++) { if (xmlEl[0].childNodes[colHead].nodeType != 1) { continue; } var tableHead = document.createElement("th"); var colName = document.createTextNode(xmlEl[0].childNodes[colHead].nodeName); tableHead.appendChild(colName); row.appendChild(tableHead); } tbody.appendChild(row); // Create table row for (i = 0; i < xmlEl.length; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild. nodeValue); 24 Java PpP.indd 448 28/04/11 16:03 Soluzioni degli esercizi 449 td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); } document.getElementById("xmldata").appendChild(table); } function getXML() { tablelink.style.visibility = "hidden"; if (typeof document.implementation.createDocument != "undefined") { docObj = document.implementation.createDocument("", "", null); docObj.onload = displayData; } else if (window.ActiveXObject) { docObj = new ActiveXObject("Microsoft.XMLDOM"); docObj.onreadystatechange = function () { if (docObj.readyState == 4) displayData() }; } docObj.load("books.xml"); } var tablelink = document.getElementById("displaytable"); EHandler.add("tablelink","click",function() { getXML(); }); </script> </body> </html> Esercizio extra: Il seguente codice aggiunge un collegamento “Display Table” e poi, quando la tabella è visualizzata, aggiunge un collegamento “Hide Table”. Questo non era incluso nell’esercizio. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="ehandler.js"></script> <title>Books</title> </head> <body> <div id="xmldata"></div> <p><a href="#" id="displaytable">Display Table</a></p> <script type="text/javascript"> function displayData() { var xmlEl = docObj.getElementsByTagName("book"); var table = document.createElement("table"); table.setAttribute("id","bookstable"); table.border = "1"; var tbody = document.createElement("tbody"); // Append the body to the table table.appendChild(tbody); 24 Java PpP.indd 449 28/04/11 16:03 450 Soluzioni degli esercizi var row = document.createElement("tr"); for (colHead = 0; colHead < xmlEl[0].childNodes.length; colHead++) { if (xmlEl[0].childNodes[colHead].nodeType != 1) { continue; } var tableHead = document.createElement("th"); var colName = document.createTextNode(xmlEl[0].childNodes[colHead].nodeName); tableHead.appendChild(colName); row.appendChild(tableHead); } tbody.appendChild(row); // Create table row for (i = 0; i < xmlEl.length; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild. nodeValue); td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); } var tableanchor = document.createElement("a"); var tableanchortext = document.createTextNode("Hide Table"); tableanchor.setAttribute("id","hidetable"); tableanchor.setAttribute("href","#"); tableanchor.appendChild(tableanchortext); if (typeof window.addEventListener != "undefined") { tableanchor.addEventListener("click",hideTable,false); } else { tableanchor.attachEvent("onclick",hideTable); } document.getElementById("xmldata").appendChild(tableanchor); document.getElementById("xmldata").appendChild(table); } function hideTable() { var bookstable = document.getElementById("bookstable"); bookstable.style.display = "none"; tablelink.style.display = ""; var tableanchor = document.getElementById("hidetable"); tableanchor.style.display = "none"; } 24 Java PpP.indd 450 28/04/11 16:03 Soluzioni degli esercizi 451 unction getXML() { tablelink.style.display = "none"; if (typeof document.implementation.createDocument != "undefined") { docObj = document.implementation.createDocument("", "", null); docObj.onload = displayData; } else if (window.ActiveXObject) { docObj = new ActiveXObject("Microsoft.XMLDOM"); docObj.onreadystatechange = function () { if (docObj.readyState == 4) displayData() }; } docObj.load("books.xml"); } var tablelink = document.getElementById("displaytable"); EHandler.add("tablelink","click",function() { getXML(); }); </script> </body> </html> 2. Anche questa soluzione richiede il file books.xml. La maggior parte del codice corrisponde alla versione finale di books.htm del capitolo 17 e le differenze sono riportate in grassetto: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Books</title> </head> <body> <div id="xmldata"></div> <script type="text/javascript"> window.onload = getXML; function displayData() { var xmlEl = docObj.getElementsByTagName("book"); var table = document.createElement("table"); table.border = "1"; var tbody = document.createElement("tbody"); // Append the body to the table table.appendChild(tbody); var row = document.createElement("tr"); for (colHead = 0; colHead < xmlEl[0].childNodes.length; colHead++) { if (xmlEl[0].childNodes[colHead].nodeType != 1) { continue; } var tableHead = document.createElement("th"); 24 Java PpP.indd 451 28/04/11 16:03 452 Soluzioni degli esercizi var colName = document.createTextNode(xmlEl[0].childNodes[colHead].nodeName); tableHead.appendChild(colName); row.appendChild(tableHead); } tbody.appendChild(row); // Create table row for (i = 0; i < xmlEl.length; i++) { var row = document.createElement("tr"); // Create the row/td elements for (j = 0; j < xmlEl[i].childNodes.length; j++) { // Skip it if the type is not 1 if (xmlEl[i].childNodes[j].nodeType != 1) { continue; } // Insert the actual text/data from the XML document. var td = document.createElement("td"); if (i % 2) { td.style.background = "#aaabba"; } var xmlData = document.createTextNode(xmlEl[i].childNodes[j].firstChild. nodeValue); td.appendChild(xmlData); row.appendChild(td); } tbody.appendChild(row); } document.getElementById("xmldata").appendChild(table); } function getXML() { if (typeof document.implementation.createDocument != "undefined") { docObj = document.implementation.createDocument("", "", null); docObj.onload = displayData; } else if (window.ActiveXObject) { docObj = new ActiveXObject("Microsoft.XMLDOM"); docObj.onreadystatechange = function () { if (docObj.readyState == 4) displayData() }; } docObj.load("books.xml"); } </script> </body> </html> 24 Java PpP.indd 452 28/04/11 16:03 Soluzioni degli esercizi 453 Capitolo 18 Non ci sono esercizi per il capitolo 18. Capitolo 19 1. Nessuno dei metodi Hypertext Transfer Protocol (HTTP) trattati nel capitolo offre maggiore sicurezza degli altri. Solo l’aggiunta di Secure Sockets Layer (SSL) fornisce un livello di sicurezza sopra i metodi HTTP. Dovreste notare che utilizzando il metodo POST non vengono nascosti i dati di input e che soltanto il metodo POST dovrebbe essere utilizzato con SSL perché il metodo GET inserisce i parametri direttamente nell’URL, dove potrebbero essere visti indipendentemente da SSL. 2. Le risposte che utilizzano l’HTML standard sono recuperate con il metodo responseText e possono contenere qualsiasi cosa che si potrebbe ottenere tramite HTTP. Le risposte in Extensible Markup Language (XML) devono essere ottenute con il metodo responseXML e devono essere servite come XML content type dal server. Le risposte in JavaScript Object Notation (JSON) sono risposte JavaScript, perciò offrono vantaggi di prestazioni rispetto agli altri metodi. 3. Questa soluzione è stata trattata nel capitolo stesso, ma qui è riportata la chiamata asincrona (sostituite YOUR SERVER con quanto appropriato per il vostro ambiente): <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Async</title> </head> <body> <div id="xmldata"></div> <script type="text/javascript"> function readyAJAX() { try { return new XMLHttpRequest(); } catch(e) { try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) { try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) { return "A newer browser is needed."; } } } } var requestObj = readyAJAX(); var url ="http://YOUR SERVER/sum.php?num1=2&num2=2"; 24 Java PpP.indd 453 28/04/11 16:03 454 Soluzioni degli esercizi requestObj.open("GET",url,true); requestObj.send(); requestObj.onreadystatechange = function() { if (requestObj.readyState == 4) { if (requestObj.status == 200) { alert(requestObj.responseText); } else { alert(requestObj.statusText); } } } </script> </body> </html> Il file sum.php è un programma lato-server in PHP estremamente piccolo e non sicuro che ha il seguente aspetto: <?php print $_GET['num1'] + $_GET['num2']; ?> Capitolo 20 1. Questa soluzione utilizza il listato 19.1 e richiede l’aggiunta di un pulsante di invio al form. Il form ora è il seguente: <form name="nameform" id="nameform" action="" method="GET"> Enter State: <input id="textname" type="text" name="textname"> <input type="submit" name="submit" id="statesubmit"> </form> A parte includere ehandler.js, un gestore di evento e una nuova funzione sono tutto ciò che questa soluzione richiede. Sono aggiunti all’interno del JavaScript esistente. var formSubmit = document.getElementById("nameform"); EHandler.add("formSubmit","submit",function() { showstate(); }); function showstate() { alert(document.forms[0].textname.value); } 2. Questa soluzione è una variante della precedente e di altre del capitolo 19. Il programma lato-server deve restituire l’elenco delimitato dalla virgola di persone per la directory della società, in modo simile a come l’esempio sugli stati restituiva un elenco degli stati USA. 24 Java PpP.indd 454 28/04/11 16:03 Soluzioni degli esercizi 455 Capitolo 21 1. Sia jQuery sia MooTools sono veloci da imparare, e anche PrototypeJS è facile da apprendere. Dojo non è uno strumento per programmatori JavaScript alle prime armi, mentre per quanto riguarda YUI ho incontrato diversi sviluppatori che ne sono confusi nonostante la sua completa documentazione. Tuttavia ognuno apprende in modo diverso, perciò vi consiglio di provare ciascuno di questi strumenti, anziché prendere alla lettera il giudizio di altri! 2. L’esercizio di questo capitolo fornisce un esempio di creazione di una vostra libreria e della sua inclusione in una pagina. Capitolo 22 1. Un metodo per ottenere questo è utilizzare la funzione .hover() insieme alla funzione .css() per cambiare il colore di sfondo. Questo avviene nella funzione showStates. Segue la funzione showStates modificata di ajax.html: function showStates(data,status) { $.each(data, function(item) { $("#states").append("<div>" + data[item] + "</div>"); $('#states').children().hover( function() { $(this).css('background-color','blue'); }, function() { $(this).css('background-color',''); } ); }); } 2. Ecco il codice lato-serve scritto in PHP. Questo codice restituisce “Wisconsin” quando è passata l’abbreviazione WI: <?php $stateAbbrev = trim($_POST['state']); if ($stateAbbrev == "WI") { print json_encode("Wisconsin"); } ?> 24 Java PpP.indd 455 28/04/11 16:03 456 Soluzioni degli esercizi 3. Ecco l’HTML, JavaScript e jQuery per generare l’output basato sulla chiamata AJAX: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>AJAX Data Test</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> </head> <body> <div id="state"> </div> <script type="text/javascript"> $(document).ready(function() { $.ajax({ type: "POST", url: "statefull.php", dataType: "json", success: showStateFull, data: "state=WI" }); function showStateFull(data,status) { $("#state").text(data); } }); </script> </body> </html> Capitolo 23 1. Potete aggiungere funzionalità per mostrare tutte le opzioni in molti modi. Questo esempio aggiunge un elemento àncora con l’ID showAll. Questo ID è poi legato a una funzione nel codice jQuery/JavaScript. La funzione esegue un loop su ciascuna delle opzioni e, se la proprietà di visualizzazione di un’opzione è impostata a none, il codice esegue la funzione .show() per essa. Un’altra possibilità, forse migliore, sarebbe aggiungere una classe chiamata hidden all’elemento <li> quando la funzione .hide() viene eseguita in origine. Quindi trovare l’elemento nascosto sarebbe molto più facile, perché potreste limitarvi a cercare qualsiasi elemento <li> che sia nascosto nel tag <ul>. C’è anche un modo per fare questo con il selettore jQuery :hidden, tuttavia ho incontrato alcune difficoltà nel far funzionare il selettore :hidden in browser diversi, e questo è il motivo per cui ho scelto di mostrare gli altri approcci per svolgere l’attività. In ogni caso ecco il codice: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 24 Java PpP.indd 456 28/04/11 16:03 Soluzioni degli esercizi 457 <html> <head> <title>Hide</title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <style type="text/css"> .removeBtn { color: #0000CC; } </style> </head> <body> <ul> <li id="option1">Option 1 <span class="removeBtn" id="remove1">(x)</span></li> <li id="option2">Option 2 <span class="removeBtn" id="remove2">(x)</span></li> <li id="option3">Option 3 <span class="removeBtn" id="remove3">(x)</span></li> <li id="option4">Option 4 <span class="removeBtn" id="remove4">(x)</span></li> </ul> <a href="" id="showAll">Show All</a> <script type="text/javascript"> $(document).ready(function() { $('.removeBtn').each(function(elm) { $(this).click(function() { $(this).parent().hide(); }); }); $('#showAll').click(function() { $('.removeBtn').each(function(elm) { if ($(this).parent().attr("display","none")) { $(this).parent().show(); } }); }); }); </script> </body> </html> 2. La chiave per questo esercizio è l’utilizzo dell’opzione async nella funzione .ajax() di jQuery. Senza async, la funzione .accordion() tende ad avviarsi prima che le opzioni per l’accordion siano ricevute ed elaborate da AJAX. Questo esempio di codice utilizza una chiamata JSON per recuperare l’elenco degli stati utilizzati nel capitolo 22. Questo elenco viene quindi inserito nell’accordion. Il codice imposta async a false nella chiamata di .ajax() e poi aggiunge un po’ di elaborazione alla funzione showStates del capitolo 22. Per il resto questa è una variante dell’esempio di accordion del capitolo 23. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Accordion</title> 24 Java PpP.indd 457 28/04/11 16:03 458 Soluzioni degli esercizi <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <script type="text/javascript" src="js/jquery-ui-1.8.4.custom.min.js"></script> <style type="text/css"> #container { width: 350px; height: 700px; border: solid 2px black; padding: 3px; } .optionHead { border: solid 1px black; background-color: #abacab; } .optionDiv { border-bottom: dotted 1px black; } </style> </head> <body> <div id="container"> </div> <script type="text/javascript"> $(document).ready(function() { $.ajax({ type: "GET", url: "json.php", dataType: "json", success: showStates, async: false }); function showStates(data,status) { $.each(data, function(item) {; $("#container").append( "<h3 class=\"optionHead\">" + data[item] + "</h3>" + "<div class=\"optionDiv\">" + "Option text goes here</div>"); }); } $('#container').accordion({ collapsible: true, active: false }); }); </script> </body> </html> 24 Java PpP.indd 458 28/04/11 16:03