LEZIONI DI
PROGRAMMAZIONE PER IL WEB
QUESTO DOCUMENTO E' IN VIA DI COMPLETAMENTO
ENTRO GENNAIO 2016
CI SCUSIAMO CON I VISITATORI PER LA MANCANZA
DI MOLTI CONTENUTI CHE PRESTO VI APPARIRANNO
generali
❍ Note
per la lettura di questo documento
❍ Dove
posso trovare documentazione online sui linguaggi php, javascript e html?
❍ Esistono
libri consigliabili a chi si avvicina per la prima volta a php, ajax, mySQL?
siti internet in hosting gratuito (es.
altervista.org)
html & css
❍ Visualizzare
il codice di una pagina web
❍ Gli elementi della pagina web
❍ Come
centrare orizzontalmente e verticalmente un elemento nella pagina web
❍ Come
si crea e si configura una tabella con i fogli di stile
javascript & jquery
❍ Come
rilevare le versioni di Explorer e in particolare quelle anteriori a Explorer 9
❍ Cos'è
il DOM che viene utilizzato da javascript?
❍ Acquisire
e manipolare gli elementi di una pagina tramite javascript e jQuery
❍ Come
si costruisce un oggetto javascript
❍ La proprietà documentElement
❍ Subordinare l'apertura di un link al valore vero/falso
di una funzione javascript
❍ Acquisire
la posizione di un elemento entro il documento
❍ Fare
lo scrolling fino a portare un elemento della pagina in vista
❍ Alcune cose che javascript non fa o fa solo a prezzo di una programmazione complicata e poco pulita
php & mysql
❍ Una
pagina php che cambia aspetto ogni volta che la si ricarica
❍ Un
codice php per consentire agli utenti del vostro sito il download di qualsiasi
tipo di file
❍ Una
pagina in cui una routine php genera una tabella che mostra il contenuto di un
database
❍ Come
importare una tabella Access nel database MySQL del vostro server, utilizzando
XML e php
❍ Alcune cose che php non fa, anche se sembrerebbe possibile
ajax
❍ Inviare
dati al server tramite i metodi GET e POST e gestirli con una routine php
❍ Acquisire
un documento XML dal server e metterlo a disposizione di javascript
❍ Acquisire
codice javascript dal server ed eseguirlo immediatamente tramite la funzione
eval()
❍ Creare
un oggetto javascript che incorpori una pagina html esterna e manipolarla
❍ Come
ottenere l'esatto indirizzo di una pagina internet che si vuole utilizzare con
javascript
❍ Una pagina per sperimentare semplice codice
javascript, jQuery, ajax, php
❍ Alcune cose che con ajax non si possono fare, anche se apparentemente sembrerebbero semplici
xml & xpath & simplexml
❍ Cos'è
un documento XML e come lo si può gestire
❍ Leggere
un documento XML posto sul server e farne apparire il contenuto nella pagina
web
varie
❍ Note per la lettura di questo
documento
Come già detto, questo documento è in via
di completamento entro gennaio 2016. Controllate quindi, dopo questa data, se
siano presenti altri articoli di vostro interesse.
Controllate alla fine di ogni articolo se
sono presenti riferimenti a risorse internet che potrebbero esservi utili
riguardo l'argomento ("ulteriore
documentazione consultabile").
Se viene riportato un codice di più righe
con una riga colorata:
<style
type ="text/css">
.TableCell {
border : 1px solid black;
text-align : center;
padding : 10px;
}
</style>
se la riga viene riportate e commentata
singolarmente più in basso, essa avrà lo stesso colore, per facilitare la sua
identificazione nel codice:
border
: 1px solid black;
All'interno di un articolo eventuali
sottotitoli in rosso:
ulteriore
documentazione consultabile
servono ad illustrare la ripartizione dei
contenuti.
❍ Dove posso trovare
documentazione sui linguaggi php, javascript e html?
● Google è una delle principali fonti di
informazione: è sufficiente premettere nel box di ricerca il nome del
linguaggio e scrivere del problema (ad esempio: "php string
functions"): appariranno subito le ricerche pertinenti il nostro caso che
sono state fatte da altri programmatori. Questo è il sistema più comunemente
usato da molti sviluppatori.
Un
consiglio: chi conosce bene
l'inglese dovrebbe digitare i suoi quesiti in questa lingua, perché le risorse
internet in lingua anglosassone sono molto più complete e approfondite di
quelle in lingua italiana.
● Il sito W3schools.com (in lingua inglese) offre
pagine chiare e corredate di esercizi pratici su javascript, php, html
● Il sito stackoverflow.com (in lingua inglese) non
è personalmente quel che consiglierei per acquisire i rudimenti, perché riporta
semplicemente domande e risposte di programmatori, con poche righe di
esplicazione. Molti post sono inutili o poco comprensibili. Ma con pazienza si
possono trovare soluzioni interessanti a problemi particolari.
● Il forum del sito altervista.org fornisce
molte utili risposte a problemi di programmazione riguardanti siti gestiti con
php e MySQL
● www.developer.mozilla.org (inglese) contiene
numerosi esempi e soluzioni scritte e indirizzate a sviluppatori in ambito Firefox,
ma normalmente anche con gli altri browser
● Controllate alla fine di ogni articolo di
questo documento se sono presenti riferimenti a risorse internet che potrebbero
esservi utili riguardo l'argomento ("ulteriore
documentazione consultabile").
Sarà capitato a tutti di imbattersi in un
interessantissimo articolo di programmazione, e di non avere il tempo di
esaminarlo sul momento. Come salvarlo per poterlo poi rileggere in tutta calma?
L'opzione "Salva pagina con
nome" ➙ "Solo
HTML" rende necessario ricollegarsi ad internet (e nel frattempo la pagina
potrebbe essere stata tolta o cambiata…)
L'opzione "Salva pagina con
nome" ➙ "Pagina web completa" riproduce sul
vostro computer la pagina intera, ma il download è lento e il file è
ingombrante.
Google Chrome mette a disposizione una
funzionalità incredibilmente utile, che non è posseduta dagli altri browser: la
possibilità di creare in pochi secondi una perfetta copia pdf di qualsiasi
pagina.
E' sufficiente selezionare dal menu la
voce "stampa", cliccare sul bottone "modifica" e
selezionare, invece di una stampante, l'opzione "Salva come PDF".
Chrome, invece di procedere alla stampa
chiederà dove salvare il documento PDF, che potrete aprire tranquillamente in
seguito.
❍ Esistono libri consigliabili a
chi si avvicina per la prima volta a php, ajax, mySQL?
Una
premessa importante: i libri in
lingua inglese sono spesso indispensabili, per completezza e per chiarezza che
purtroppo mancano a non pochi libri italiani. Oltre a ciò, il loro prezzo è
decisamente più contenuto di questi ultimi. Moltissimi testi inglesi sono
disponibili in ebook, il che ne abbassa ulteriormente il costo. Quasi tutti
forniscono un indirizzo internet da cui scaricare le pagine con il codice già
scritto.
Ecco, senza alcuna pretesa di esaustività,
un elenco di libri che sono stati utilissimi a chi scrive e sufficienti a
fargli apprendere come creare e gestire il suo sito internet:
● Lemay-Colburn, HTML & CSS, McGraw-Hill
● Beighley,
jQuery for Dummies, Wiley
Publishing Inc.
Libro in lingua inglese. Disponibile
versione ebook
● Holzner,
Ajax: A Beginner's Guide,
McGraw-Hill
Libro in lingua inglese. Disponibile
versione ebook
Libro assolutamente consigliabile:
contiene una descrizione passo-passo di XML, javascript e DOM, ajax, php. Il
codice è commentato riga per riga e niente è lasciato senza spiegazione. Viene
fornito un link per scaricare tutti i file di esempio.
● Nixon, Learning
PHP, MySQL, JavaScript, and CSS: A Step-by-Step Guide to Creating Dynamic
Websites, O'Reilly.
Libro in lingua inglese. Disponibile
versione ebook
● Amedeo, JQuery,
Apogeo Pocket
● Rubini, MySQL
versione 5, Apogeo Pocket
● Rubini, Javascript,
Apogeo Pocket
● Canducci, PHP
5, Apogeo Pocket
● Flanagan, Javascript
Pocket Reference, Tecniche Nuove-O'Reilly
● Ferrero, SQL,
Apogeo Pocket
● Powers, Programmare
in Javascript, Tecniche Nuove-O'Reilly
Contiene anche una trattazione di ajax
● Meyer, Cascading
Style Sheets, Tecniche Nuove-O'Reilly
● Bodensiek, Effetti
speciali per il web, Jackson Libri
● Schafer, HTML
e CSS, Mondadori
● Kofler, MySQL5,
Guida completa, Apogeo
● Nikolassy, Manuale
di Javascript, Hoepli
Libro validissimo, completo e
letteralmente infarcito di codice e di esercizi.
Tutti i libri Apogeo sono disponibili in
versione ebook. Molti sono libri pocket, economici ma completi per un
apprendimento di medio livello.
Personalmente, tra gli editori italiani, chi
scrive si è trovato bene con Apogeo, Mondadori e McGraw-Hill, mentre considera
Jackson Libri di qualità inferiore e talvolta alquanto scadente.
Il sito www.altervista.org è uno dei siti
di hosting gratuiti europei più importanti. Mette a disposizione degli utenti
un nome di dominio e uno spazio sul server di 2 Gb, con un traffico di 30 Gb al
mese, 20mila query all'ora per il database mySQL.
Tra i linguaggi che vengono supportati dai
suoi server c'è php versione 5, MySQL versione 5, un programma FTP per fare
l'upload e il download dei files sul server.
Il database MySQL è gestibile in modo
semplicissimo con codice php e dal proprio account altervista tramite
PhpMyAdmin, un programma open source di gestione del database che consente di
creare tabelle e collegamenti e fare delle query.
Anche www.xoom.virgilio.it è un hosting
gratuito di buon livello, dotato di php, MySQL e di spazio illimitato su server
Un programma FTP, tipicamente, consente di
effettuare l'upload e il download di files (pagine web, files di testo o di
altro tipo) dall'hard-disk del proprio computer al server che ospita il proprio
sito e viceversa.
Uno dei migliori programmi scaricabili
gratuitamente è senz'altro Filezilla di SourceForge. Per semplicità d'uso e di
interfaccia e per completezza di funzionalità è semplicemente insuperato per
gli utenti alle prime armi, ma anche per quelli esperti è estremamente potente.
L'utente digita un URL (acronimo di
"Uniform Resource Locator"), cioè l'indirizzo di una pagina web nella
barra degli indirizzi del browser, come ad esempio:
"http://www.server.com".
Il browser cerca l'IP corrispondente a
quell'URL. Ogni computer collegato ad internet ha un indirizzo IP
("Internet Protocol address"), incluso il vostro (esistono anche
altri significati di IP che non vanno confusi con questo: "Internet Provider",
è ad esempio la società che vi fornisce l'accesso ad internet). Il browser
consulta il DNS ("Domain Name Service") per trovare l'indirizzo IP
del server associato a "server.com".
Il browser, utilizzando l'IP address,
invia una richiesta al server corrispondente a quell'indirizzo, di inviare
l'home page.
Il server, ricevuta la richiesta, cerca la
home page sul suo hard disk. I server web sono configurati in modo da inviare
una pagina di default (il file-indice) ogni volta che un browser richiede un
nome di directory. Per esempio, se il vostro link è "www.example.com/about/",
un tipico server web cercherà in quella directory un file chiamato "index.html". I nomi più
comuni, sono "index.htm", "index.html", "index.php", "index.asp". Moltissimi indirizzi ufficiali internet
forniti da società o siti, come: "www.usatoday.com" o "www.flowersgallery.com" sono solo indirizzi
di directory all'interno delle quali si trova la pagina di default, non di
rado annidato in sottodirectory. Molti server impediscono al browser di visualizzare
nella barra degli indirizzi il nome del file-indice.
Se il server si accorge che nella pagina è
incorporato del codice server-side
come php, lo esegue prima di inviare la pagina web (es. si collega ad un
database per recuperare dei dati da mostrare nella pagina; configura elementi
della pagina in base al tipo di utente che ha fatto la richiesta; ecc.).
Il server invia la pagina al browser.
Il browser mostra la pagina sul vostro
computer.
Normalmente questo processo si ripete per ogni elemento della pagina web: un
grafico, un video, una pagina di stile CSS.
Se il browser si accorge che nella pagina
è incorporato del codice client-side
(tipicamente javascript) lo esegue immediatamente dopo il caricamento della
pagina, a meno che si tratti di funzioni da attivare solo a seguito di un
evento.
E' importante porre, all'inizio del
documento, prima del tag <html>,
la seguente dichiarazione:
<!DOCTYPE HTML>
che può scriversi anche in minuscolo:
<!doctype
html>
Questo elemento della pagina dice al
browser quale versione del linguaggio HTML è usata nel codice che segue. Senza
questa indicazione, il browser è costretto ad indovinare a quale versione si
riferiscano i comandi, e questo non è molto raccomandabile.
Commentiamo la seguente dichiarazione:
<!DOCTYPE
HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">
HTML : il linguaggio utilizzato è HTML
PUBLIC : il documento è pubblico; in alternativa viene
dichiarato "SYSTEM" (il documento è una risorsa privata)
"-//W3C//DTD XHTML 1.0
Strict//EN" : si tratta di una DTD
("Document Type Declaration") in forma di FPI ("Formal Public
Identifier"). In alternativa ad una DTD in forma di FPI si può usare una
DTD in forma di URL del tipo: "http://www.w3.org/DTD/xhtml1.dtd".
Commentiamo qui sotto i singoli elementi
della dichiarazione:
//W3C : il documento fa riferimento alle specifiche del
consorzio W3C. Il segno meno (" - ") indica che le specifiche non
sono registrate all'ISO (International Standardization Organization,
Organizzazione di Standardizzazione Internazionale). Se lo fossero state ci
sarebbe un " + "
//DTD XHTML 1.0 Strict : la definizione vera e propria del tipo di documento
(DTD). Il linguaggio XHTML è l'immediato successore del linguaggio HTML 4.1, e
ha due versioni: "XHTML transitional", che è maggiormente compatibile
con il vecchio HTML 4.1 e "XHTML strict", che contiene diverse
caratteristiche incompatibili con HTML 4.1.
//EN : la lingua in cui è scritta la DTD è l'inglese
Con l'avvento di HTML5 non è più
necessaria una DTD in forma di FPI o di URL, e la dichiarazione è
semplicemente:
<!DOCTYPE
HTML>
Ecco i vari tipi di dichiarazioni per i
diversi linguaggi che si sono succeduti nel tempo:
Tipo di documento |
Dichiarazione: |
HTML5 |
<!DOCTYPE
html> |
XHTML 1.1 |
<!DOCTYPE
html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> |
XHTML 1.1 Strict |
<!DOCTYPE
html PUBLIC "-//W3C//DTD XHTML 1.1 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
XHTML 1.1 Transitional |
<!DOCTYPE
html PUBLIC "-//W3C//DTD XHTML 1.1 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
XHTML 1.1 Frameset |
<!DOCTYPE
html PUBLIC "-//W3C//DTD XHTML 1.1 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> |
XHTML 1.0 Strict |
<!DOCTYPE
html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
XHTML 1.0 Transitional |
<!DOCTYPE
html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
XHTML 1.0 Frameset |
<!DOCTYPE
html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> |
HTML 4.01 Strict |
<!DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd"> |
HTML 4.01 Transitional |
<!DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd"> |
HTML 4.01 Frameset |
<!DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
"http://www.w3.org/TR/html4/frameset.dtd"> |
HTML 3.2 |
<!DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> |
HTML 2.0 |
<!DOCTYPE
HTML PUBLIC "-//IETF//DTD HTML//EN"> |
HTML5, il linguaggio più comunemente
utilizzato attualmente, è una evoluzione del linguaggio HTML che supporta tra
l'altro anche elementi audio e video
ulteriore
documentazione consultabile:
https://en.wikipedia.org/wiki/Document_type_declaration : Pagina Wikipedia che spiega come funziona una
dichiarazione DOCTYPE (in inglese)
❍ Visualizzare il codice di una
pagina web
Con Chrome, tasto destro del mouse,
opzione "visualizza sorgente pagina"
Con Mozilla, tasto destro del mouse,
opzione "visualizza sorgente pagina"
Con Explorer, tasto destro del mouse,
opzione "HTML"
❍ Gli
elementi della pagina web
Cominciamo col distinguere block-elements e inline-elements, distinzione che ci sarà utile nel prosieguo. Ogni
elemento della pagina html ha un valore display
che può essere modificato col foglio CSS, e il valore di default per molti
elementi è block o inline.
Un block-level
element inizia sempre con una nuova linea, è seguito da un'altra linea e si
estende a sinistra e a destra quanto può (provate a settare il bordo con
l'istruzione CSS: border : 1px solid
black e vedrete che il box si estende per tutta la larghezza della pagina).
Sono esempi di block-level elements:
<div>, <table>, <h1> …
<h6>, <p>, <form>
Un block-element
ha le seguenti caratteristiche:
● Si espande automaticamente entro il suo
parent container
● Può avere margini o padding
● Se non è settata la proprietà width, o è settata ad auto si espande naturalmente ad
incorporare gli elementi figli (es. dei paragrafi entro un <div>)
● Di default è posto al disotto degli altri
elementi della pagina, nell'ordine stabilito entro il codice html o dal
posizionamento assoluto
● Ignora la proprietà vertical-align
un inline
element non inizia con una nuova linea e ha la larghezza strettamente
necessaria. Ad esempio gli elementi:
<span>, <a>, <img>,
<button>, <input>, <label>, <select>, <textarea>,
</br>
sono inline
elements. La maniera migliore di descrivere un simile elemento è di
pensarlo come un box che si comporta come
una stringa di testo.
Un inline
element ha le seguenti caratteristiche:
● E' contenuto nell'eventuale testo del blocco,
e non provoca al suo interno un ritorno a capo
● E' soggetto alle proprietà CSS white space
● Non accetta le proprietà top margin e bottom margin,
ma accetta le proprietà padding, left margin, right margin
● Non accetta le proprietà width ed height
● Accetta la proprietà vertical-align
Consideriamo la seguente rappresentazione
di un box in una pagina web:
Come si vede, qualsiasi box ha una area
del contenuto, un margine, che segna l'area più esterna, un border, che individua il confine che può
essere visualizzato come linea, un padding,
cioè una distanza tra il border e il
contenuto. Ciascuno di questi elementi (margin,
border, padding) può essere trattato separatamente rispetto al lato destro
(right segment), lato sinistro (left segment), lato superiore (top segment), lato inferiore (bottom segment), ma spesso è utile
generare il padding o i margini o lo
spessore del bordo sui 4 lati mediante istruzioni come:
margin : 5 px;
padding : 5px;
border : 5 px;
Il limite del margine si chiama outer edge o margin edge; il limite che segna la fine del bordo è il border edge; il limite dove cessa
l'effetto del padding è il padding edge,
e finalmente abbiamo l'inner edge o content edge, che circonda
immediatamente il contenuto. Per ciascuno si ha un top edge, bottom edge, right edge, left edge.
I valori possono essere dati in
percentuale, in pixel o settati come "auto".
E' possibile dare un valore negativo ai
margini: questo vuol dire che gli altri contenuti web "entreranno"
nel box invece di esserne distanziati (con il margine positivo)
Consideriamo ad esempio il seguente
codice:
<div id="parent" style="margin-left:auto;margin-right:auto;text-align:center;border:1px
solid
black;width:400px;height:50px;line-height:auto;vertical-align:middle;padding:5px;">
<div id="child"
style="border:1px solid
red;margin-left:auto;margin-right:auto;margin-bottom:-10px;height:30px;">
</div>
Questa è una
linea di testo!
</div>
Esso genera la seguente immagine nella
pagina web: il box nero delimita il div "parent", mentre il box rosso
delimita il div "child", che ha un margine negativo di -10 pixels: si
vede chiaramente che in tal caso la linea di testo "invade" lo spazio
dell'elemento.
Le proprietà di larghezza del bordo per i
vari lati sono espresse da border-top-width,
border-bottom-width, border-left-width, border-right-width, che, anziché in pixels o percentuale, possono
essere settati con i valori predefiniti thick,
medium, thin.
Le proprietà di colore sono espresse da border-top-color, border-bottom-color, border-left-color,
border-right-color.
Lo stile della linea del bordo viene
settata normalmente a border : none, oppure a border : solid (a cui si aggiunge il colore)
Passiamo ora ad illustrare una proprietà
importantissima di ogni elemento della pagina: position.
● static :
è il valore di default; gli elementi vengono posizionati secondo l'ordine in
cui appaiono nel codice della pagina web, uno dopo l'altro, verticalmente:
● relative
: l'elemento viene posizionato relativamente alla sua posizione static, precisando l'offset rispetto ad
essa:
Il codice CSS corrispondente alla
disposizione visualizzata sopra è il seguente:
#box-1 {
width: 150px;
}
#box-2 {
width: 150px;
position: relative;
left: 10px;
top: 10px;
}
#box-3 {
width: 150px;
}
● absolute
: posiziona l'elemento rispetto al documento, con le istruzioni:
position: absolute;
right: 10px;
bottom: 10px;
● fixed :
posiziona l'elemento rispetto alla finestra. Questo vuol dire che lo scrolling
non sposta l'elemento, come invece fa nel caso di position absolute:
position: fixed;
top: 0px;
Qualsiasi contenuto della pagina, secondo
le specifiche CSS, è racchiuso in un rettangolo chiamato CSS box. Nel caso di block-elements
come <div> è l'elemento stesso a formare il rettangolo, chiamato block box. Ma nel caso di un inline element e contiene un testo
lungo, richiede più rettangoli per essere mostrato. Questi rettangoli sono
chiamati anonymous boxes. Si vede
così che i contenuti di un elemento possono consistere di un solo rettangolo o
di rettangoli multipli. E' possibile acquisire tutti questi rettangoli con la
funzione element.getClientRects(),
mentre il metodo element.getBoundingClientRect()
restituisce un unico elemento, che è il più piccolo rettangolo che contiene
tutti quelli contenuti in element.getClientRects().
❍ Come centrare orizzontalmente e
verticalmente un elemento nella pagina web
Per la terminologia che sarà utilizzata (block element e inline element) si veda il paragrafo sugli elementi della pagina
web. Sinteticamente si può dire che un block
element è un riquadro che può contenere altri riquadri o linee di testo,
mentre un inline element è un
elemento che è una linea di testo o può essere inserito entro una linea di
testo senza produrre un ritorno a capo.
Come regola generale, si può porre un
block element o un inline element all'interno di un altro block-element e un
inline element all'interno di un altro inline element, ma non un block element entro un inline element.
Il primo
metodo per centrare orizzontalmente si impiega quando un elemento inline
(da centrare) è all'interno di un block-element
come <p> o <div>. Si consideri il seguente codice:
<div
align="center">
Hello World!
</div>
o, in alternativa, ricorrendo alle
proprietà di stile:
<div style="text-align:center">
Hello World!
</div>
Esso centrerà orizzontalmente il testo
"Hello World!" nella pagina. Ma consideriamo il seguente codice:
<div
style="text-align:center; width:300px;">
Hello World!
</div>
In questo caso il testo non sarà centrato, perché l'elemento
<div>, che prima occupava tutta la larghezza della pagina, ora è largo
solo 300 pixel e per default viene posizionato a sinistra. Per centrare
l'elemento inline (il testo) occorre in questo caso prima centrare il
box-element (il tag div), come viene mostrato qui di seguito.
Il secondo
metodo per centrare orizzontalmente si può impiegare per posizionare nella
pagina un block-element come:
<div id="MyDiv"
class="MyDivClass">
Questo è il testo da centrare
</div>
è sufficiente, nel foglio di stile,
settare ad "auto" sia margin-left che margin-right: il browser capirà
automaticamente di dover centrare orizzontalmente:
<style
type ="text/css">
.MyDivClass {
margin-left: auto;
margin-right: auto;
}
</style>
Se si tratta di un inline element un metodo è quello di agire sull'elemento-genitore
(parent element) e settare la proprietà align:
<div id="MyDiv"
align="center">
<p>Questo è il testo da centrare</p>
</div>
Centrare invece l'elemento verticalmente è
molto più complicato. In particolare l'istruzione:
vertical-align:
middle;
Ma valign
agisce solo su celle di tabella, mentre vertical-align
agisce solo su celle di tabella e su certi elementi inline. I suoi valori hanno
senso rispetto ad un elemento-parent inline.
Ma sfortunatamente vertical-align non si applica a block-level elements, come un
paragrafo entro un <div>, che è il caso tipico in cui si ha bisogno di
centrare verticalmente.
Il primo
metodo per centrare verticalmente si può impiegare quando entro il
<div> esiste una sola linea di testo. Si può settare la proprietà css line-height ad un valore superiore a
quello reso necessario dal font. Questo spazio aggiuntivo sarà ripartito
equamente al disopra e al disotto del testo, che ne risulterà centrato
verticalmente. Al limite si può settare l'altezza della linea ad un valore pari
a quello dell'elemento <div> che lo contiene, ma questo non è necessario.
Ecco un codice tipico:
html:
<div id="parent">
<div
id="child">Content here</div>
</div>
css:
#child {line-height: 200px;}
Come già detto, questo codice non funziona se ci sono più linee di testo.
Il secondo
metodo per centrare verticalmente non è altro che una applicazione del
primo metodo agli elementi <img> che contengono una immagine.
html:
div id="parent">
<img
src="image.png" alt="" />
</div>
css:
#parent {
line-height: 200px;
}
#parent img {
vertical-align: middle;
}
Il terzo
metodo per centrare verticalmente consiste nel settare mediante css il
<div> genitore come tabella e l'elemento-figlio come cella di tabella. In
tal modo possiamo utilizzare l'istruzione vertical-align:
middle ed essa funzionerà.
html:
<div id="parent">
<div id="child">Content here</div>
</div>
css:
#parent {display: table}
#child {
display: table-cell;
vertical-align: middle;
}
Il quarto
metodo per centrare verticalmente ricorre al posizionamento assoluto
dell'elemento-figlio (mentre l'elemento-genitore ha posizionamento relativo).
Esso funziona per block-elements all'interno di un altro block-element.
html:
<div id="parent">
<div id="child"></div>
</div>
css:
#parent {position: relative}
#child {
position:
absolute;
top: 50%;
left: 50%;
height: 30%;
width: 50%;
margin: -15% 0 0 -25%;
}
Il quinto
metodo per centrare verticalmente impiega anch'esso il posizionamento
relativo dell'elemento-genitore e il posizionamento assoluto
dell'elemento-figlio. In questo caso noterete che i valori del posizionamento
assoluto sono "0". Ma quando il browser incontra l'istruzione margin : auto, che si riferisce ai 4
margini, è forzato a distribuirli uniformemente, a destra/sinistra e in
alto/basso, centrando l'elemento-figlio.
html:
div
id="parent">
<div id="child">Content
here</div>
</div>
css:
#parent {position: relative;}
#child {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 50%;
height: 30%;
margin: auto;
}
Il sesto
metodo per centrare verticalmente consiste nello stabilire i valori del padding (bottom, top, left, right) sia per l'elemento-genitore che per
l'elemento-figlio. Questo centrerà il contenuto dell'elemento-figlio e
l'elemento-figlio all'interno dell'elemento genitore.
html:
<div id="parent">
<div id="child">Content here</div>
</div>
css:
#parent {
padding: 5% 0;
}
#child {
padding: 10% 0;
}
I valori di larghezza e altezza dei
block-elements sono, nel codice sottostante, non dichiarati. Se si stabilisce
un valore per i box occorre fare calcoli più accurati. Per esempio, se
l'altezza del genitore è 400 px e del figlio è 100 px noi dobbiamo settare sia padding-top che padding-bottom ad un valore di 150, perché 150 + 150 + 100 = 400.
Invece di operare sul padding si possono settare margini eguali per l'elemento figlio.
Il settimo
metodo per centrare verticalmente richiede un <div> vuoto che
viene posizionato col metodo del floating,
che normalmente viene usato per le immagini.
Con questa proprietà è possibile rimuovere
un elemento dal normale flusso del documento e spostarlo su uno dei lati
(destro o sinistro) del suo elemento contenitore. Il contenuto che circonda
l’elemento scorrerà intorno ad esso sul lato opposto rispetto a quello indicato
come valore di float
Ad esempio, con l'istruzione: float : right, l'immagine sarà
posizionata nello stesso contenitore allo stesso livello del testo, ma a
destra. Più floating elements possono essere disposti uno accanto all'altro con
l'istruzione: float : left.
Posizioniamo il floating div a sinistra o
a destra e gli diamo un'altezza del 50% del genitore. Il testo viene posto da
css al disotto del floating div. Il margin-bottom
negativo serve a creare un vuoto sotto il floating element, dove il testo può
fluire (altrimenti il testo verrà spinto a destra del floating element).
html:
<div id="parent">
<div id="floater"></div>
<div id="child">Content here</div>
</div>
css:
#parent {height: 250px;}
#floater {
float: left;
height: 50%;
width: 100%;
margin-bottom: -50px;
}
#child {
clear: both;
height: 100px;
}
Una compagna quasi inseparabile della
proprietà float è la proprietà clear che, se applicata ad
un elemento successivo ad uno reso float, impedisce che questo subisca il
float. L’origine di tale proprietà è questa: visto che il float sposta un
elemento dal flusso normale del documento, è possibile che esso venga a
trovarsi in posizioni non desiderate, magari al fianco di altri elementi che
vogliamo invece tenere separati. clear risolve questo problema.
Nell'esempio sopra riportato, l'istruzione clear : both, impedisce che il floating si trasmetta sia da destra
che da sinistra.
❍ Come si crea e si configura una tabella con i
fogli di stile
Ecco la struttura essenziale di una
tabella con due righe e due colonne:
<table>
<tr>
<td>
Questa è la cella della prima colonna, prima
riga
</td>
<td>
Questa è la cella della seconda colonna,
prima riga
</td>
</tr>
<tr>
<td>
Questa è la cella della prima colonna,
seconda riga
</td>
<td>
Questa è la cella della seconda colonna,
seconda riga
</td>
</tr>
</table>
I tag <td> rappresentano le celle
della tabella, e il testo va inserito al loro interno.
Non
si può scrivere direttamente
all'interno di un tag <tr>; occorre sempre
inserirvi un tag <td> in cui scrivere. In altre parole, non funziona un
codice come:
<table>
<tr>
Questo non funziona
</tr>
</table>
mentre funziona un codice come:
<table>
<tr>
<td>
Questo funziona
</td>
</tr>
</table>
All'interno di un tag <td> può
essere inserita un'altra tabella. Attenzione: non si può semplicemente creare un'altra riga e inserire la tabella
direttamente nella riga:
...
<tr>
<table>
...
</table>
</tr>
...
Occorre sempre inserire la sotto-tabella in un elemento <td> della
tabella principale:
<table>
<tr>
<td>
<table>
...
</table>
</td>
</tr>
</table>
In altre parole, un codice come il
seguente, che inserisce la tabella direttamente in una nuova riga, non
funziona:
<table>
<tr>
<table>
...
</table>
</tr>
</table>
A meno che non si voglia configurare
diversamente ogni singola cella, per la loro configurazione (margini, ecc.) si
impone l'uso di un foglio di stile. Il seguente foglio riquadra ogni cella con
un margine in nero (esistono margini separati per la tabella e le celle:
settare un margine per la tabella non equivale a settarlo per le celle):
css
<style
type ="text/css">
.TableCell
{
border : 1px solid black
}
</style>
html
<td
class="TableCell"> ... </td>
Il valore "1px" indica lo
spessore del bordo in pixel.
Il valore "solid" indica che il
bordo è una linea continua.
Il valore "black" indica il
colore. Per i codici dei principali colori si può consultare la pagina internet
http://www.w3schools.com/html/html_colornames.asp.
In alternativa, si dovrebbe introdurre in
ciascun tag <td> una dichiarazione di stile del tipo:
<td
style="border : 1px solid black;">
Quando i settaggi del foglio di stile
diventano numerosi, questo sistema risulta assai scomodo, perché le stringhe di
stile diventano eccessivamente lunghe, ed è preferibile inserire nel tag solo
il richiamo ad un foglio di stile.
Chi scrive consiglia, in fase di creazione
di una tabella, di inserire sempre
margini visibili, perché aiuta notevolmente a capire dove siano situate le
celle e gli effetti dei vari comandi di centraggio ecc. (Si tenga presente che
è possibile inserire un bordo alle tabelle e alle celle ma non alle righe).
Come si centra orizzontalmente una
tabella? E' sufficiente inserire la proprietà align="center":
<table
align="center">
Ecco ora la struttura della tabella
arricchita con i fogli di stile:
css:
<style
type ="text/css">
.Table {
border : 1px solid red;
padding : 10px;
border-collapse : separate;
border-spacing : 10px;
}
.TableCell {
border : 1px solid black;
text-align : center;
padding : 10px;
}
</style>
html:
<table
class="Table" align="center">
<tr>
<td class="TableCell"
style="border-color:blue;">
Questa è la cella della prima colonna, prima
riga
</td>
<td class="TableCell">
Questa è la cella della seconda colonna,
prima riga
</td>
</tr>
<tr>
<td class="TableCell">
Questa è la cella della prima colonna,
seconda riga
</td>
<td class="TableCell">
Questa è la cella della seconda colonna,
seconda riga
</td>
</tr>
<tr>
<td class="TableCell"
colspan="2">
<table align="center" style="border:1px solid
red;padding:10px;">
<tr>
<td class="TableCell">
Questa è la cella della tabella contenuta nella terza riga
</td>
</tr>
</table>
</td>
</tr>
</table>
Ed ecco come appare la tabella nella
pagina (i bordi delle tabelle sono in rosso, mentre i bordi delle celle sono in
nero, tranne quelli della prima, che sono in blu):
Analizziamo il foglio di stile della
tabella più esterna:
.Table {
border : 1px solid red;
padding : 10px;
border-collapse : separate;
border-spacing : 10px;
}
padding : 10px (stabilisce la distanza tra i margini della tabella e
i margini delle celle)
border-spacing : 10px (stabilisce la distanza intorno a ciascuna cella)
(l'attributo "cellspacing" non è più supportato da HTML5)
border-collapse : separate (stabilisce che i bordi della tabella e delle celle
appariranno distinti; va sempre settata come "separate" perché la
proprietà "border-spacing" funzioni)
Si noti come la distanza del bordo delle
celle dal bordo della tabella più esterna è doppia rispetto alla distanza
interna tra i bordi delle celle. Questo perché il valore di "padding" si somma a
quello di "border-spacing".
Si noti l'istruzione (evidenziata con lo
stesso colore nel codice):
<td
class="TableCell" colspan="2">
Il numero di celle delle righe successive
è identico a quello delle righe precedenti, quindi la sotto-tabella verrebbe
inserita a sinistra (cella di sinistra della terza riga) e non sarebbe
centrabile. Per centrare la sotto-tabella occorre unificare le due righe
settando la proprietà "colspan" in modo che la cella si estenda per due
colonne.
Analizziamo il foglio di stile delle
singole celle:
.TableCell {
border : 1px solid black;
text-align : center;
padding : 10px;
}
text-align : center (centra il testo all'interno della cella)
padding : 10px (stabilisce una distanza di 10 pixel tutto intorno al
testo, rispetto ai margini della cella: a destra, sinistra, in alto e in basso)
Si noti che sia nel caso della tabella che
nel caso della cella, la proprietà "padding" può essere specificata rispetto ad un singolo
lato: "padding-left", "padding-right", "padding-top", "padding-bottom".
Anche la proprietà "border-spacing" della
tabella può essere settata orizzontalmente e verticalmente inserendo due
valori:
border-spacing
: 10px 20px;
Prendiamo in esame ora il modo in cui la
tabella esterna è stata centrata orizzontalmente. Questo è stato fatto
inserendo " align = 'center' " entro il tag <table>:
<table
class="Table" align="center">
ma questo metodo è ufficialmente
sconsigliato (in gergo, "deprecated") a favore dell'uso dei fogli di
stile (CSS). La tabella si può centrare orizzontalmente aggiungendo al foglio
di stile le istruzioni:
margin-left :
auto;
margin-right
: auto;
che fanno capire al browser che lo spazio
a destra e a sinistra deve essere identico.
Per operare entro una sola cella una variazione rispetto allo stile assegnato
tramite CSS con una dichiarazione di classe è sufficiente inserirvi una
dichiarazione di stile del tipo:
<td
class="TableCell" style="border-color:blue;">
con cui abbiamo colorato di blu il bordo
della prima cella. La dichiarazione style="…" prevale su quella
contenuta nel foglio CSS associato all'elemento tramite la dichiarazione class="TableCell".
Esistono anzi attributi che non possono essere inseriti in un CSS e
necessitano di essere inseriti direttamente nel tag. Questo è il caso ad
esempio degli attributi:
align =
"center"
colspan =
"2"
che non possono essere inseriti in un CSS
come
align :
center;
colspan : 2;
Riprendiamo ora in esame l'attributo
"colspan" e il suo analogo per le righe: "rowspan".
L'attributo "colspan" è utilizzato per raggruppare due celle di
colonne adiacenti. Si supponga di avere una tabella composta da due colonne e
tre righe. Il suo aspetto normale sarebbe:
Applicando l'attributo "colspan", invece,
potremmo ottenere una struttura del genere:
L'attributo "rowspan" è identico
al precedente con la differenza che il raggruppamento delle celle non avviene
in orizzontale (per colonne) ma in verticale (per righe). Segue un esempio:
Possono sorgere problemi con l'uso ad
esempio di "colspan" quando in un foglio di stile è stato settata la
larghezza delle celle ad un valore definito:
width : 350px
L'effetto che ne risulta è il seguente:
Come si vede, ora la tabella nella terza
riga non occupa l'intera larghezza
della riga, come vorremmo, perché, anche se le celle della terza riga sono
state ridotte ad una sola cella, questa avrà comunque la stessa larghezza delle
altre: 350px, che rappresenta solo metà
della larghezza della riga. Per rimediare, si può inserire una variazione di
stile nel tag della cella che occupa due colonne, stabilendo una larghezza
doppia (700px):
<td
class="TableCell" colspan="2" style="width:700px;">
Una soluzione più elegante sarebbe quella
di inserire nei CSS una variazione dello stile "TableCell"
limitatamente alle celle con l'attributo " colspan='2' ":
.TableCell[colspan="2"]
{
width: 700px;
}
Si noti che, in alternativa a nomi di
vostra creazione per gli stili di cella, c'è un nome standard ("td") che può essere
utilizzato:
td {
border : 1px solid black;
text-align : center;
padding : 10px;
}
Ma gli attributi si applicherebbero a tutte le celle di tutte le tabelle della pagina web. In alternativa, come abbiamo
fatto noi, si può utilizzare un nome di nostra creazione come ".TableCell" per le
celle di ciascuna tabella, oppure utilizzare un selettore, come abbiamo visto
fare sopra con "colspan":
td[colspan="2"]
{
width: 700px;
}
Tutte le maggiori applicazioni web, da
Yahoo a Google a Facebook ad EBay utilizzano massicciamentte, oltre che il
linguaggio html, anche css e javascript, nonché Ajax e PhotoShop.
Microsoft è sempre stata accusata di
scarsa attenzione al rispetto degli standard, e lo sviluppo con Internet
Explorer 5 e 6 si è rivelato in passato decisamente problematico. Con l'uscita
delle versioni 7, 8, 9 le cose sono migliorate, ma ancora oggi siamo lontani da
una piena compatibilità e anzi, specifiche CSS ormai molto datate continuano a
non essere supportate correttamente nei browser di casa Microsoft.
Quanto ai problemi di compatibilità con le
vecchie versioni di Explorer, ormai si può dire che essi sono stati risolti nel
senso di un unanime rigetto di tali
piattaforme. Ormai tutti gli sviluppatori, dai programmatori indipendenti
alle grandi software houses, hanno abbandonato il supporto alle versioni di
Internet Explorer (IE) anteriori alla 9, per numerose ragioni: presenza di
bachi, problemi di sicurezza, incompleto supporto alle specifiche HTML e
javascript, caratteristiche custom non utilizzabili con gli altri browser, e
chi più ne ha più ne metta.
Purtroppo, le vecchie versioni di Explorer
sono ancora relativamente diffuse; ma siete comunque caldamente sconsigliati dal
provare a far funzionare le vostre pagine web con tali versioni. L'unica cosa
da fare è far apparire un messaggio che dichiara che il vostro programma non è
supportato dalla versione di Explorer presente sul browser, perché anteriore
alla 9, e stabilire una istruzione condizionale che disattiva automaticamente
il funzionamento delle routine critiche del vostro sito, mantenendo solo quelle basilari. Ad
esempio, il sito dello scrivente blocca l'esecuzione del codice delle ToolTips
per timore che possa provocare blocchi o apparizione di fastidiosi messaggi di
errore.
L'utilizzo di ajax con Explorer presenta
alcuni problemi che illustreremo qui di seguito.
Le versioni precedenti a Explorer 9 non
hanno un oggetto XMLHttpRequest
nativo incorporato nel modello javascript di documento, quindi è necessario
aggiungere all'inizio della propria routine ajax un codice per testare se un
tale oggetto esista, e in caso contrario ricorrere al vecchio codice Microsoft
ActiveX per crearlo:
var
XMLHttpRequestObject = false;
if
(window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if
(window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
Il codice Ajax per fare il download dal
server di documenti XML non funziona correttamente con Explorer, persino con le
versioni più aggiornate. Consideriamo un codice come il seguente:
<script
language = "javascript">
XMLHttpRequestObject = new XMLHttpRequest();
XMLHttpRequestObject.open("GET",
"colors.xml");
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
var
xmlDocument=XMLHttpRequestObject.responseXML;
var colors =
xmlDocument.getElementsByTagName("color");
alert(colors.length);
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
Questo codice, che funziona perfettamente
con Chrome e Firefox, generando un alert box che indica il numero dei tag <color> contenuti nel file colors.xml con Explorer non funziona, per problemi di cache.
Internet Explorer è l'unico browser che fa una copia cache automatica di tutti
i download effettuati con ajax. Il problema sorge per il fatto che, quando con GET si va a caricare il file colors.xml, Explorer preleva
immancabilmente dalla memoria del computer client i dati dell'ultimo download
corrispondente alla stessa URL, senza collegarsi al server per acquisire dati
aggiornati. Questo provoca immancabilmente malfunzionamenti, e nell'alert
compare come numero dei nodi <color>
il numero "0", che vuol dire che Explorer considera i dati in formato
errato e non li legge.
Per evitare questo inconveniente è
sufficiente rendere la URL di ogni chiamata diversa dall'altra aggiungendo ad
esempio come parametro una stringa con il tempo del momento in cui viene fatta
la chiamata (si veda la riga rossa nel codice di cui sopra):
<script
language = "javascript">
XMLHttpRequestObject = new XMLHttpRequest();
XMLHttpRequestObject.open("GET",
"colors.xml?timestamp=" + new Date().getTime());
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
var
xmlDocument=XMLHttpRequestObject.responseXML;
var colors =
xmlDocument.getElementsByTagName("color");
alert(colors.length);
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
Persino jQuery non funziona se la cache
non è disabilitata. Il codice per disabilitarla è il seguente:
$.ajax(
cache: false,
url:
'http://myurl',
data: {}
);
Oppure si può disabilitarla una volta per
tutte per le chiamate ajax:
$.ajaxSetup({
cache: false });
Altri sistemi che si possono provare
consistono nella disabilitazione del controllo del tipo di dati che viene fatta
da Explorer tramite l'istruzione:
<script
language = "javascript">
XMLHttpRequestObject = new XMLHttpRequest();
XMLHttpRequestObject.overrideMimeType("text/xml");
XMLHttpRequestObject.open("GET",
"colors.xml");
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
var xmlDocument=XMLHttpRequestObject.responseXML;
var colors =
xmlDocument.getElementsByTagName("color");
alert(colors.length);
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
Si può anche indicare ad Explorer che si
sta scaricando dati in formato xml:
<script
language = "javascript">
XMLHttpRequestObject = new XMLHttpRequest();
XMLHttpRequestObject.open("GET",
"colors.xml");
XMLHttpRequestObject.setRequestHeader('Content-Type', 'text/xml');
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
var
xmlDocument=XMLHttpRequestObject.responseXML;
var colors =
xmlDocument.getElementsByTagName("color");
alert(colors.length);
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
Con Explorer non funziona sempre
l'istruzione jQuery:
$("#mydiv").load("student.html");
e anche in questo caso va disattivata la
copia cache automatica (vedi sopra)
❍ Come rilevare le versioni di
Explorer e in particolare quelle anteriori a Explorer 9
Ecco un semplice codice consigliato nel
sito Microsoft per stabilire se il browser è Explorer ed eventualmente la
versione di Explorer:
function getInternetExplorerVersion()
// Returns the version of Internet Explorer or a -1
// (indicating the use of another browser).
{
var rv = -1;
// Return value assumes failure.
if
(navigator.appName == 'Microsoft Internet Explorer')
{
var ua =
navigator.userAgent;
var
re = new RegExp("MSIE
([0-9]{1,}[\.0-9]{0,})");
if
(re.exec(ua) != null)
rv =
parseFloat( RegExp.$1 );
}
return rv;
}
function checkVersion()
{
var msg =
"You're not using Internet Explorer.";
var ver =
getInternetExplorerVersion();
if ( ver
> -1 )
{
if ( ver
>= 8.0 )
msg =
"You're using a recent copy of Internet Explorer."
else
msg =
"You should upgrade your copy of Internet Explorer.";
}
alert( msg
);
}
L'unico problema è che questo codice non funziona: infatti, la stringa navigator.appName, anche se il browser è Explorer, è (quasi)
invariabilmente "Netscape". Infatti le specifiche del linguaggio
HTML5 consentono a qualsiasi browser di dichiarsi "Netscape",
ufficialmente per ragioni di compatibilità.
La verità è invece un'altra: sempre più
programmatori utilizzavano il codice di rilevazione del tipo e versione del browser
per escludere quelli che ritenevano
malfunzionanti con il proprio software. I creatori di browser si resero
rapidamente conto che se ingenuamente e onestamente dichiaravano il nome e la
versione del loro browser nella stringa userAgent, esso rischiava di essere escluso dai programmatori.
In particolare Microsoft, il cui browser era all'epoca pieno di caratteristiche
customizzate e non supportava pienamente gli standard HTML e javascript era il
fornitore che aveva più da temere al riguardo. Ad esempio la stringa userAgent di Explorer 5 è la seguente: "Mozilla/4.0
(compatible; MSIE 5.01; Windows NT)".
I browser diversi da Explorer, temendo al contrario di essere discriminati,
riportavano stringhe userAgent
indistinguibili da quelle di Explorer. Il risultato pratico di tutto questo è
che le stringhe userAgent
sono inservibili e prive di significato.
I programmatori più esperti utilizzano la feature detection, cioè scrivono un
codice che controlla specificamente se l'istruzione o la caratteristica che a
loro interessa sia supportata dal browser, ma le istruzioni sono lunghe,
complesse, numerose, e non sono alla portata del programmatore alle prime armi.
Dato che ormai, come già detto, quasi tutti gli sviluppatori hanno deciso di
abbandonare il supporto alle versioni di Explorer anteriori alla 9, sarà per la
maggior parte delle necessità sufficiente sincerarsi che la versione del
proprio browser non sia anteriore alla 9. Ecco un semplice codice per rilevare
se la versione del browser che riceve la pagina è precedente a IE 9:
function CheckExplorerVersion()
{
var div =
document.createElement("div");
div.innerHTML
= "<!--[if lt IE 9]><i></i><![endif]-->";
var
isIeLessThan9 = (div.getElementsByTagName("i").length == 1);
if
(isIeLessThan9) {return false;}
else {return
true;}
}
Ecco una versione più sofisticata, in
grado di rilevare tutte le versioni fino alla 9:
function CheckExplorerVersion()
{
var undef;
var v = 3;
var div =
document.createElement('div');
while
(
div.innerHTML
= '<!--[if gt IE '+(++v)+']><i></i>< ! [endif] –>',
div.getElementsByTagName('i')[0]
);
if (v >
4){return v}
else {return
undef}
}
La funzione dà i seguenti risultati:
CheckExplorerVersion() == undefined (il browser non è Explorer o si tratta di versioni
inferiori a Explorer 5 o di Explorer 9 e versioni superiori)
CheckExplorerVersion() == 4 < numero < 9 (Explorer 5, 6
o 7)
Entrambi i blocchi di codice si basano su
una caratteristica presente nelle versioni di Explorer anteriori alla 9, ma
successivamente non più supportata da Microsoft: i commenti condizionali. Un commento condizionale ha la forma
seguente:
<!--[if expression]> HTML <![endif]-->
dove HTML può essere qualsiasi blocco di codice html,
comprensivo di tag e di testo. Le principali espressioni standard per testare
le versioni di Explorer sono illustrate dai seguenti esempi:
[if IE]
("se il browser è Explorer")
[if !IE] ("se il browser non è Explorer")
[if IE 7] ("se il browser è Explorer 7")
[if lt IE 5.5]
("se il browser è una versione di Explorer inferiore a 5.5") ("lt"
= "less than")
[if lte IE 6] ("se il browser è una versione di Explorer inferiore
o uguale a 6 ") ("lte" = "less than or equal")
[if gt IE 5]
("se il browser è una versione di Explorer superiore a 5 ") ("gt"
= "greater than")
[if gte IE 7]
("se il browser è una versione di Explorer superiore o eguale a 5") ("gte"
= "greater than or equal")
Il codice non fa altro che creare in
memoria (senza inserirlo nel documento) un tag <div> che contiene un commento condizionale che crea un
elemento <i></i> vuoto (se contenesse qualcosa i caratteri potrebbero
essere visualizzati con effetto antiestetico), e poi testare l'esistenza nel
tag <div>
dell'elemento <i> mediante il codice:
div.getElementsByTagName('i')[0]
Nelle versioni anteriori alla 5 e
successive alla 8 i commenti condizionali non funzionano, e quindi
l'espressione ha valore null, che l'istruzione while() trasforma in false.
Javascript è un linguaggio client-side, cioè che viene eseguito dal
computer di chi riceve i contenuti web, e che può essere inserito all'interno
di una pagina web (normalmente nella sezione head) tra due tag, con istruzioni
separate da puntoevirgola, come ad esempio:
<script type="text/javascript">
prima istruzione;
seconda istruzione;
..................
ultima istruzione;
</script>
oppure entro un tag html, come ad esempio:
<p onclick="alert('Hello World');">Clicca
qui per far apparire il messaggio</p>
Un tag <script> può contenere sia
istruzioni separate, che vengono eseguite automaticamente al caricamento della
pagina web, che la definizione di funzioni, che vengono invece eseguite quando
richiamate:
<script type="text/javascript">
alert("Hai aperto la pagina web");
function MyFunction()
{
document.write("La funzione è stata
richiamata");
}
</script>
La prima istruzione alert viene eseguita
immediatamente: al caricamento appare il messaggio "Hai aperto la pagina
web", mentre la funzione MyFunction
viene richiamata in seguito e scrive una riga di testo nel documento.
Una funzione ha una struttura tipica:
function MyFunction(var1, var2, ..., varN)
{
return(var1*var2*...*varN);
}
Possono esserle passati dei parametri che
sono specificati nella parentesi che la segue o non avere parametri (la
parentesi deve comunque essere presente, anche se vuota)
Può restituire un valore con l'istruzione return e/o compiere delle operazioni sul documento o far
apparire messaggi.
La struttura tipica di javascript è il
richiamo di una funzione al verificarsi di un evento, che consiste
principalmente in un evento di tastiera
(onKeyDown, onKeyPress,
onScrolling) o in un evento di mouse (onMouseOver, onClick,
onMouseOut) o in un evento riguardante l'apertura o la chiusura
del documento (onLoad,
OnUnLoad). Al verificarsi dell'evento viene richiamata una
funzione.
Ecco un elenco degli eventi più
comunemente utilizzati:
Evento |
Si verifica quando… |
onabort |
una
azione è interrotta |
onblur |
un
elemento perde la proprietà focus |
onchange |
si
verifica un cambiamento nel contenuto di un elemento, come ad es. un box di
testo |
onclick |
si
è cliccato su un elemento |
ondblclick |
si
è cliccato due volte su un elemento |
ondragdrop |
è
stata eseguita una operazione drag-and-drop (un elemento è stato trascinato
nella pagina) |
onerror |
si
è verificato un errore javascript |
onfocus |
un
elemento acquisisce la proprietà focus |
onkeydown |
un
tasto è premuto |
onkeyup |
un
tasto è rilasciato dopo essere stato premuto |
onload |
viene
caricata la pagina |
onmousedown |
è
premuto un bottone del mouse |
onmousemove |
il
mouse è spostato sulla pagina |
onmouseout |
il
mouse esce da un elemento della pagina |
onmouseover |
il
mouse entra nella zona di un elemento della pagina |
onmouseup |
è
rilasciato un bottone del mouse dopo essere stato premuto |
onreset |
viene
cliccato il bottone di reset |
onresize |
vengono
modificate le dimensioni o la posizione di un elemento della pagina |
onsubmit |
l'utente
clicca un pulsante di tipo "submit" |
onunload |
la
pagina è scaricata |
onscrolling |
si
è effettuato lo scrolling della pagina |
Il codice contenuto nella funzione o in
genere in uno script può accedere in lettura e in modifica al contenuto e agli
attributi interni (es. l'attributo href
e l'attributo title di un tag <a>) di un tag e ai fogli di stile tramite il modello DOM
(Document Object Model: vedi più
avanti). Può inoltre aprire e leggere files, acquisire data e ora e altri dati
riguardanti il sistema, può fare apparire messaggi e ricevere input tramite box
di dialogo e di input. Inoltre, javascript implementa un set completo di
istruzioni per la lettura di documenti XML.
Ecco di seguito l'esempio di una pagina
html in cui cliccando su un elemento si attiva una funzione che dichiara il
nome di quell'elemento.
<html>
<head>
<script type="text/javascript">
function
MyFunction(MyDiv)
{
alert("hai cliccato sul " +
MyDiv.innerHTML);
}
</script>
</head>
<body>
<div onclick="MyFunction(this)">
BOX1
</div>
</br>
<div onclick="MyFunction(this)">
BOX2
</div>
</br>
<div onclick="MyFunction(this)">
BOX3
</div>
</body>
</html>
Alla funzione MyFunction viene inviato come argomento il parametro this, che è un oggetto corrispondente al div in cui è
inserita l'istruzione onclick.
Questo oggetto consente l'accesso a tutte le proprietà del tag <div>, incluso il testo compreso al suo interno, tramite
l'istruzione:
MyDiv.innerHTML
L'output nella finestra, cliccando su BOX1
è il seguente:
Aprite la pagina Experiments_1.htm
, per osservare altre cose che possono fare le routines javascript e
visualizzatene il codice.
Javascript è un linguaggio potente e molto
migliorato col tempo in termini di performance
e di affidabilità, ma il codice risulta piuttosto ingombrante, anche perché col
tempo funzionalità non essenziali della pagina, come effetti grafici e
animazione, che prima erano affidate a tecnologie differenti come immagini
animate o flash, ora sono gestite con javascript. Inoltre, l'accesso alla
struttura DOM (Document Object Model)
del documento al fine di manipolare gli elementi della pagina avviene
attraverso un insieme di API (Application
Programming Interface), che sono oggetti e metodi di interfaccia, il cui
uso non è affatto banale. La natura fortemente strutturata e gerarchita dei
documenti HTML e XML si riflette sulla struttura del DOM, la cui interrogazione
e modifica richiede verbose operazioni di iterazione e ricorsione. Il
necessario traversamento dell'albero che rappresenta gli oggetti del documento
può quindi richiedere una quantità significativa di codice.
Javascript è un linguaggio alquanto
laborioso, con un debugging difficile, che non perdona il minimo errore di
sintassi (a differenza di HTML) e il minimo scambio di maiuscole e minuscole, e
le cui istruzioni sono a volte poco intuitive.
Si aggiunga che ormai è diventato
indispensabile al programmatore l'utilizzo di codice Ajax (Asynchronous Javascript and XML): un mix di javascript, xml e php
che risulta complicato e poco gestibile se scritto in javascript puro.
Infine, il fatto che esistano più browser
e più sistemi operativi rende necessario scrivere altro codice ingombrante (e
difficilmente alla portata di un programmatore alle prime armi) per assicurare
un minimo di compatibilità della propria pagina con i principali browser.
I programmatori, che in un primo tempo
avevano sviluppato soluzioni javascript ciascuno indipendentemente dall'altro,
si resero ben presto conto della follia di costruire da soli un sito internet
partendo da zero, e sentirono sempre di più la necessità di condividere le
routine utilizzate.
Per ovviare a questi inconvenienti sono
state rese disponibili in rete, gratuitamente o a pagamento, delle librerie
javascript, che racchiudono funzionalità studiate per superare queste
limitazioni.
Una delle più affermate è appunto jQuery (http://jquery.com). L'home page del progetto afferma che si tratta di
"una libreria JavaScript veloce e concisa che semplifica il traversamento
dei documento HTML, la gestione degli eventi, l'animazione e le interazioni
Ajax per uno sviluppo web rapido". Al difuori delle parole dei suoi stessi
autori, jQuery è comunemente considerato uno dei protagonisti della rinascita
della tecnologia javascript soprattutto per via di tre caratteristiche
fondamentali: la buona capacità di nascondere le peculiarità dei browser
offrendo un'interfaccia e funzionalità omogenee; la possibilità di accedere a
elementi della struttura DOM attraverso selettori CSS e la semplicità d'uso.
Con jQuery è possibile utilizzare tecnologie all'ultimo grido, come Ajax e CSS,
anche su browser che non le supportano direttamente.
Sicuramente, frequentando i blog di
argomento tecnico, avrete sentito decantare le potenzialità strepitose di altre
librerie javascript, anche in confronto a jQuery. Come scegliere la libreria
giusta? Quando si sceglie una libreria per integrare un linguaggio di
programmazione, occorre considerarne attentamente il grado di diffusione,
perché librerie molto valide ma poco utilizzate finiscono ben presto per non
essere supportate dagli sviluppatori e costringono a riscrivere completamente
il codice per eliminarle. Da questo punto di vista, jQuery è una libreria
affermata sulla Rete da diversi anni e vanta il fatto di essere utilizzata da
molte organizzazioni di primaria importanza, come Google, Dell, Bank of
America, NBC, CBS, Netflix, Technorati, Mozilla.org, WordPress e Drupal, per
citare solo i riferimenti più importanti indicati nell'home page del sito
ufficiale della libreria. Infine, jQuery è estremamente leggera (la versione compatta
richiede solo 32 Kb, corrispondenti alla quantità di dati di una foto di media
qualità).
E' possibile scaricare jQuery dal sito http://jquery.com. L'installazione è molto facile e veloce perché, a
differenza di altre complicate librerie, si
tratta di un unico file. Viene offerta una scelta di versioni meno recenti
e più recenti, tutte perfettamente funzionanti. Ognuna di tali librerie viene
resa disponibile in due versioni: quella minifilizzata,
da cui sono stati rimossi tutti gli spazi inutili e i ritorni a capo, rendendola
praticamente illeggibile ma molto compatta, e quella per lo sviluppo, dotata di
ampio commento, che occupa 247 Kb ed è costituita da più di 9400 righe di
codice. Sono inoltre disponibili i file migrate,
che, scaricati insieme alle librerie più recenti, risolvono tutti i problemi di
compatibilità con quelle meno recenti, evitando di dover riscrivere il codice
ad ogni aggiornamento.
Nel momento in cui scriviamo la versione
più recente è la 1.11.2, (contenuta nel file jquery-1.11.2.min.js) che viene fornita con un file di compatibilità (jquery-migrate-1.2.1.js).
Per poter utilizzare jQuery all'interno
della vostra pagina web è sufficiente inserire nell'<head> del documento i
seguenti due script:
<script
src="jquery-1.11.2.min.js"></script>
<script src="jquery-migrate-1.2.1.js"></script>
Un modo alternativo e ancora più facile
(senza bisogno di scaricare nulla) per includere la libreria jQuery nelle
proprie pagine HTML è quello di utilizzare una delle copie gestite dai diversi Content Delivery Network (CDN, network di distribuzione dei contenuti).
Un CDN è un sistema distribuito di grande estenzione, costituito da un numero
significativo di server ospitati presso più data center sulla Rete. Lo scopo di
un CDN è di fornire contenuto agli utenti finali in un contesto di alta
affidabilità e in modo performante. I CDN oggi rendono disponibili gran parte
dei contenuti della rete, come elementi grafici, script, file multimediali,
applicazioni o anche dati in streaming (come musica e video). Su internet esiste
un certo numero di CDN commerciali, utilizzati da grandi aziende per la
distribuzione di risorse critiche. jQuery è ospitato su diversi CDN, che
offrono accesso pubblico e gratuito alla libreria. Ecco tre script alternativi,
che fanno riferimento a tre CDN diversi, ciascuno dei quali può essere inserito
nel documento risparmiandovi persino la fatica di scaricare il file sul server
del vostro sito:
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script
src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.2.min.js"></script>
<script
src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
Convenienza di jQuery
rispetto a javascript puro
JQuery rende più robuste istruzioni come:
var target =
document.getElementById("targetDiv");
target.innerHTML
= "<p>Hello World</p>";
che non funzionano con diverse versioni di
explorer, sostituendole con:
$("#targetDiv").html("<p>Hello
World</p>");
che funziona con tutti i browser.
jQuery semplifica istruzioni verbose come:
var target =
document.getElementById( "targetDiv" );
var
newElement = document.createElement( "div" );
target.parentNode.insertBefore(
newElement, target.nextSibling );
sostituendole con istruzioni più semplici come:
$("#targetDiv").after($("<div></div>"));
Tanto per fare un esempio del grado di semplicità
che si può ottenere con jQuery, ecco qui due blocchi di codice Ajax, uno in
javascript puro, l'altro in jQuery, che fanno esattamente la medesima cosa (aprono in modo asincrono il file MyScript.php e mostrano il testo ricevuto entro il documento HTML)
codice
javascript
var
XMLHttpRequestObject = false;
if
(window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if
(window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function
getData()
{
if(XMLHttpRequestObject)
{
var obj =
document.getElementById("targetDiv");
XMLHttpRequestObject.open("GET",
"MyScript.php");
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
obj.innerHTML =
XMLHttpRequestObject.responseText;
}
}
XMLHttpRequestObject.send(null);
}
}
codice
jQuery
$.get("MyScript.php",function(Response)
{
document.getElementById("targetDiv")= Response;
},"text");
Alcune difficoltà e cautele
nell'uso di jQuery
Non
è assolutamente facile scoprire quale parte del vecchio codice sia
incompatibile con le nuove versioni di jQuery,
perché, duole dirlo, le indicazioni delle novità e delle incompatibilità sono a
dir poco lacunose e difficili da trovare. Lo scrivente si è trovato a dover
utilizzare un file di compatibilità accanto a una delle ultime versioni, che
altrimenti non funzionava, malgrado abbia tentato con tutti i mezzi di scoprire
quali erano le istruzioni da riscrivere:
<script
src="jquery-1.11.2.min.js"></script>
<script
src="jquery-migrate-1.2.1.js"></script>
Sebbene
venga unanimemente raccomandato di inserire il codice jQuery entro lo spazio di
esecuzione condizionale della funzione $(document).ready(), dato da:
$(document).ready(function(){...});
certe
routine non funzionano se poste in
tale spazio, mentre funzionano se poste al difuori.
Purtroppo, è impossibile sapere a priori quando è necessario mettere del codice
entro o fuori tale spazio condizionale.
Prendete ad esempio la seguente pagina
internet:
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script
language = "javascript">
$(document).ready(function(){
alert(document.getElementById("MyIframe").childNodes.length);
});
</script>
</head>
<body>
<iframe
id="MyIframe" style="position:absolute;left:30%;top:35%;"
src="http://www.w3schools.com"></iframe>
</body>
</html>
Sembrerebbe logico porre l'istruzione:
alert(document.getElementById("MyIframe").childNodes.length);
entro la funzione $(document).ready(),
per la ragione, raccomandata dal sito jQuery, che il codice potrebbe altrimenti
essere eseguito prima che tutti gli
elementi della pagina siano stati caricati, e quindi non potrebbe leggere entro
"MyIframe".
Ma in realtà accade esattamente il
contrario! Posto entro $(document).ready() l'istruzione non funziona, mentre se posta
all'esterno… funziona.
❍ Cos'è il DOM che viene
utilizzato da javascript?
Il DOM (Document Object Model) è un
modo di rappresentare un documento e i suoi elementi tramite
"oggetti" che possiedono attributi e proprietà di lettura/scrittura,
metodi e oggetti-figli (parent). il DOM è un’interfaccia, o meglio una API (Application
Programming Interface) ideata dal consorzio W3C, che permette di accedere
agli elementi di una pagina.
Chi ha già lavorato con Visual Basic for
Application Microsoft (VBA) conosce già il tipico codice per esprimere un
oggetto. Ecco un tipico oggetto VBA:
ActiveDocument.Range.Paragraphs(1)
è l'oggetto che si riferisce al primo
paragrafo di una selezione in un documento Word. I punti di separazione
introducono tipicamente una proprietà, un metodo o un oggetto-parent (figlio).
Ecco un tipico oggetto DOM javascript, che
consente di accedere al valore del rientro destro nel corpo del documento:
document.body.style.paddingLeft
Consideriamo il seguente tag HTML:
<a id="MyAnchor"
name="MyLink" href="MyFile.htm">Clicca qui per aprire il
file</a>
Ecco l'oggetto che permette di manipolare
il testo "Clicca qui per aprire il file" incluso nel tag:
document.getElementById("MyAnchor").innerHTML
Ecco l'oggetto che permette di accedere
agli attributi "name" e "href" contenuti nel tag:
document.getElementById("MyAnchor").attr("name").value
document.getElementById("MyAnchor").attr("href").value
Ecco il metodo che consente di scrivere
nell'oggetto document
document.write("Hello World")
❍ Acquisire e manipolare gli
elementi di una pagina tramite javascript e jQuery
In
javascript si chiamano "selettori" le espressioni che permettono di
ottenere un singolo elemento o un gruppo omogeneo di elementi del DOM.
Per selezionare tutti i tag <img>
con class="class1" oppure class="class2":
$("img.class1, img.class3")
Per selezionare tutti i paragrafi con tag
<p> all'interno dell'elemento con id="MyTag":
$(#MyTag p")
$(#MyTag).find(" p")
Per selezionare tutti i tag <input>
del documento:
$("input")
Per selezionare tutti i tag con
class="MyClass" del documento:
$(".MyClass")
Per selezionare i tag che hanno un certo
valore dell'attributo "name" (o qualsiasi altro attributo)
$("[name=MyTagName]")
Per selezionare tutti i tag con la
proprietà di stile "hidden":
$(":hidden")
Per selezionare tutti i tag hidden del tag
con id="MyTag":
$("#MyTag").find(":hidden")
Il metodo find() svolge una ricerca sui
nodi contenuti in quello considerato. Accetta gli stessi argomenti di $(…). Se
scriviamo .find("*") otteniamo tutti i discendenti di un elemento.
Consideriamo i seguenti elementi di una pagina
HTML:
<style type="text/css">
.MyBoxClass{
width : 200px;
height : 25px;
background-color : white;
font-family : "Times New Roman";
color : red;
font-size : 100%;
vertical-align : center;
text-align : center;
border : 1px solid black;
}
</style>
<a id="MyAnchor"
name="MyLink" href="MyFile.htm">Clicca qui per aprire il
file</a>
<table>
<tr>
<td id="MyBox"
class="MyBoxClass" title="Questo è il mio box">
QUESTO E' IL MIO BOX
</td>
</tr>
</table>
<p>
SCRIVI
NEL BOX SOTTOSTANTE </br>
<input
id="MyTextBox" type="text" >
</p>
<div id="MyDiv">
</div>
Ecco, di seguito, una serie di modi in cui
tali elementi possono essere manipolati.
Ottenere (javascript) il testo
"Clicca qui per aprire il file" incluso nel tag <a>:
document.getElementById("MyAnchor").innerHTML
$("#MyAnchor").text()
Cambiare (javascript) il testo
"Clicca qui per aprire il file" incluso nel tag <a>:
document.getElementById("MyAnchor").innerHTML
= "Questo è il nuovo contenuto del tag";
Far sparire e riapparire il tag <a>:
$('#MyAnchor').hide();
$('#MyAnchor').show();
$('#MyAnchor').attr("visibility","hidden");
$('#MyAnchor').attr("visibility","displayed");
L'istruzione "show" funziona
anche se il tag <a> è stato dichiarato come invisibile, con l'istruzione
di stile:
<a
style="display:none;">Clicca qui per aprire il file</a>
Questo codice ha una interessante
applicazione pratica: se si vuole creare un bottone che richiama routine
diverse in relazione a due situazioni diverse, invece di scrivere complicate
istruzioni condizionali si possono creare due
bottoni identici, e far apparire quello che richiama la routine adatta alla
circostanza, facendo sparire quello che richiama la routine non adatta alla
circostanza.
Modificare il colore del testo contenuto
nel tag <a>:
document.getElementById("MyAnchor").style.color
= "red";
Leggere (javascript) gli attributi
"name" e "href" contenuti nel tag <a>:
document.getElementById("MyAnchor").attr("name").value
document.getElementById("MyAnchor").attr("href").value
Leggere (jQuery) gli attributi
"name" e "href" contenuti nel tag:
$("#MyAnchor").attr("name")
$("#MyAnchor").attr("href")
Acquisire i dati presenti nel CSS di MyBox:
$("#MyBoxClass").css('height')
$(".MyBox").css('height')
(il risultato è "25px")
Modificare il contenuto del tag <a> con jQuery:
$("#MyAnchor").html("Questa
è la nuova stringa inserita nel tag");
Cambiare il valore dell'attributo title del box MyBox con jQuery:
$("#MyBox").attr("title",
"Questo è sempre il mio box");
Leggere il valore dell'attributo title:
$("#MyBox").attr('title')
Leggere l'eventuale valore di un campo
testo dell'oggetto (es. un box di informazioni):
$("#MyBox").text()
Cambiare l'impostazione di stile contenuta
nel foglio CSS abbinato all'elemento con id="MyTag":
$("#MyBox").css({width:30});
Cancellare tutte le ricorrenze della
stringa "px" nel campo che contiene il valore CSS dell'altezza del
Box con id="MyTag":
$("#MyBox").css('height').replace("px","");
Acquisire il contenuto di quanto è stato
scritto nel box di testo MyTextBox:
document.getElementById("MyTextBox").value
$("#MyTextBox").val()
$("MyTextBox").attr("value")
Acquisire la lunghezza della stringa che è
stata immessa in MyTextBox (ad es. per controllare se sia stato correttamente
digitato il numero di una carta di credito):
$('#MyInputBox').attr('value').length
Immettere del testo nel box MyTextBox
$('#MyTextBox').val("Hello
World");
Non solo è possibile, sia con javascript
che con jQuery, immettere nella pagina una semplice stringa di testo, ma anche
altri tag, come paragrafi, e persino tabelle, dotati delle caratteristiche di
stile desiderate.
Ecco ad esempio, come far comparire in
MyDiv un paragrafo con una riga di testo:
$('#MyDiv').html("<p
style='font-size:150%;color:blue;font-weight:bold;'>" +'ABRACADABRA'+"</p>");
oppure:
document.getElementById("MyDiv").innerHTML
= "<p style='font-size:150%;color:blue;font-weight:bold;'>" +'ABRACADABRA'+"</p>");
to be continued…
❍ Come si costruisce un oggetto
javascript
Un oggetto è una entità javascript che può
essere dotata di proprietà e metodi definiti dal programmatore, mediante la dot notation. Ad es. possiamo avere la
proprietà MioGatto.nome, o MioGatto.razza, il metodo MioGatto.apprezza().
Un primo modo di creare oggetti javascript
è di utilizzare il costruttore predefinito Object(), che crea oggetti vuoti, ovvero privi di proprietà e
metodi. Le proprietà degli oggetti costruiti con Object() devono essere definite successivamente alla
creazione.
Creiamo ad esempio un nuovo oggetto di
nome mioCell,
con 4 proprietà:
var mioCell =
new Object;
mioCell.marca
= "LG";
mioCell.colore
= "bianco";
mioCell.display
= 16000colori";
mioCell.mms =
"si";
mioCell.camera
= "si";
Un secondo modo di creare oggetti è
tramite un costruttore personalizzato:
function
Automobile(marca, modello, colore, cilindrata)
{
this.marca=marca;
this.modello=modello;
this.colore=colore;
this.cilindrata = cilindrata;
this.trazione;
this.carburante = 5;
}
Si notino le proprietà "trazione" e "carburante": il valore
di "trazione" verrà assegnato in seguito, all'istanza
dell'oggetto:
var punto =
new Automobile;
punto.trazione
= "integrale";
Alla proprietà "carburante" è assegnato
sin dall'inizio un valore di default
che può essere cambiato una volta creata una istanza dell'oggetto.
che
può essere scritta/letta ma non necessita di inizializzazione al momento della
creazione dell'oggetto. Si noti la proprietà "carburante", che viene
inizializzata dal codice dell'oggetto.
Disponendo del costruttore, si può creare
una istanza del tipo di oggetto
definito, che è quanto stiamo cercando:
var punto =
new Automobile("Fiat", "Punto", "rosso",
"1200");
Queste proprietà possono essere modificate
in modo molto semplice:
punto.colore
= "argento";
utilizzando la dot notation.
Una volta che si è istanziato un nuovo
oggetto Automobile, si possono aggiungere altre proprietà, che non sono
proprie della classe, ma solo di quell'oggetto:
punto.alimentazione
= "gasolio";
Per costruire un metodo si ricorre alla
definizione di una funzione. Sviluppando l'esempio della classe "Automobile", definiamo
:
function
Automobile(marca, modello, colore, cilindrata)
{
this.marca = marca;
this.modello = modello;
this.colore = colore;
this.cilindrata = cilindrata;
this.trazione;
this.carburante = 5;
this.rifornimento = function(litri)
{
if(this.carburante + litri * 1 >=50)
{
this.carburante=50;
}
else
{
this.carburante = this.carburante +
(litri*1);
}
operazione.value = this.carburante + "
Litri";
}
this.pieno = function()
{
this.carburante = 50;
operazione.value = 50 + " Litri";
}
this.viaggia = function(km)
{
if (this.carburante - (km/10) >=0)
{
this.carburante = this.carburante - km/10;
}
else
{
this. carburante = 0;
}
operazione.value = this.carburante +
"Litri";
}
}
Per vedere come funzionano i metodi,
creiamo un nuovo oggetto "punto" corrispondente alla classe "Automobile":
var punto =
new Automobile("Fiat", "Punto", "rosso", 1200);
Inoltre, inseriamo una textbox in cui
inserire il livello del serbatoio:
Litri
serbatoio: <input type="text" id="operazione"
size="3" value="5 Litri">
Il metodo Automobile.rifornimento
(evidenziato in rosso) viene richiamato dal bottone:
<input
type="button" value="Rifornisci"
onclick="punto.rifornimento(prompt('litri?',''))">
che fa apparire un prompt che chiede
quanti litri di rifornimento sono stati aggiunti al serbatoio, vi aggiunge la
quantità di carburante già presente nel serbatoio (che compare nel box di
testo), e fa apparire nel box di testo i litri totali immessi.
Il metodo Automobile.pieno (evidenziato in
viola) viene richiamato dal bottone:
<input
type="button" value="Rifornisci"
onclick="punto.rifornimento(prompt('litri?',''))">
che fa apparire un prompt che chiede
quanti litri di rifornimento sono stati aggiunti al serbatoio, vi aggiunge la
quantità di carburante già presente nel serbatoio (che compare nel box di
testo), e fa apparire nel box di testo i litri totali immessi.
<input
type="button" value="Fai il pieno"
onclick="punto.pieno()">
e si limita a visualizzare "50
Litri" nel box di testo.
Il metodo Automobile.viaggia (evidenziato
in verde) viene richiamato dal bottone:
<input
type="button" value="Viaggia"
onclick="punto.viaggia(prompt('Km percorsi',''))">
fa apparire un prompt che richiede il
numero di kilometri percorsi e sottrae ai litri del serbatoio (nel box di
testo) quelli consumati in relazione ai kilometri percorsi.
Un oggetto può essere definito e
instanziato contestualmente tramite un codice come il seguente:
trapezio =
{
BaseMinore : 10;
BaseMaggiore : 20;
Altezza : 15;
area : function()
{
return (this.BaseMinore + this.BaseMaggiore)
* this.Altezza / 2;
}
}
La proprietà "prototype" di un
oggetto è un modo per riferirsi globalmente alle proprietà e ai metodi di
quell'oggetto. Per capire a cosa serva la proprietà "prototype", creiamo
due oggetti (costruttori). Creiamo dapprima l'oggetto "EssereVivente":
EssereVivente
= function()
{
this.nome="";
this.cosaMangia="";
this.setCosaMangia = function(cibo)
{
this.cosaMangia=cibo;
}
}
Creiamo poi l'oggetto
"Mammifero":
Mammifero =
function()
{
this.razza="";
this.dataNascita="";
}
Come fare per far ereditare tutte le
proprietà e i metodi di "EssereVivente" a "Mammifero"? Semplice: facendo riferimento al "prototype" di "Mammifero" e
inserendovi le proprietà e i metodi di "EssereVivente":
Mammifero.prototype
= new EssereVivente;
In tal modo ogni istanza dell'oggetto
"Mammifero" erediterà anche le proprietà di "EssereVivente".
Se si vuole inserire una singola proprietà
o metodo ad un oggetto si deve prima crearla:
function
DisplayRazza()
{
alert("La razza di questo animale è:
" + this.razza);
}
Successivamente si inserisce il metodo
DisplayRazza nell'oggetto "Mammifero":
Mammifero.prototype.DisplayRazza
= DisplayRazza;
In questo modo tutte le istanze
dell'oggetto mammifero create
successivamente alla inclusione di questo metodo, avranno la possibilità di
utilizzarlo, ma non quelle create
anteriormente.
Osservate questa pagina web:
essa corrisponde al seguente codice:
<html>
<head>
<style>
#myDIV {
border:1px solid black;
height: 250px;
width: 250px;
overflow: auto;
position:absolute;
top:20%;
left:35%;
}
#content {
height: 800px;
width: 2000px;
background-color: HoneyDew;
}
</style>
</head>
<body>
<div
id="myDIV">
<div id="content">
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
Il contenuto dell'elemento interno eccede
quello dell'elemento esterno</br>
</div>
</div>
</body>
</html>
La riga di codice responsabile
dell'effetto scrolling è evidenziata in colore rosso scuro (vedi):
overflow:
auto;
La proprietà overflow può avere diversi
valori, i più utili dei quali sono:
overflow:
visible|hidden|scroll|auto;
overflow
: visible
avrebbe fatto "fuoriuscire" il contenuto dell'elemento interno dai
limiti dell'elemento esterno, invadendo la pagina. Questo è il valore di
default. Per impedire questo, normalmente si setta il margine dell'elemento
esterno come auto, in modo che si
adatti all'elemento interno.
overflow
: hidden taglia semplicemente il
contenuto eccedente le dimensioni dell'elemento esterno, rendendolo invisibile
e irraggiungibile (non c'è scrolling)
overflow
: scroll taglia il contenuto
eccedente le dimensioni dell'elemento esterno, ma lo rende accessibile dotando
quest'ultimo di barre per lo scrolling verticale e orizzontale.
overflow
: auto se il contenuto eccede
le dimensioni dell'elemento esterno, fa apparire delle barre per lo scrolling.
Rispetto all'opzione overflow : scroll,
è più conveniente, perché, mentre in quel caso le barre appaiono sempre, anche se il contenuto è compreso
nei limiti dell'elemento, con overflow :
auto esse compaiono solo se il contenuto eccede le dimensioni assegnate.
❍ La
proprietà documentElement
Quando si dispone di un documento
strutturato mediante tag, come una pagina web:
<html>
<head>
… </head>
<body>
… </body>
</html>
oppure come un documento xml:
<catalogo>
<scheda>
<autore>
… </autore>
<titolo>
… </titolo>
<editore>
… </editore>
<scheda>
<scheda>
<autore>
… </autore>
<titolo>
… </titolo>
<editore>
… </editore>
<scheda>
</catalogo>
E' possibile leggerne il contenuto tramite
apposite istruzioni, che fanno riferimento ai nodi del documento. Un nodo è un tag o il contenuto (testo o
immagine) di un tag. Per poter fare questo occorre acquisirlo come documento
strutturato con una istruzione del tipo:
var
mydocument = document.documentElement
(caso di un file con il codice di una
pagina web)
oppure con una istruzione del tipo:
xmlDoc=loadXMLDoc("books.xml");
mydocument=xmlDoc.documentElement;
(caso di un file xml)
Proviamo ad esempio ad acquisire la
seguente pagina html come documento strutturato in nodi:
<html>
<head>
</head>
<body>
<div
id="MyDiv">
Questo è il testo contenuto nel tag div
</div>
<table
id="MyTable">
<tr>
<td>
Questo è il testo contenuto nel tag td
</td>
</tr>
</table>
</body>
</html>
Con la proprietà .documentElement si acquisisce il nodo principale, che racchiude gli
altri nodi. Ecco il codice per leggere il testo contenuto nel tag <div> e
farlo apparire entro un alert box:
alert(document.documentElement.getElementsByTagName("div")[0].firstChild.nodeValue);
Ecco il codice per leggere il testo
contenuto nel tag <td> della tabella e farlo apparire entro un alert box:
alert(document.documentElement.getElementsByTagName("div")[0].firstChild.nodeValue);
L'output che otteniamo in questo secondo
caso nella pagina web è:
Con apposite istruzioni possiamo navigare
attraverso i nodi per acquisirne il valore. Ecco ad esempio il codice per
acquisire il nome del tag <head> del documento html e farlo apparire in
un alert box:
alert(document.documentElement.firstChild.nodeName);
L'output che otteniamo è il seguente:
Riguardo il nodo si possono ottenere tra
le altre le proprietà .nodeName, nodeValue e nodeType, su cui ci soffermeremo in seguito
❍ Subordinare l'apertura di un
link al valore vero/falso di una funzione javascript
Osservate il codice seguente:
<html>
<head>
<script text="javascript">
function Controllo(){
return true;
}
</script>
</head>
<body>
<a href="MyFile.htm"
onclick="return Controllo();">Clicca qui per aprire il
file</a>
</body>
</html>
Il file MyFile.htm, a cui fa riferimento il link <a>…</a> si aprirà solo se la funzione "Controllo()" restituisce "true" (come in questo caso), mentre se restituisce
"false" il link rimarrà inattivo.
Aprite il documento MouseTracking.htm
e visualizzate il codice con l'opzione "visualizza sorgente pagina"
del tasto destro del mouse (per Explorer l'opzione è "HTML").
Al passare del mouse su uno dei box una
funzione jQuery visualizza le informazioni di posizione del mouse:
$('.MyBox').mousemove
(
function(event)
{
log2("Window Height :
"+window.innerHeight+
"</br>Top Box :
"+Math.floor($(this).offset().top)+
"</br>Left Box :
"+Math.floor($(this).offset().left)+
"</br>Box Height :
"+$(this).css('top')+
"</br>Box Width :
"+$(this).css('top')+
"</br>Window Width :
"+window.innerWidth+
"</br>Absolute Mouse X :
"+event.pageX+
"</br>Absolute Mouse Y :
"+event.pageY+
"</br>Window Mouse X :
"+event.pageX+
"</br>Window Mouse Y :
"+(event.pageY-document.VerticalScrollValue));
}
);
Window Width è la larghezza utile
(innerWidth) della finestra in punti
Window Height è l'altezza utile
(innerHeight) della finestra in punti
(provate ad aumentare l'ingrandimento
della finestra con CTRL+rotella del mouse e noterete che Window Width si riduce quando l'ingrandimento aumenta, e così pure capita a Window
Height)
Top Box è la distanza in punti del margine superiore del box
dall'inizio del documento (non della finestra)
Left Box è la distanza in punti del margine sinistro del box
dal lato sinistro del documento (non della finestra)
Box Height è l'altezza del box in punti, letta nel foglio CSS
Box Width è la larghezza del box in punti, letta nel foglio CSS
Absolute Mouse X è la distanza in punti del mouse rispetto al lato
sinistro del documento (non della finestra)
Absolute Mouse Y è la distanza in punti del mouse rispetto al lato
superiore del documento (non della finestra)
Window Mouse X è la distanza in punti del mouse rispetto al lato
sinistro della finestra, cioè tenendo
conto dello scrolling
Window Mouse Y è la distanza in punti del mouse rispetto al lato
superiore della finestra, cioè
tenendo conto dello scrolling
Un'altra funzione jQuery fa apparire
invece, in un'altra finestra, i dati dello scrolling verticale e orizzintale in
punti, che sono indispensabili per ottenere la posizione del mouse relativa
alla finestra, e non al documento:
$(window).scroll(function(event)
{
log1("Scrolling verticale:
"+$(window).scrollTop()+"</br>Scrolling orizzontale :
"+$(window).scrollLeft());
document.VerticalScrollValue=$(window).scrollTop();
document.HorizontalScrollValue=$(window).scrollLeft();
});
Chi ha esperienza di javascript non
mancherà di notare la maggiore facilità di acquisizione dei dati con jQuery,
che permette persino di accedere alle misure di larghezza e altezza del box.
❍ Acquisire la posizione di un
elemento entro il documento
Consideriamo la seguente rappresentazione
di un box come visualizzato in una pagina web:
Questo box corrisponde al seguente codice:
html:
<div id="container">
</div>
css:
#container {
padding:
24px;
margin:
24px;
border:
50px #ccc solid;
left:
10px;
top:
200px;
position:
absolute;
}
I valori padding, margin, border, left,
top influiscono tutti sulla posizione che il contenuto del box ha nella pagina:
ad esempio, aumentando il padding o il margine, una eventuale linea di testo
scenderà più in basso nella pagina.
Un elemento immagine invece avrà una
struttura più semplice:
La nostra immagine è situata nel suo
contenitore e non ha valori definiti per padding, margin o border.
Consideriamo ora una pagina web che mostra
elementi annidati:
I bordi rossi sono quelli di una tabella,
mentre i bordi neri sono quelli di una cella della tabella. Abbiamo tre tabelle
annidate che contengono altrettante celle.
Questa visualizzazione corrisponde al
codice seguente:
<table align="center" style="border:1px solid
red;width:auto;height:auto;padding:20px;">
<tr>
<td style="border:1px solid
black;width:300px;height:200px;padding:20px;">
<table align="center"
style="border:1px solid red;width:auto;height:auto;padding:20px;">
<tr>
<td style="border:1px
solid black;width:300px;height:200px;padding:20px;">
<table
align="center" style="border:1px solid
red;width:auto;height:auto;padding:20px;">
<tr>
<td id="MyBox" style="border:1px
solid black;width:300px;height:200px;text-align:center;font-size:120%;font-weight:bold;">
MyBox
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
Come si può acquisire la posizione della
cella MyBox all'interno del
documento? Ecco un codice che lavora risalendo dall'elemento interno a quelli
più esterni, sommando via via le posizioni all'interno dell'oggetto contenitore
(parent):
function getPosition(element)
{
var xPosition = 0;
var yPosition = 0;
while(element)
{
xPosition += (element.offsetLeft -
element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop -
element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition
};
}
L'argomento della funzione è un elemento
della pagina; nel nostro esempio essa è richiamata dall'istruzione:
function getPosition(document.getElementById("MyBox"));
Il loop while inizia con l'elemento designato, ed aggiunge a xPosition e yPosition i valori che andiamo a commentare:
Le proprietà offsetLeft e offsetTop
restituiscono la posizione a sinistra e dall'alto relativa
all'elemento-genitore più prossimo, cioè la distanza dell'angolo superiore
sinistro dell'elemento considerato rispetto all'angolo superiore sinistro
dell'elemento-genitore. Normalmente è il valore di padding che fa sì che questi due angoli non coincidano, facendo
rientrare l'elemento-figlio.
Le proprietà clientLeft e clientTop
tengono conto dello spessore rispettivamente del bordo sinistro e del bordo
superiore dell'elemento (che sono quelli rilevanti per il posizionamento)
Le proprietà scrollLeft e scrollTop riguardano
il contenuto di ogni elemento, e misurano lo scrolling interno di tale contenuto. Questa è la ragione per cui i relativi
valori vengono sottratti, piuttosto
che addizionati.
Un altro modo, più veloce, di ottenere lo
stesso risultato, è quello di utilizzare il metodo getBoundingClientRect(), che è supportato attualmente da tutti i
browser.
Il metodo viene applicato ad un elemento,
ad esempio con l'istruzione:
document.getElementById("MyBox").getBoundingClientRect()
Per capire l'oggetto che si ottiene,
occorre premettere che, secondo le specifiche CSS, qualsiasi contenuto della
pagina web è racchiuso in un rettangolo chiamato "CSS box". Nel caso
di un block-element come <div>
è l'elemento stesso che forma un simile rettangolo, chiamato block box. Nel caso di un inline element, ogni ritorno a capo
genera un box: ogni linea è un rettangolo e questi rettangolo sono chiamati anonymous boxes. In tal modo il
contenuto di un elemento può consistere di un unico rettangolo o di rettangoli
multipli, che è possibile richiamare con il metodo element.getClientRects(). Il metodo element.getBoundingClientRect() restituisce il minimo rettangolo
che racchiude tutti i rettangoli che sono in element.getClientRects().
La funzione che consente di ottenere la
posizione dell'elemento per questa via si presenta nel modo seguente:
function getOffsetRect(elem)
{
// (1)
var
box = elem.getBoundingClientRect();
var
body = document.body;
var
docElem = document.documentElement;
// (2)
var
scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
var
scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
// (3)
var
clientTop = docElem.clientTop || body.clientTop || 0;
var
clientLeft = docElem.clientLeft || body.clientLeft || 0;
// (4)
var
top = box.top + scrollTop - clientTop;
var
left = box.left + scrollLeft - clientLeft;
return
{ top: Math.round(top), left: Math.round(left) };
}
Si notino le istruzioni condizionali come:
var scrollTop = window.pageYOffset ||
docElem.scrollTop || body.scrollTop;
Il significato delle due sbarre verticali
"||" è simile a quello logico "or", in quanto acquisisce il
primo elemento non nullo dell'insieme. Così, una istruzione come:
alert(""
|| "paperino" || "pluto");
restituirà "paperino", mentre l'istruzione:
alert("pippo"
|| "paperino" || "pluto");
restituirà "pippo".
Consideriamo ora il documento web prodotto
dal seguente codice:
<html>
<head>
</head>
<body>
<p id="MyParagraph"
align="center" style="border:1px solid black;">
Questo è il mio paragrafo
</p>
</body>
</html>
Con la proprietà offset() di jQuery possiamo ottenere la posizione del box che
racchiude l'elemento relativa al documento:
$("#MyParagraph").offset().top
Si può vedere come la proprietà offset() ha due valori: offset().top e offset().left, che determinano la posizione del box.
Questa istruzione fornisce il valore
"8", e non "0", come ci si sarebbe aspettato per il primo
elemento della pagina, perché il browser normalmente pone una piccola distanza
tra l'elemento e il margine superiore della finestra.
Il metodo offset() può essere utilizzato sia in lettura che scrittura, cioè
per settare le coordinate. Ad esempio l'istruzione:
$("#MyParagraph").offset({top: 200,left:200});
sposta l'elemento alle coordinate 200,
200.
Gli stessi risultati si possono ottenere
con position():
$("#MyParagraph").position().top
La differenza tra i metodi position() e offset() di jQuery sta nel modo con cui vengono calcolate le
coordinate restituite. Nel primo caso, le coordinate vengono calcolate sempre
rispetto al genitore dell’elemento, mentre nel secondo caso tali coordinate
possono essere calcolate rispetto all’offset dell’elemento genitore rispetto
alla pagina quando il genitore è posizionato, ossia ha un valore CSS diverso
da static. Se il genitore non è posizionato, entrambi i metodi
restituiscono gli stessi valori.
Un'altra utile proprietà è offsetParent. Consideriamo il seguente elemento:
<div id="MyDiv" style="position:absolute;top:200px;left:100px;">
<p
id="MyParagraph" class="paragraph"
align="center">
Questo
è il mio paragrafo
</p>
</div>
Consideriamo la seguente istruzione:
alert($(document.getElementById("MyParagraph").offsetParent).offset().top);
Il valore che sarà mostrato nel box di
dialogo è 200, perché l'elemento parent di MyParagraph è il <div> che lo
contiene, e che ha un posizionamento assoluto dato dai valori:
top : 200px
left : 100px.
Un'altra proprietà utile per calcolare la
posizione di un elemento è .clientTop,
che indica lo spessore del bordo superiore dell'elemento, in pixel (per il
bordo sinistro si utilizza .clientLeft).
Considerando l'elemento:
<div id="MyDiv" style="border:10px">
<p
id="MyParagraph" class="paragraph"
align="center">
Questo
è il mio paragrafo
</p>
</div>
l'istruzione:
alert(document.getElementById("MyParagraph").offsetParent.clientTop);
dà come valore "10", che
corrisponde al valore dato alla proprietà border-top di MyDiv.
Come si vede questa istruzione non appartiene a jQuery, ma a javascript, quindi
non funziona se associata ad un identificatore jQuery:
alert($("#MyParagraph").offsetParent.clientTop);
Tuttavia clientTop non tiene
conto degli effetti della proprietà padding, né della proprietà margin. Al suo posto si può usare la proprietà .style.borderTopWidth.
❍ Fare lo scrolling
fino a portare un elemento della pagina in vista
Consideriamo la seguente pagina web Scrolling.htm
:
<html>
<head>
<script
type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script
type="text/javascript">
$(document).ready(function(){
$("#MyButton").offset({top: 200,
left: 600});
$("html,body").scrollTop(0);
});
function
MyFunction()
{
var offset =
$("#MyButton").offset();
offset.top = offset.top - 50;
$("html,body").scrollTop(offset.top);
}
</script>
</head>
<body>
<div
style="height:1000px;"></div>
<p
align=center>
<input
id = "MyButton" type="button" value="INVIO"
onclick="MyFunction();">
</p>
<div
style="height:1000px;"></div>
</body>
</html>
Le istruzioni javascript utilizzano la
proprietà .scrollTop() associata ad
un qualsiasi elemento, che permette di leggerne o settarne lo scrolling interno. Quest'ultimo rilievo vuol dire
che non riusciremo a muovere in alto di 50 pixels il bottone con l'istruzione:
$("#MyButton").scrollTop(50);
bensì con l'istruzione:
$("html,body").scrollTop(50);
perché lo scrolling si riferisce ad un
eventuale contenuto dell'elemento, e
quindi l'elemento a cui dobbiamo associare l'istruzione non è il tag del
bottone ma il tag <body>, all'interno del quale si trova il bottone.
Nel documento appare un bottone:
<input
id = "MyButton" type="button" value="INVIO"
onclick="MyFunction();">
che viene posizionato 200 punti in basso a
partire dall'inizio del documento e 600 punti a destra a partire dal lato
sinistro del documento:
$("#MyButton").offset({top:
200, left: 600});
L'evento onclick del tag MyButton richiama
una funzione:
onclick = "MyFunction();"
La funzione MyFunction acquisisce la
posizione verticale del bottone mediante :
var
offset = $("#MyButton").offset();
Se noi facessimo lo scrolling in basso
pari a tale valore (cioè 200 punti), il bottone salirebbe fino a sparire dalla
vista.
Poiché vogliamo che dopo lo scrolling il
bottone sia posizionato 50 punti più in basso dell'inizio della finestra,
occorre fare lo scrolling di un valore pari alla posizione dell'elemento meno
50 punti:
offset.top
= offset.top - 50;
Ora, facendo lo scrolling del documento,
il bottone verrà posizionato esattamente 50 punti in basso a partire
dall'inizio della finestra.
Cos'è una "tooltip"? E' un box informativo
che compare quando il mouse passa sopra un elemento della pagina, che potrebbe
essere un link, un tag <td> di una tabella o un altro tag (jQuery
permette di dotare di tooltip un tag qualsiasi).
La soluzione che proponiamo qui è dovuto ad Alessio
Atzeni, e si può trovare sul suo sito www.alessioatzeni.com.
attenzione: Se dopo aver dotato la vostra pagina di tooltips
voleste automatizzare le operazioni di inserzione delle informazioni nel campo
"title", scrivendole in un documento XML e inserendole nel tag al
momento del caricamento della pagina, consultate in questo documento l'articolo
"Inserire nel campo 'title' dei vostri link le informazioni visualizzate
dal browser al passaggio del mouse utilizzando XML, javascript e php"
Per creare le tooltips vengono utilizzati i seguenti
linguaggi o funzionalità: html, css, javascript, jQuery.
Noi abbiamo apportato diversi miglioramenti al codice,
di cui diamo un sintetico elenco (ciascuno sarà spiegato in dettaglio più
avanti):
● Alcune
istruzioni sono state sostituite da altre più comprensibili per i principianti
e il codice è stato lievemente modificato e indentato in modo da renderlo più
leggibile.
● E' stata
aggiunta una condizione che fa apparire la ToolTip solo per i box con campo
"title" non vuoto (il codice di Atzeni faceva comparire un
antiestetico box vuoto)
● Il
codice funziona con elementi appartenenti a classi diverse, non solo con con
elementi di una sola classe.
● L'inserzione
del testo nei tooltip è stata razionalizzata tramite caricamento da un file xml
(questa funzionalità non sarà implementata in questo articolo, ma sarà oggetto
di una trattazione indipendente)
● La
ToolTip si autoconfigura in relazione al contenuto, in modo da avere una
larghezza doppia dell'altezza
● Il testo
della ToolTip è stato formattato in modo più elegante, con giustificazione dei
margini
● La
posizione della ToolTip si modifica rispetto a quella di default (in basso e a
destra rispetto al box) ogni volta che, data la posizione del box, rischia di
uscire dallo schermo.
Per vedere il codice javascript, aprite il file PaginaConTooltip.htm
dal sito learningsources e fate visualizzare al browser il sorgente nel
seguente modo:
Con Chrome, tasto destro del mouse,
opzione "visualizza sorgente pagina"
Con Mozilla, tasto destro del mouse,
opzione "visualizza sorgente pagina"
Con Explorer, tasto destro del mouse,
opzione "HTML"
Esponiamo in breve la struttura del codice che
consente di creare tooltips. Il file PaginaConTooltip.htm visualizza dei box costituiti da celle di tabella
generate dal seguente codice:
<td
class="MyBox" title="Questo è un box di
informazioni"> </td>
Come si vede ogni tag <td> ha al suo interno
l'attributo "title",
in cui viene inserito il testo da visualizzare nella tooltip. Quando il mouse
passa sul box, si attiva una routine jQuery collegata all'evento mouseover, che genera e fa
apparire la tooltip InfoBox, che non è altro che un semplice paragrafo di testo
formattato con il foglio di stile .tooltip, che ne definisce il bordo, il colore di background,
la giustificazione e il font del testo, setta il posizionamento come assoluto (position : absolute)
e la non-visibilità (display : none):
InfoBox =$("<p
class='tooltip'></p>");
Subito dopo viene posto all'interno della tooltip InfoBox il testo che è
contenuto nell'attributo "title" del box:
InfoBox.text(title)
La tooltip InfoBox viene poi inserita nel documento con l'istruzione .appendTo() e fatta
apparire con fadeIn(), e posizionata in modo assoluto a sinistra e in
basso rispetto alla posizione corrente del mouse, tramite il seguente codice:
$('.tooltip').offset({top:
mousey,left: mousex});
dove mousex e mousey definiscono lo scostamento orizzontale e lo
scostamento verticale del margine superiore sinistro di InfoBox rispetto alla
posizione del mouse.
Dopo questi brevi cenni introduttivi, passiamo ad
analizzare nel dettaglio il codice di PaginaConTooltip.
Si noti anzitutto, nella sezione <head>, il richiamo alle
libreria jQuery, indispensabile per scrivere un codice compatto ed efficiente:
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
In questo caso, per evitare di dover scaricare sul
proprio computer il file jquery-1.11.2.min.js, si è utilizzato un CDN (Content Delivery Network), cioè si è fatto riferimento, nel link, a
una copia della libreria ospitata su server che la mettono a disposizione
gratuitamente degli utenti di internet (in questo caso si tratta dei server
Google):
Diamo un'occhiata al codice che genera i box: si
tratta di tre fogli CSS posti nella sezione <head> e di una tabella posta nella sezione <body>.
I fogli CSS definiscono tre classi: una per i box veri
e propri (classe .MyBox), una per gli interstizi verticali tra i box (classe .hspacing) e una per gli
interstizi orizzontali tra i box (classe .vspacing):
<style
type ="text/css">
.MyBox{
border:1px solid black;
width:200px;
height:50px;
background-color:ivory;
}
.hspacing{
width:auto;
}
.vspacing{
height:40px;
}
</style>
Qui sotto è riportato il codice che genera una delle numerose
righe della tabella. Questo codice viene ripetuto identicamente, in modo da
generare tutte le linee orizzontali ciascuna composta da 4 box affiancati:
<table
align="center" style="width:140%">
<tr>
<td
class="MyBox"
title="Questo è un box di informazioni.
Questo è un box di informazioni. Questo è un box di informazioni. Questo è un
box di informazioni. Questo è un box di informazioni.";
align="left">
</td>
<td
class="hspacing"></td>
<td
class="MyBox"
title="Questo è un box di informazioni.
Questo è un box di informazioni. Questo è un box di informazioni. Questo è un
box di informazioni. Questo è un box di informazioni.";
align="center">
</td>
<td
class="hspacing"></td>
<td
class="MyBox"
title="Questo è un box di informazioni.
Questo è un box di informazioni. Questo è un box di informazioni. Questo è un
box di informazioni. Questo è un box di informazioni.";
align="right">
</td>
<td
class="hspacing"></td>
<td
class="MyBox"
title="Questo è un box di informazioni.
Questo è un box di informazioni. Questo è un box di informazioni. Questo è un
box di informazioni. Questo è un box di informazioni.";
align="center">
</td>
</tr>
<tr><td
class="vspacing"></td></tr>
..................................................................
</table>
Il tag <td> che corrisponde al box vero e proprio contiene nel
campo title il testo che verrà visualizzato nella Tooltip:
title = "Questo è un box di
informazioni. Questo è un box di informazioni. Questo è un box di informazioni.
Questo è un box di informazioni. Questo è un box di informazioni."
Ciascuno, ovviamente, inserirà il proprio testo al
posto di quello mostrato.
Il foglio di stile CSS della Tooltip è il seguente:
.tooltip {
display:none;
position:absolute;
word-wrap: normal;
width:8cm;
height:auto;
border:2px solid red;
background-color:papayawhip;
border-radius:5px;
padding:10px;
padding-top:4px;
padding-bottom:5px;
color:black;
font-size:14px
font-family: "Times New Roman";
font-weight:normal;
text-align:justify;
text-justify:inter-word;
}
La tooltip non appare finché non si verifica l'evento
del passaggio del mouse su uno dei box, e quindi viene dichiarata invisibile:
display:none;
Il testo al suo interno viene giustificato con le due
istruzioni:
text-align:justify;
text-justify:inter-word;
Poiché la tooltip deve essere spostabile in qualsiasi
parte della finestra, la sua posizione viene dichiarata assoluta:
position:absolute;
Le posizioni top e left che sono associate ad una posizione assoluta non
vengono precisate: lo saranno al momento del verificarsi del passaggio del
mouse su un box. A differenza del valore fixed, il valore absolute di position fissa la posizione del box rispetto al documento e
non alla finestra, e quindi il box si muove (teoricamente) con lo scrolling,
mentre nel caso di posizione fixed lo scrolling non modifica la sua posizione nella
finestra.
La prima istruzione che compare nello script che si
occupa di gestire le tooltip è la seguente:
$(document).ready(function()
{
.........
.........
.........
});
Si tratta di una tipica istruzione jQuery: tutto il
codice jQuery viene normalmente eseguito solo dopo che il codice HTML per la
visualizzazione della pagina sia stato eseguito; in altre parole solo dopo che
tutti gli elementi del documento siano stati mostrati nella pagina, per
impedire il malfunzionamento delle istruzioni che li manipolano.
Passiamo ora alla descrizione delle routine che
gestiscono gli eventi relativi al mouse.
Quando il mouse passa su un box si attiva una funzione
collegata all'evento mouseover:
$('.MyBox,.MyAnchor').mouseover
(
function(event)
{
var title = $(this).attr('title');
if(title != null && title.length
> 0)
{
$(this).data('tipText', title);
$(this).removeAttr('title');
var InfoBox=$("<p class='tooltip'></p>");
InfoBox
.text(title)
.appendTo($(this))
.fadeIn('fast');
InfoBoxWidth=InfoBox.css('width').replace("px","");
InfoBoxHeight=InfoBox.css('height').replace("px","");
while(InfoBoxWidth <
(InfoBoxHeight*(200/100)))
{
InfoBoxWidth=InfoBoxWidth*(105/100);
InfoBox.css({width:InfoBoxWidth});
InfoBoxHeight=InfoBox.css('height').replace("px","");
InfoBoxWidth=InfoBox.css('width').replace("px","");
}
document.InfoBoxWidth=InfoBoxWidth;
document.InfoBoxHeight=InfoBoxHeight;
InfoBoxOffsetX = 30;
InfoBoxOffsetY = 40;
RelativeToWindowMouseX=event.pageX-document.HorizontalScrollValue;
RelativeToWindowMouseY=event.pageY-document.VerticalScrollValue;
if(RelativeToWindowMouseY+InfoBoxOffsetY+5
> document.WindowHeight -
document.InfoBoxHeight){InfoBoxOffsetY=-(InfoBoxOffsetY)-document.InfoBoxHeight;}
if(RelativeToWindowMouseX+InfoBoxOffsetX+5
> document.WindowWidth -
InfoBoxWidth){InfoBoxOffsetX=-(InfoBoxOffsetX)-InfoBoxWidth;}
mousex=event.pageX+InfoBoxOffsetX;
mousey=event.pageY+InfoBoxOffsetY;
$('.tooltip').offset({top: mousey,left:
mousex});
}
}
);
Il codice jQuery per l'attivazione di una funzione al
verificarsi di un evento ha la seguente struttura:
$('.MyBox').mouseover
(
function(event)
{
........
........
........
}
)
dove $('.MyBox').mouseover rappresenta l'evento del passaggio del mouse su un
elemento di classe "MyBox" e function(event){...} contiene le istruzioni che devono essere eseguite.
Si noti l'uso dell'oggetto "this", che in
jQuery può rappresentare cose diverse in contesti diversi, ma qui rappresenta
il box a cui si ricollega l'evento (passaggio del mouse). Perciò l'istruzione:
var title =
$(this).attr('title');
legge la stringa che costituisce il
valore dell'attributo "title" del box
in cui si è verificato l'evento.
Se nel codice del box non è stato inserito un
attributo "title":
<td
class="MyBox"> </td>
ovvero se l'attributo consiste di una stringa vuota
perché non è stato riempito:
<td
class="MyBox" title=""> </td>
allora la funzione non esegue alcuna istruzione.
Questa condizione è espressa da:
if(title != null && title.length >
0){...}
dove le eventuali istruzioni vanno a posto dei
puntini. Senza questa istruzione, quando il mouse passa su un box con title=""
verrebbe visualizzata una antiestetica tooltip vuota.
La prima istruzione inserisce l'attributo 'tipText' e gli dà come
valore la stringa contenuta nell'attributo titolo:
$(this).data('tipText', title);
il metodo data(NomeElemento, dati) di jQuery collega dei
dati ad un qualsiasi elemento DOM, che possono essere letti con una istruzione
del tipo:
$(this).data('tipText');
Dopo che il valore dell'attributo "title" è stato
salvato in "tipText", viene rimosso l'attributo "title":
$(this).removeAttr('title');
Questo per evitare che, subito dopo che è apparsa la
tooltip, compaia anche il piccolo box che Explorer associa all'eventuale
presenza di un attributo "title".
Viene quindi creata la variabile InfoBox,
che rappresenta un paragrafo di classe .tooltip,
che è il nostro box informativo, che faremo apparire al momento giusto:
var
InfoBox=$("<p class='tooltip'></p>");
Il testo che era contenuto nell'attributo "title" e che ora è
nella variabile "title" viene scritto in InfoBox:
InfoBox.text(title)
Il box InfoBox viene posizionato al disotto del box rappresentato
dall'oggetto "this" (vale a dire dove sarebbe posizionato se il suo
codice fosse posto sotto il codice del box rappresentato dalla variabile "this"):
InfoBox.appendTo($(this))
Il box InfoBox viene reso visibile:
InfoBox.fadeIn('fast');
Vengono acquisite la larghezza e l'altezza del box:
InfoBoxWidth=InfoBox.css('width').replace("px","");
InfoBoxHeight=InfoBox.css('height').replace("px","");
Attraverso un ciclo while vengono modificate larghezza e altezza di InfoBox in modo che la
larghezza abbia misura doppia dell'altezza:
while(InfoBoxWidth
< (InfoBoxHeight*(200/100)))
{
InfoBoxWidth=InfoBoxWidth*(105/100);
InfoBox.css({width:InfoBoxWidth});
InfoBoxHeight=InfoBox.css('height').replace("px","");
InfoBoxWidth=InfoBox.css('width').replace("px","");
}
document.InfoBoxWidth=InfoBoxWidth;
document.InfoBoxHeight=InfoBoxHeight;
Vengono settati i valori dello spostamento di InfoBox rispetto alla posizione
del mouse:
InfoBoxOffsetX
= 30;
InfoBoxOffsetY
= 40;
Vengono acquisiti i valori dello scrolling verticale e
dello scrolling orizzontale, cioè della distanza in pixel tra l'inizio del
documento e il punto del documento che corrisponde al margine superiore della
finestra (scrolling verticale) e la distanza in pixel tra il margine sinistro
del documento e il punto della riga in cui inizia la visualizzazione della
finestra (scrolling orizzontale):
RelativeToWindowMouseX=event.pageX-document.HorizontalScrollValue;
RelativeToWindowMouseY=event.pageY-document.VerticalScrollValue;
Viene controllato se la linea inferiore di InfoBox è
all'interno della finestra:
if(RelativeToWindowMouseY+InfoBoxOffsetY+5
> document.WindowHeight - document.InfoBoxHeight)
{
InfoBoxOffsetY=-(InfoBoxOffsetY)-document.InfoBoxHeight;
}
La posizione verticale della linea inferiore di
InfoBox rispetto al lato superiore della finestra è data dalla somma della
posizione del mouse rispetto all'angolo superiore della finestra (RelativeToWindowMouseY)
più la distanza verticale dell'angolo superiore sinistro di InfoBox rispetto al mouse
(InfoBoxOffsetY)
più l'altezza di InfoBox (document.InfoBoxHeight). Se questo valore è superiore all'altezza della
finestra (document.WindowHeight):
RelativeToWindowMouseY
+ InfoBoxOffsetY + document.InfoBoxHeight > document.WindowHeight
allora vuol dire che InfoBox fuoriesce in tutto o in parte inferiormente dalla
finestra e una parte del suo contenuto non è visibile. In questo caso, InfoBox viene "ribaltato"
in senso verticale: anziché essere posizionato al disotto della posizione del mouse, viene posizionato al disopra del mouse, con il margine
inferiore ad una distanza dalla posizione del mouse pari in valore assoluto a
quella che esisteva tra la posizione del mouse e il margine superiore di InfoBox prima della
rettifica:
InfoBoxOffsetY=-(InfoBoxOffsetY)-document.InfoBoxHeight;
Viene poi controllato se la linea laterale destra di InfoBox sia all'interno
della finestra:
if(RelativeToWindowMouseX+InfoBoxOffsetX+5
> document.WindowWidth - InfoBoxWidth)
{
InfoBoxOffsetX=-(InfoBoxOffsetX)-InfoBoxWidth;
}
La posizione orizzontale della linea destra di InfoBox rispetto al lato
sinistro della finestra è data dalla somma della posizione del mouse rispetto
al lato sinistro della finestra (RelativeToWindowMouseX) più la distanza orizzontale dell'angolo superiore
sinistro di InfoBox rispetto al mouse (InfoBoxOffsetX) più la larghezza di InfoBox (InfoBoxWidth). Se questo
valore è superiore alla larghezza della finestra (document.WindowHeight)
allora vuol dire che InfoBox fuoriesce in tutto o in parte dal lato destro della
finestra, e una parte del suo contenuto non è visibile. In questo caso InfoBox viene "ribaltato" orizzontalmente:
anziché essere posizionato a destra
della posizione del mouse, viene posizionato a sinistra del mouse, con il margine destro ad una distanza dalla
posizione del mouse pari in valore assoluto a quella che esisteva tra la
posizione del mouse e il margine sinistro di InfoBox prima della rettifica:
InfoBoxOffsetX=-(InfoBoxOffsetX)-InfoBoxWidth;
Dopo questi aggiustamenti, si procede a modificare
effettivamente la posizione di InfoBox:
mousex=event.pageX+InfoBoxOffsetX;
mousey=event.pageY+InfoBoxOffsetY;
$('.tooltip').offset({top:
mousey,left: mousex});
Consideriamo ora il codice che viene chiamato al
verificarsi dello spostamento del mouse entro uno dei box:
$('.MyBox,.MyAnchor').mousemove
(
function(event)
{
InfoBoxOffsetX = 30;
InfoBoxOffsetY = 40;
RelativeToWindowMouseX=event.pageX-document.HorizontalScrollValue;
RelativeToWindowMouseY=event.pageY-document.VerticalScrollValue;
if(RelativeToWindowMouseY + InfoBoxOffsetY
+ 5> document.WindowHeight - document.InfoBoxHeight){InfoBoxOffsetY=-(InfoBoxOffsetY)-document.InfoBoxHeight;}
if(RelativeToWindowMouseX+InfoBoxOffsetX +
5 > document.WindowWidth -
document.InfoBoxWidth){InfoBoxOffsetX=-(InfoBoxOffsetX)-document.InfoBoxWidth;}
mousex=event.pageX+InfoBoxOffsetX;
mousey=event.pageY+InfoBoxOffsetY;
$('.tooltip').offset({top: mousey,left:
mousex});
}
);
Vengono settati i valori dello spostamento di InfoBox rispetto alla
posizione del mouse:
InfoBoxOffsetX
= 30;
InfoBoxOffsetY
= 40;
Viene acquisita la posizione del mouse rispetto alla finestra (non al
documento):
RelativeToWindowMouseX=event.pageX-document.HorizontalScrollValue;
RelativeToWindowMouseY=event.pageY-document.VerticalScrollValue;
La posizione orizzontale del mouse rispetto alla
finestra è data dalla posizione del mouse rispetto al documento (event.pageX) meno il valore
dello scrolling orizzontale (document.HorizontalScrollValue).
La posizione verticale del mouse rispetto alla
finestra è data dalla posizione del mouse rispetto al documento (event.pageY) meno il valore
dello scrolling verticale (document.VerticalScrollValue):
Seguono istruzioni simili a quelle che abbiamo già
commentato nel caso dell'evento mouseover, per posizionare correttamente InfoBox, in modo che
tutto il suo contenuto risulti in vista:
if(RelativeToWindowMouseY
+ InfoBoxOffsetY + 5> document.WindowHeight - document.InfoBoxHeight)
{
InfoBoxOffsetY=-(InfoBoxOffsetY)-document.InfoBoxHeight;
}
if(RelativeToWindowMouseX+InfoBoxOffsetX
+ 5 > document.WindowWidth - document.InfoBoxWidth)
{
InfoBoxOffsetX=-(InfoBoxOffsetX)-document.InfoBoxWidth;
}
mousex=event.pageX+InfoBoxOffsetX;
mousey=event.pageY+InfoBoxOffsetY;
$('.tooltip').offset({top:
mousey,left: mousex});
Quando il mouse esce dal box, si attiva la funzione
collegata all'evento mouseout:
$('.MyBox,.MyAnchor').mouseout
(
function()
{
$(this).attr('title',
$(this).data('tipText'));
$('.tooltip').remove();
}
);
Viene ripristinato il valore dell'attributo "title" del box
(che era stato rimosso quando il mouse era entrato nel box):
$(this).attr('title',
$(this).data('tipText'));
Vengono rimossi i dati associati temporaneamente al
box per ospitare il contenuto dell'attributo "title":
$('.tooltip').remove();
Il codice che abbiamo esaminato sinora fa riferimento
in alcuni casi a valori ottenuti direttamente con metodi e proprietà jQuery,
come ad esempio:
event.pageX
event.pageY
mentre in altri casi fa riferimento a variabili
globali dichiarate al momento del caricamento della pagina
document.InfoBoxHeight=0;
document.InfoBoxWidth=0;
document.WindowHeight=window.innerHeight;
document.WindowWidth=window.innerWidth;
document.VerticalScrollValue=0;
document.HorizontalScrollValue=0;
document.RelativeToWindowMouseX=0;
document.RelativeToWindowMouseY=0;
Alcune di queste variabili sono acquisite al
caricamento del documento e non cambiano:
document.WindowHeight=window.innerHeight;
document.WindowWidth=window.innerWidth;
Altre variabili sono ricalcolate ad ogni spostamento
del mouse tramite apposite istruzioni:
document.WindowHeight=window.innerHeight;
document.WindowWidth=window.innerWidth;
document.VerticalScrollValue=0;
document.HorizontalScrollValue=0;
document.RelativeToWindowMouseX=0;
document.RelativeToWindowMouseY=0;
L'altezza e larghezza di InfoBox vengono
aggiornate, nella routine mouseover, una volta che le proporzioni di InfoBox sono state
modificate con il ciclo while che abbiamo già commentato:
while(InfoBoxWidth
< (InfoBoxHeight*(200/100)))
{
InfoBoxWidth=InfoBoxWidth*(105/100);
InfoBox.css({width:InfoBoxWidth});
InfoBoxHeight=InfoBox.css('height').replace("px","");
InfoBoxWidth=InfoBox.css('width').replace("px","");
}
document.InfoBoxWidth=InfoBoxWidth;
document.InfoBoxHeight=InfoBoxHeight;
La posizione del mouse rispetto alla finestra viene
calcolata entro la routine mouseover e la routine mousemove:
RelativeToWindowMouseX=event.pageX-document.HorizontalScrollValue;
RelativeToWindowMouseY=event.pageY-document.VerticalScrollValue;
E questo è tutto.
attenzione: Se
volete automatizzare le operazioni di inserzione delle informazioni nel campo
"title", scrivendole in un documento XML e inserendole nel tag al
momento del caricamento della pagina, consultate in questo documento l'articolo
"Inserire nel campo 'title' dei vostri link le informazioni visualizzate
dal browser al passaggio del mouse utilizzando XML, javascript e php"
Tutti i principali browser dispongono di una funzionalità
che verifica se un tag disponga al suo interno di un campo "title" e
in caso affermativo fa apparire, dopo una frazione di secondo, un minuscolo box
informativo con la stringa inserita in "title". Ad esempio, nel caso
del seguente tag:
<a
title="Questa è la pagina del principale giornale statunitense
online" href="usatoday.com">USA Today</a>
al passaggio del mouse sul link apparirà un piccolo
box con la spiegazione: "Questa è la pagina del principale giornale
statunitense online".
Se volete che tutti
i vostri link siano dotati di un simile box informativo, dovreste inserire un
campo "title" in ciascuno di essi, seguito da una stringa
illustrativa.
Questo crea qualche difficoltà nel momento in cui
volete aggiornare la descrizione di qualche link, perché dovrete aprire con un
editor il codice della pagina internet, cercare al suo interno il link - che
non è facile quando essa ne contiene parecchie decine - e modificare
l'attributo "title", salvando poi il tutto. Inoltre, se le
descrizioni sono lunghe, questo affollerà di stringhe il codice HTML rendendolo
poco leggibile.
L'alternativa che vi proponiamo qui è di dotare ogni
tag <a> di un id univoco che consente di capire immediatamente di quale
link si tratti, e di raccogliere tutte le descrizioni in un file XML posto
sullo stesso server dove è la vostra pagina web, dove ognuna di esse è
facilmente ritrovabile, perché associata all'id del link. Ogni tag <a>
avrebbe allora un id e un campo "title" vuoto:
<a id="UsaToday"
title="" href="usatoday.com">USA Today</a>
Per vedere all'opera questo sistema, apriamo la pagina
TitlesLoadingExample.htm, e osserviamone il codice.
Entro una tabella abbiamo 4 box il cui codice è (in
questo caso si tratta del Box 1):
<td
id="Box1"
class="MyBox" title="">
BOX 1
</td>
Come si vede l'attributo "title" esiste ma è
vuoto. Esso è destinato ad essere riempito con la stringa "Questo e' il
Box 1" contenuta nel file titles.xml. In altre parole, il testo da
visualizzare nella tooltip, anziché inserito nel codice della pagina html entro
il tag con l'istruzione title = "…" viene, più ordinatamente, letto
da una routine javascript/jQuery dal file titles.xml al momento del caricamento della pagina:
<?xml
version='1.0' encoding='utf-8'?>
<documenti>
<documento>
<titolo>Box1</titolo>
<presentazione>
Questo e' il Box 1
</presentazione>
</documento>
<documento>
<titolo>Box2</titolo>
<presentazione>
Questo e' il Box 2
</presentazione>
</documento>
<documento>
<titolo>Box3</titolo>
<presentazione>
Questo e' il Box 3
</presentazione>
</documento>
<documento>
<titolo>Box4</titolo>
<presentazione>
Questo e' il Box 4
</presentazione>
</documento>
<documento>
<titolo>Box5</titolo>
<presentazione>
Questo e' il Box 5
</presentazione>
</documento>
</documenti>
Ecco il codice ajax che consente di leggere il file
xml in cui sono contenuti i testi da inserire nei campi "title":
<script
type="text/javascript">
function FillTitleAttribute()
{
var mozillaFlag = false;
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
XMLHttpRequestObject.overrideMimeType("text/xml");
mozillaFlag = true;
}
else if (window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
if(XMLHttpRequestObject)
{
XMLHttpRequestObject.open("GET",
"titles.xml", true);
XMLHttpRequestObject.setRequestHeader('Content-Type', 'text/xml');
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
var xmlDocument =
XMLHttpRequestObject.responseXML;
if(mozillaFlag)
{
removeWhitespace(xmlDocument);
}
WriteTitles (xmlDocument);
}
}
XMLHttpRequestObject.send(null);
}
}
function WriteTitles(xmldoc)
{
var documenti = xmldoc.documentElement;
var LoopIndex;
var BoxName;
for(LoopIndex = 0;
LoopIndex<documenti.childNodes.length; LoopIndex++)
{
BoxName=documenti.childNodes[LoopIndex].firstChild.firstChild.nodeValue;
if (document.getElementById(BoxName) != null
&&
documenti.childNodes[LoopIndex].lastChild.firstChild.nodeValue.length > 8)
{
try
{
document.getElementById(BoxName).attributes["title"].value=documenti.childNodes[LoopIndex].lastChild.firstChild.nodeValue;
}
catch(err){}
}
}
}
function removeWhitespace(xml)
{
var loopIndex;
for (loopIndex = 0; loopIndex <
xml.childNodes.length; loopIndex++)
{
var currentNode = xml.childNodes[loopIndex];
if (currentNode.nodeType == 1)
{
removeWhitespace(currentNode);
}
if (((/^\s+$/.test(currentNode.nodeValue)))
&& (currentNode.nodeType == 3))
{
xml.removeChild(xml.childNodes[loopIndex--]);
}
}
}
</script>
La funzione FillTitleAttribute() viene richiamata al
caricamento della pagina mediante l'istruzione:
<body
onload="FillTitleAttribute();">
La funzione FillTitleAttribute() acquisisce con
una chiamata asincrona il file titles.xml, ne elimina gli spazi e i ritorni a
capo che potrebbero provocare malfunzionamenti, richiamando la funzione removeWhitespace(xml),
e poi passa il documento alla funzione WriteTitles(xmldoc) perché riempia i
campi "title".
Il codice, dopo aver letto il documento titles.xml, entra in un loop
che scorre uno alla volta gli elementi <documento>...</documento> di titles.xml, ne legge il campo <titolo>...</titolo> e se trova un tag di TitlesLoadingExample.htm che ha l'attributo "id" coincidente,
provvede a riempire l'attributo "title" con l'istruzione:
document.getElementById($(this).find('titolo').text()).attributes['title'].value=$(this).find('presentazione').text();
Quando non esiste un tag di TitlesLoadingExample.htm
con l'identificativo corrispondente a quello letto nel file titles.xml viene generato
errore, ma l'errore è catturato dalle istruzioni:
try
{
document.getElementById(BoxName).attributes["title"].value=documenti.childNodes[LoopIndex].lastChild.firstChild.nodeValue;
}
catch(err){}
in modo che il programma non si arresti e il loop
prosegua.
Il codice per leggere il file xml funziona sia
client-side (sul vostro computer non collegato alla rete) sia server-side (con
la pagina html e il file xml sul server).
Nel caso di un sito internet è di poca utilità un
codice che funziona in locale sul vostro computer, ma è tuttavia utile per il
debugging, perché per testarne il funzionamento non è necessario rifarne ogni
volta l'upload.
Ecco la versione del codice utilizzando invece jQuery:
<script
type="text/javascript">
$(document).ready(function()
{
$.get("titles.xml",function(xmlDoc)
{
$(xmlDoc).find('documento').each
(
function()
{
try
{
document.getElementById($(this).find('titolo').text()).attributes['title'].value=$(this).find('presentazione').text();
}
catch(err){}
}
);
},"xml");
});
</script>
Vi proponiamo infine un terzo modo di inserire il
testo di titles.xml nei tag che si vogliono dotare di tooltip, nella pagina TitlesLoadingExample.php (cliccate per
visualizzarla) mediante codice php.
Osserviamo la diversa struttura di uno dei box nel
<body> del documento:
<tr>
<td
<?W('Box1');?> class="MyBox">
BOX 1
</td>
</tr>
Come si vede, invece dell'attributo title = " ... " si ha un frammento di codice php:
<?W('Box1');?>
che richiama la funzione W($NomeFile)
definita nell'<head> della pagina:
<?php
function W($NomeFile)
{
$title = simplexml_load_file('titles.xml');
$MyArray=$title->xpath('//documento[titolo="'.$NomeFile.'"]');
$presentazione =
$MyArray[0]->presentazione;
print("title=\"".$presentazione."\"");
}
?>
la quale apre il file ToolTipText.xml, cerca
l'elemento <documento>…</documento> il cui titolo coincide con la
stringa passata come argomento e provvede a scrivere entro il tag
<td>…</td> la seguente stringa:
title="..."
dove il contenuto di title è il campo
<presentazione>…</presentazione> dell'elemento di ToolTipText.xml.
In tal modo la pagina html viene inviata dal server al
vostro computer già completa con gli attributi "title" riempiti.
Ricordiamo che anche in questo caso il file
ToolTipPage.php non funziona sul
vostro computer, ma su un server php, e quindi per vederla dovete farne
l'upload sul vostro server o installare un server php sul vostro computer.
❍ Alcune cose che javascript non fa o fa solo a prezzo di una
programmazione complicata e poco pulita
Javascript non può assolutamente scrivere
o leggere dei files che sono sul client, cioè sull'hard-disk dell'utente a cui
viene inviata la pagina web, e ciò per ovvi motivi di sicurezza.
L'unica maniera di memorizzare dati è
nelle variabili della pagina, dando loro nomi come window.MyVariable o document.MyVariable, oppure in qualche attributo di un tag (ad es.
nell'attributo title o nell'attributo value di un box di testo con la qualità
"display:hidden", che risulta nascosto all'utente, ma è leggibile da
javascript.
Ma questi dati spariranno con la chiusura
della sessione web.
Altri dati possono essere scritti nei
cookies, e possono rimanere sul computer ospite, ma non tutti i computer
accettano cookies, e quindi il codice scritto basandosi suo cookies è
assolutamente inaffidabile
Far aprire un documento nella stessa
finestra da cui lo si richiama con il comando:
window.open("NomeFile");
è estremamente difficile: il documento si
apre immancabilmente in un'altra finestra. A meno che non abbiate diverse ore da
perdere o un suggerimento funzionante
di un programmatore esperto (che chi scrive non ha trovato), lasciate perdere
per il momento.
I box di messaggio javascript sono molto
rudimentali; ad esempio nel box di input che compare con la seguente
istruzione:
Password = prompt("DIGITA LA PASSWORD","");
non è possibile modificare l'avviso "la
pagina all'indirizzo… dice:" che precede il testo del nostro prompt, né è
possibile cambiare la modalità di inserimento di una parola entro il box in
modo che durante la digitazione della password vengano mostrati solo
asterischi.
Malgrado abbia ottime funzionalità di
gestione di un file XML, javascript non può caricarlo direttamente, ma lo deve
trovare come variabile globale della pagina, e procurarglielo in questa forma è
alquanto laborioso, e richiede l'uso di altri linguaggi (ad esempio php e ajax)
❍ Una pagina php che cambia
aspetto ogni volta che la si ricarica
Aprite la pagina IndexRandom.php
e date un'occhiata al codice, riportato qui sotto (in particolare agli script
php, che non compaiono nel codice
della pagina web):
<html>
<head>
<?php
function DisplayTitle($elemento)
{
$nomi = array("DI BIANCANEVE",
"DELLA STREGA CATTIVA", "DEL PRESIDE DELLO SRAFFA",
"DI MATTEO RENZI", "DI SILVIO BERLUSCONI");
$azioni=array("STO FACENDO
BUNGA-BUNGA", "SONO IN BAGNO CON GRAVI PROBLEMI", "SONO
OFFLINE", "STO RIPARANDO LA MOTOZAPPA");
if($elemento=="nome")
{
$NumeroCasuale=rand(0,4);
print($nomi[$NumeroCasuale]);
}
elseif ($elemento=="azione")
{
$NumeroCasuale=rand(0,3);
print("$azioni[$NumeroCasuale]");
}
}
?>
</head>
<body>
</br></br>
<div
style="text-align:center;font-size:200%;font-weight:bold;">
BENVENUTO!
QUESTO E' IL SITO <?php DisplayTitle('nome'); ?>
</br></br>
AL
MOMENTO <?php
DisplayTitle('azione'); ?>.
</br></br>
RIPASSA PIU' TARDI.
</div>
</body>
</html>
La funzione DisplayTitle sceglie a caso un
elemento dell'array $nomi e uno dell'array $azioni e lo restituisce tramite
l'istruzione:
print("$nomi[$NumeroCasuale]");
print("$azioni[$NumeroCasuale]");
al codice che, nel messaggio di benvenuto,
la richiama.
In questo modo, ogni volta che si ricarica
la pagina, appare una scritta diversa.
❍ Un codice php per consentire agli utenti del vostro sito il download
di qualsiasi tipo di file
Per il download di file .doc, .pdf, .xls dal vostro
sito è sufficiente inserire il nome del file, ed esso sarà scaricato
correttamente:
<a
target="_parent" href="MyFile.xls">Clicca qui per
scaricare MyFile</a>
Ma quando si mettono sul server files .htm o .php o
.xml il download non viene effettuato correttamente. Per operare il download di
questi file è necessario creare un file download.php che contiene il seguente codice:
<?php
//
Recupero il nome del file dalla querystring
//
e lo accodo al percorso della cartella del download
$file
= (isset($_GET['filename']) ? $_GET['filename'] : false);
//
verifico che il file esista
if
(!file_exists($file))
{
// se non esiste stampo un errore
echo "Il file non esiste!";
}else{
// Se il file esiste...
// Imposto gli header della pagina per
forzare il download del file
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment;
filename= " . $file);
header("Content-Transfer-Encoding:
binary");
// Leggo il contenuto del file
readfile($file);
}
?>
Nella pagina html, il link per scaricare ad esempio il
file MyFile.htm
dovrà essere il seguente:
<a
target="_parent"
href="download.php?filename=MyFile.htm">Clicca qui per scaricare
MyFile</a>
Errore da principianti: il file download.php, per funzionare, deve essere sul server.
Se fate una prova del codice con download.php che è nella directory del sito che avete sul vostro
hard disk, quello che viene scaricato è… il file download.php.
❍ Una pagina in cui una routine
php genera una tabella che mostra il contenuto di un database
Aprite la pagina Experiments2.htm
. Date un'occhiata al codice con l'opzione "visualizza sorgente
pagina" del tasto destro del mouse (per Explorer l'opzione è
"HTML"):
<html>
<head>
<script
type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js">
</script>
<script
language="javascript">
$(document).ready(function()
{
$('#MostraAutoreButton').prop('checked',true);
$('#NonMostrareAutoreButton').prop('checked',false);
});
function
GetPoems()
{
var DisplayResults = "";
if
($('#MostraAutoreButton').prop('checked')){DisplayAuthor="true";}else{DisplayAuthor="false";}
$.get("GetPoems.php?DisplayAuthor="+DisplayAuthor,function(result54){$('#DisplayResults').html(result54);},"text");
}
</script>
</head>
<body
onload="GetPoems();">
</br></br>
<table
align="center" style="text-align:left;width:250px;border:1px
solid black;">
<tr>
<td>
<input align="center"
id="MostraAutoreButton" type="radio"
name="MostraAutore" value ="enabled">Mostra l'autore
</br>
<input id="NonMostrareAutoreButton"
type="radio" name="MostraAutore" value
="disabled">Non mostrare l'autore
</td>
</tr>
</table>
</br></br>
<table
align="center">
<tr>
<td>
<form name="RefreshForm"
action="">
<input type="button"
value="REFRESH" onclick="GetPoems();"/>
</form>
</td>
</tr>
</table>
</br></br>
<div
id="DisplayResults">
</div>
</body>
</html>
Al caricamento del documento (e ogni volta
che viene premuto il bottone "refresh") viene chiamata la funzione
GetPoems(), che a sua volta chiama in modo asincrono il file GetPoems.php
presente sul server, che contiene il seguente codice:
<?php
//VENGONO ACQUISITI I PARAMETRI
$FlagDisplayAuthor=(string)$_GET['DisplayAuthor'];
//CONNESSIONE AL DATABASE
$host = 'localhost';
$user = 'learningsources';
$database = 'my_learningsources';
$password = '';
$MyTable = "Haiku";
$db=mysql_connect($host,$user,$password);
mysql_select_db($database,$db);
//SELEZIONA IL RECORD IN BASE ALLA CONDIZIONE
PASSATA COME PARAMETRO
$query="select * FROM Haiku";
$dbResult=mysql_query($query,$db);
$AffectedRows=mysql_numrows($dbResult);
//SE ESISTE IL RECORD CORRISPONDENTE ALLA
QUERY, GENERA LA TABELLA
if ($AffectedRows>0)
{
echo "<table align='center'
style='border:1px solid blue;background-color:blue;border:1px solid
blue;'>";
if($FlagDisplayAuthor=="true")
{
echo "<td align='center'
valign='top' style='color:red;border:1px solid blue;background-color:white;font-size:150%;font-family:Times
New
Roman;padding-left:20px;padding-right:20px;padding-top:15px;padding-bottom:15px;font-weight:bold;'>AUTORE</td>";
echo "<td align='center'
valign='top' style='color:red;border:1px solid blue;background-color:white;font-size:150%;font-family:Times
New
Roman;padding-left:20px;padding-right:20px;padding-top:15px;padding-bottom:15px;font-weight:bold;'>HAIKU</td>";
}
else
{
echo "<td align='center'
valign='top' style='color:red;border:1px solid blue;background-color:white;font-size:150%;font-family:Times
New
Roman;padding-left:20px;padding-right:20px;padding-top:15px;padding-bottom:15px;font-weight:bold;'>HAIKU</td>";
}
while($row = mysql_fetch_array($dbResult))
{
echo "<tr>";
if($FlagDisplayAuthor=="true")
{
echo "<td align='center'
style='border:1px solid
blue;background-color:white;font-size:150%;font-family:Times New
Roman;padding-left:20px;padding-right:20px;padding-top:15px;padding-bottom:15px;font-weight:bold;'>".$row['Autore']."</td>";
echo "<td align='center'
style='border:1px solid
blue;background-color:white;font-size:150%;font-family:Times New
Roman;padding-left:20px;padding-right:20px;padding-top:15px;padding-bottom:15px;font-weight:bold;'>".$row['Testo']."</td>";
}
else
{
echo "<td align='center'
style='border:1px solid
blue;background-color:white;font-size:150%;font-family:Times New
Roman;padding-left:20px;padding-right:20px;padding-top:15px;padding-bottom:15px;font-weight:bold;'>".$row['Testo']."</td>";
}
echo "</tr>";
}
echo "</table>";
}
//CHIUDE IL DATABASE
mysql_close($db);
?>
Questo codice php si collega alla tabella
"Haiku" del database "my_learningsources" presente sul
server altervista.org e invia indietro tramite la funzione "echo" il
testo delle poesie e l'autore, incapsulandoli nelle righe di una tabella (pure
generata con la funzione "echo"). Queste righe vengono visualizzate
come contenuto del tag:
<div
id="DisplayResults">
</div>
Tramite l'istruzione ajax:
$.get("GetPoems.php?DisplayAuthor="+DisplayAuthor,function(result54){$('#DisplayResults').html(result54);},"text");
Se il bottone "Mostra Autore" è
stato selezionato, il parametro "DisplayAuthor" passato alla routine
php è "true", e viene generata anche la colonna corrispondente
all'autore.
❍ Come importare una tabella
Access nel database MySQL del vostro server, utilizzando XML e php
Per compiere questa operazione sfrutteremo una utile
funzionalità dei database Access, che possono esportare il contenuto di una
tabella in formato XML.
Creiamo anzitutto nel nostro database MySQL una
tabella di prova, che denomineremo "Haiku", i cui campi sono:
Indice (smallint(6), autoincremento, chiave primaria)
Autore (TEXT, 512 caratteri)
Epoca (TEXT, 512 caratteri)
Paese (TEXT, 512 caratteri)
Soggetto (TEXT, 1024 caratteri)
Testo (TEXT, 65535 caratteri)
Creiamo nel nostro database Access una tabella di
prova, che denomineremo "Haiku", i cui campi sono:
Indice (intero lungo, autoincremento, chiave primaria)
Autore (testo breve, 255 caratteri)
Epoca (testo breve, 255 caratteri)
Paese (testo breve, 255 caratteri)
Soggetto (testo breve, 255 caratteri)
Testo (testo lungo)
Apriamo la tabella "Haiku" in Access e nel
menu "dati esterni"
selezioniamo l'opzione "File XML" e seguiamo le istruzioni per
generare il file.
L'esportazione opera solo sui record selezionati, e
questo vi permette di scegliere quelli da trasferire operando un filtraggio
sulla tabella Access.
Se volete eliminare dei campi, l'unico modo è creare
una copia della tabella e rimuovere i campi dalla sua struttura; altrimenti
l'esportazione creerà delle intestazioni XML anche per i cambi indesiderati.
Vi consiglio di non rimuovere i caratteri speciali con
cui Access sostituisce le vocali accentate e altri caratteri critici per XML e
HTML, perché a quanto mi risulta le sigle immesse al loro posto vengono
tradotte perfettamente dal browser.
Se il codice php non dovesse funzionare, controllate
anzitutto che nel file XML non vi siano caratteri come apici o virgolette, che
devono essere introdotti preceduti dal backslash: \' , \" .
L'unica pecca è che nell'esportazione in XML vengono
persi i caratteri CR (ritorno a capo).
Nel nostro esempio di prova noi abbiamo già generato
un output XML nel file Haiku.xml
(clicca per scaricarlo).
Creiamo il file EsportaDatabase.php
(clicca per scaricarlo) inserendovi il seguente codice:
<?php
//CREA LE
VARIABILI CON I NOMI DEI CAMPI
$FNameAutore='Autore';
$FNameEpoca='Epoca';
$FNamePaese='Paese';
$FNameSoggetto='Soggetto';
$FNameTesto='Testo';
//CONNESSIONE
AL DATABASE
$host =
'localhost';
$user =
'BlogName';
$password =
'';
$database =
'my_BlogName';
$tabella =
'Haiku';
$db=mysql_connect($host,$user,$password)
or
die("Impossibile connettersi al server $host");
mysql_select_db($database,$db)
or die("Impossibile
connettersi al database $database");
//ACQUISISCE
I VALORI DA IMMETTERE NEL DATABASE
$ITEMS =
simplexml_load_file('Haiku.xml') or die("ERROR");
foreach($ITEMS->children()
as $item)
{
echo $item->Indice."</br>";
$FValueAutore=$item->Autore;
$FValueEpoca=$item->Epoca;
$FValuePaese=$item->Paese;
$FValueSoggetto=$item->Soggetto;
$FValueTesto=$item->Testo;
$sql = "
INSERT INTO $tabella(
$FNameAutore,
$FNameEpoca,
$FNamePaese,
$FNameSoggetto,
$FNameTesto)
VALUES(
'$FValueAutore',
'$FValueEpoca',
'$FValuePaese',
'$FValueSoggetto',
'$FValueTesto')";
$dbResult=mysql_query($sql,$db);
}
//CHIUDE IL
DATABASE
mysql_close($db);
?>
In questo esempio abbiamo denominato il nome
dell'ipotetico sito "BlogName" e il nome del database
"my_BlogName"
Trasferite sul server il file EsportaDatabase.php
Digitate sulla barra degli indirizzi del vostro
browser il seguente indirizzo:
"BlogName.altervista.org/EsportaDatabase.php"
Premendo il pulsante "vai" Il file php verrà
immediatamente eseguito sul server, e al vostro browser verrà inviata una copia
della pagina generata con la funzione "echo", che lista il numero
identificativo dei record trasferiti, per consentirvi di controllare il buon
esito dell'operazione. E questo è tutto: in pochi secondi i record sono stati
trasferiti sul database del vostro sito.
❍ Alcune cose che php non fa,
anche se sembrerebbe possibile
Php non
ha accesso agli elementi del documento, né in lettura né per modificarli.
Non possiede un modello DOM analogo a quello di javascript.
Per la verità è possibile caricare una
immagine xml della pagina che php legge, ma gli è impossibile modificare gli
elementi della pagina tramite riferimenti DOM.
Ricordate sempre che javascript inizia a
funzionare solo dopo che è stato eseguito
il codice php, e quindi le funzioni php non sono accessibili a javascript e
quelle javascript non sono accessibili a php (sebbene php possa modificarne il
testo).
Ajax è l'acronimo di Asynchronous JavaScript and XML, ed è un insieme di tecniche per
creare siti web altamente interattivi e applicazioni web. Una delle tecniche
più importanti e caratteristiche di ajax è quella che combina le risorse di
vari linguaggi per ottenere l'aggiornamento della pagina web usando dati
scaricati da internet, senza il refresh della finestra del browser (asynchronous data retrieval).
Oltre a questa, ajax comprende le tecniche
più potenti che impiegano XML, CSS, il DOM javascript, in combinazione tra loro
per creare una pagina web altamente dinamica. In altre parole, ajax non è un nuovo linguaggio di programmazione,
ma piuttosto un insieme di tecniche che utilizza linguaggi esistenti per
ottenere risultati nuovi o più sofisticati di quelli che si potrebbe ottenere
dall'impiego dei singoli linguaggi. Il linguaggio-base che collega tutte le
varie parti di una applicazione ajax è javascript.
La potenzialità più sofisticata e
distintiva di ajax è, come abbiamo detto, quella che ottiene dei dati dal sito
che ha inviato la pagina o da altre fonti su internet e li fa apparire sulla
pagina senza bisogno di refresh e
senza che la pagina si blocchi durante il download
dei dati. Una delle prime applicazioni ajax di tal genere si è avuta per la
posta elettronica, ed è stata implementata da Google: ogni volta che arrivava
una nuova mail nella casella che l'utente aveva aperto, veniva aggiornata solo
la sezione della finestra contenente la mail, con notevole risparmio di kilobyte
da parte della connessione internet dell'utente. Anche le chat visualizzano ciò
che gli altri utenti hanno scritto nella vostra pagina e ciò che voi avete
scritto sulle pagine degli altri utenti senza nessun refresh dello schermo. Anche le tecniche di drag-and-drop che
consentono alle applicazioni più avanzate come ad esempio Mosaic di trascinare
un oggetto da un sito internet sulla propria pagina utilizzano ajax per
comunicare cosa ajax deve scaricare dal sito e dove deve visualizzarlo. Anche
le immagini possono essere cambiate, modificando la sorgente senza cambiare
l'intera pagina. Giochi online come i giochi degli scacchi modificano l'aspetto
della scacchiera senza modificare altri elementi della pagina grazie ad ajax.
Per vedere ajax all'opera, apriamo il file
AjaxExample1.htm
e clicchiamo sul bottone che vi appare: il messaggio nel box cambierà, e verrà
visualizzato il testo: "Welcome to Ajax!". Questo testo è contenuto
nel file data.txt, che è posto sul server. Analizziamo il codice della
pagina:
<html>
<head>
<script
language = "javascript">
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function getData(dataSource, divID)
{
if(XMLHttpRequestObject)
{
XMLHttpRequestObject.open("GET", "data.txt");
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
document.getElementById("targetParagraph").innerHTML =
XMLHttpRequestObject.responseText;
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
</head>
<body>
</br>
<p
style="text-align:center;font-size:120%;font-weight:bold;">Un
esempio di acquisizione di dati in modo asincrono da parte del browser tramite
ajax</p>
</br></br>
<form
style="text-align:center;">
<input type = "button" value =
"Acquisisci il messaggio" onclick = "getData();">
</form>
</br></br>
<div align="center">
<p id="targetParagraph"
style="font-size:110%;color:red;border:1px solid
black;height:40px;width:400px;margin:auto;padding-top:20px;padding-bottom:0px;">Il
messaggio acquisito apparirà qui</p>
</div>
</body>
</html>
Il paragrafo destinato ad ospitare i dati
acquisiti in modo asincrono da data.txt è il paragrafo "targetParagraph":
<div align="center">
<p id="targetParagraph"
style="font-size:110%;color:red;border:1px solid
black;height:40px;width:400px;margin:auto;padding-top:20px;padding-bottom:0px;">Il
messaggio acquisito apparirà qui</p>
</div>
La funzione getData() viene richiamata con la seguente istruzione,
inserita nel tag <button>:
onclick =
"getData();"
Le istruzioni, contenute nella funzione
getData, che trasferiscono i dati nel paragrafo sono:
document.getElementById("targerParagraph").innerHTML
= XMLHttpRequestObject.responseText;
Ma come viene acquisito il contenuto di data.txt? Viene anzitutto
creato l'oggetto di classe XMLHttpRequest, che serve a JavaScript a comunicare con il server e
a scaricare dati dal server:
var
XMLHttpRequestObject = false;
if
(window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if
(window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
L'oggetto viene posto in una variabile
globale chiamata XMLHttpRequestObject. L'oggetto XMLHttpRequest è disponibile come oggetto javascript in tutti i
browser, ma è differente il modo di accedervi da browser a browser. Netscape
Navigator, Safari versione 1.2 e successive e Firefox permettono di creare un
oggetto XMLHttpRequest direttamente con l'istruzione:
XMLHttpRequestObject
= new XMLHttpRequest();
Questo implica che esista l'oggetto
window.XMLHttpRequest, e quindi la possibilità di crearlo per tal via può
essere testata con l'istruzione condizionale:
if(window.XMLHttpRequestObject)
{…}
Nel caso di Internet Explorer, Microsoft,
come sempre, fa a modo suo, e richiede una istruzione diversa:
XMLHttpRequestObject
= new ActiveXObject("Microsoft.XMLHTTP");
Una volta creati questi oggetti, almeno
per le funzionalità di base, funzionano allo stesso modo in tutti i browser.
Ecco i metodi dell'oggetto XMLHttpRequest di Internet Explorer:
proprietà |
descrizione |
onreadystatechange |
Contiene il nome del gestore di eventi
che deve essere chiamato quando il valore della proprietà readyState cambia (lettura/scrittura) |
readyState |
Contiene lo stato della richiesta
(lettura) |
responseBody |
Contiene il corpo della risposta
risposta. E' uno dei modi in cui una richiesta HTTP può essere eseguita |
responseStream |
Contiene uno stream binario di risposta
alla richiesta HTTP (lettura) |
responseText |
Contiene il corpo della risposta come
stringa (lettura) |
responseXML |
Contiene il corpo della risposta come
documento XML (lettura) |
status |
Contiene il codice HTTP di status
restituito in seguito a una richiesta (lettura) |
statusText |
Contiene lo status della risposta come
testo (lettura) |
metodo |
descrizione |
abort |
abortisce la richiesta HTTP |
getAllResponseHeaders |
restituisce gli headers HTTP |
getResponseHeader |
restituisce il valore di un header HTTP |
open |
apre una richiesta al server |
send |
invia una richiesta al server |
setRequestHeader |
setta il nome e il valore di un header HTTP |
Ecco le proprietà e metodi dell'oggetto XMLHttpRequest per Firefox e NetScape Navigator
proprietà |
descrizione |
channel |
Contiene il canale utilizzato per
effettuare la richiestra (lettura) |
readyState |
Contiene lo stato della richiesta
(lettura) |
responseText |
Contiene il corpo della risposta come
stringa (lettura) |
responseXML |
Contiene il corpo della risposta come
documento XML (lettura) |
status |
Contiene il codice HTTP di status
restituito in seguito a una richiesta (lettura) |
statusText |
Contiene lo status della risposta come
testo (lettura) |
metodo |
descrizione |
abort |
abortisce la richiesta HTTP |
getAllResponseHeaders |
restituisce gli headers HTTP |
getResponseHeader |
restituisce il valore di un header HTTP |
openRequest |
metodo nativo (nonscript) per aprire una
richiesta al server |
overrideMimeType |
bypassa il tipo MIME che il server
restituisce |
Ecco le proprietà e metodi dell'oggetto XMLHttpRequest per Safari:
proprietà |
descrizione |
onreadystatechange |
Contiene il nome del gestore di eventi
che deve essere chiamato quando il valore della proprietà readyState cambia (lettura/scrittura) |
readyState |
Contiene lo stato della richiesta
(lettura) |
responseText |
Contiene il corpo della risposta come
stringa (lettura) |
responseXML |
Contiene il corpo della risposta come
documento XML (lettura) |
status |
Contiene il codice HTTP di status
restituito in seguito a una richiesta (lettura) |
statusText |
Contiene lo status della risposta come
testo (lettura) |
metodo |
descrizione |
abort |
abortisce la richiesta HTTP |
getAllResponseHeaders |
restituisce gli headers HTTP |
getResponseHeader |
restituisce il valore di un header HTTP |
open |
apre una richiesta al server |
send |
invia una richiesta al server |
setRequestHeader |
setta il nome e il valore di un header
HTTP |
Al caricamento del documento il browser
cerca di creare, secondo le istruzioni, un oggetto XMLHttpRequest. Il codice che
segue, contenuto nella funzione getData(), controlla anzitutto che la variabile sia stata
creata con successo, e solo in quel caso procede all'esecuzione delle
istruzioni ajax:
if(XMLHttpRequestObject)
{
.........
.........
.........
}
A
questo scopo la variabile XMLHttpRequestObject è inizializzata con il valore false, in modo che, se non si è avuto
successo nel crearla, l'istruzione sopra riportata dà come valore "false"
Se l'oggetto è stato creato, esso viene
aperto:
XMLHttpRequestObject.open("GET",
dataSource);
La struttura del metodo .open è la seguente (i
parametri opzionali sono compresi tra parentesi quadre):
open(metodo, URL, [asyncFlag], [userName], [password])
ecco una spiegazione dei parametri:
metodo |
il metodo HTTP utilizzato per aprire la
connessione (GET,
POST, PUT, HEAD, PROPFIND) |
URL |
l'URL da contattare quando ci si
connette col server |
asyncFlag |
un valore booleano che indica se la
chiamata è asincrona (default: true) |
userName |
lo username del proprio account |
password |
la password utilizzata per collegarsi al
proprio account |
Nel nostro esempio il metodo scelto per
contattare il server è il metodo "GET" (che è il modo usuale di contattare i server).
L'URL
è passata alla funzione tramite il parametro dataSource. Il metodo open configura l'oggetto XMLHttpRequest, ma non apre ancora alcuna connessione col server.
L'URL si può riferire non solo ad un file di dati, ma anche
ad un file che contiene uno script php destinato a recuperare/creare i dati. L'URL
si può riferire a un file che è sullo stesso server su cui è la pagina HTML che
utilizza il codice ajax, oppure ad un server estraneo che mette a disposizione
la risorsa cercata (ad es. Google mette a disposizione i suoi notiziari o il
risultato di una ricerca in formato XML o Json).
Il processo è asincrono (valore di default) non solo nel senso che alla sua
conclusione non avviene il refresh
dell'intera pagina, ma anche nel senso che la pagina non si blocca in attesa
che il download dei dati sia completato: l'utente può continuare ad interagire
con essa mentre esso viene effettuato.
Ajax segnala al browser che il download si è concluso mediante la
proprietà XMLHttpRequestObject.onreadystatechange, che attiva una funzione di callback quando si verifica una variazione qualsiasi nello stato del download
(inizio del download, download già
iniziato, completamento del download ecc.).
XMLHttpRequestObject.onreadystatechange
= function() {...}
In realtà, la proprietà onreadystatechange
segnala solo che la variabile di stato XMLHttpRequestObject.readyState, che esprime la situazione del download ha subito un mutamento: occorre verificare che il
cambiamento coincide con il completamento del download, verificando la proprietà XMLHttpRequestObject.readyState e la proprietà XMLHttpRequestObject.status:
if
(XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status ==
200)
Ecco un prospetto dei valori che può
assumere la proprietà readyState:
0 |
Unitialized |
1 |
Loading |
2 |
Loaded |
3 |
Interactive |
4 |
Complete |
Ecco un prospetto dei valori che può
assumere la proprietà status:
200 |
OK |
201 |
Created |
204 |
No Content |
205 |
Reset Content |
206 |
Partial Content |
400 |
Bad Request |
401 |
Unauthorized |
403 |
Forbidden |
404 |
Not Found |
405 |
Method Not Allowed |
406 |
Not Acceptable |
407 |
Proxy Authentication Required |
408 |
Request Timeout |
411 |
Length Required |
413 |
Requested Entity Too Large |
414 |
Requested URL Too Long |
415 |
Unsupported Media Type |
500 |
Internal Server Error |
501 |
Not Implemented |
502 |
Bad Gateway |
503 |
Service Unavailable |
504 |
Gateway Timeout |
505 |
HTTP Version Not Supported |
Il verificarsi della condizione XMLHttpRequestObject.readyState == 4 ("download completato") non è sufficiente:
occorre testare la condizione XMLHttpRequestObject.status
== 200 ("download
effettuato con successo") per poter iniziare a lavorare con i dati.
Prima che l'istruzione contenuta nella
funzione di callback sia eseguita:
obj.innerHTML
= XMLHttpRequestObject.responseText;
occorre effettuare la chiamata al server: tutto ciò che abbiamo fatto
sinora è stato prepararla. La
chiamata viene effettuata tramite una semplice istruzione:
XMLHttpRequestObject.send(null);
Perché viene passato un valore null? Perché il passaggio di eventuali
parametri è previsto dal metodo POST, ma non dal metodo GET, e quindi va inviato un argomento vuoto.
Lo stesso risultato (ottenimento di una
stringa di testo "Welcome to Ajax!" dal server può essere ottenuto
chiamando un file php
anziché un file txt.
La funzione getData() sarà allora richiamata con la seguente istruzione,
inserita nel tag <button>:
onclick =
"getData('data.php', 'targetParagraph')"
Ovviamente dovrà esistere un file data.php sul server, che
invii la stringa con la tipica istruzione "echo" di php. Ecco il contenuto del file data.php:
<?php
echo "Welcome to Ajax!";
?>
❍ Inviare dati al server tramite
i metodi GET e POST e gestirli con una routine php
Il metodo "GET" che abbiamo
visto sopra consente, utilizzando un file php, di inviare, anziché ricevere dati al server. Per far questo è
sufficiente far seguire il nome del file php con cui si vuole comunicare da un
punto interrogativo seguito dal nome (arbitrario) dei parametri e dal loro
valore:
Nel file AjaxExample2.htm
abbiamo posto lo stesso codice di AjaxExample1.htm, tranne che per l'istruzione
che contiene il file da chiamare (qui sotto evidenziata in colore):
<script
language = "javascript">
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function getData(dataSource, divID)
{
if(XMLHttpRequestObject)
{
XMLHttpRequestObject.open("GET", "data2.php?Nome=Pietro&Cognome=Gambadilegno");
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
document.getElementById(divID).innerHTML =
XMLHttpRequestObject.responseText;
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
L'istruzione:
XMLHttpRequestObject.open("GET",
"data.php?Nome=Pietro&Cognome=Gambadilegno");
contiene il parametro "Nome=Pietro" e il
parametro "Cognome=Gambadilegno". I nomi dei parametri possono essere
completamente arbitrari. Essi possono essere letti dal file data2.php con la
seguente istruzione:
$Nome = $_GET["Nome"];
$Cognome = $_GET["Cognome"];
Per essere sicuri di aver acquisito il
contenuto come stringa si può usare la variante:
$Nome =
(string)$_GET["Nome"];
$Cognome =
(string)$_GET["Cognome"];
Poi il nome e il cognome sono inviate
indietro al computer client che ha
effettuato la chiamata tramite l'istruzione:
echo
$Nome." ".$Cognome;
L'intero codice del file data2.php è quindi:
<?php
$Nome = $_GET["Nome"];
$Cognome = $_GET["Cognome"];
echo $Nome." ".$Cognome;
?>
Cliccando sul bottone, apparirà nel
paragrafo MyParagraph il testo: "Il nome inviato al server è: Pietro
Gambadilegno".
Per inviare questi dati, invece che il
metodo GET
si può usare il metodo POST. Si può osservare in azione tale metodo aprendo il
file AjaxExample3.htm.
Il codice ajax per collegarsi al server allora sarà il seguente (le modifiche
sono evidenziate in colore):
<script
language = "javascript">
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function getData()
{
if(XMLHttpRequestObject)
{
XMLHttpRequestObject.open("POST",
"data3.php");
XMLHttpRequestObject.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
document.getElementById("targetParagraph").innerHTML =
"Il nome inviato al server è: "+XMLHttpRequestObject.responseText;
}
}
XMLHttpRequestObject.send("Nome=Pietro&Cognome=Gambadilegno");
}
}
</script>
Come si vede, non viene più inviata una
stringa nulla con l'istruzione XMLHttpRequestObject.send, ma una stringa contenente i parametri che col metodo
GET venivano passati con l'URL del documento a cui collegarsi:
XMLHttpRequestObject.send("Nome=Pietro&Cognome=Gambadilegno");
Il codice del file data3.php sarà il seguente:
<?php
$Nome=$_POST["Nome"];
$Cognome=$_POST["Cognome"];
echo $Nome." ".$Cognome;
?>
❍ Acquisire un documento XML dal
server e metterlo a disposizione di javascript
Vediamo ora come si può utilizzare il
codice ajax per il collegamento asincrono in modo da ottenere dal server non
una stringa di testo, ma un documento XML. Proveremo a caricare e manipolare il
file colors.xml,
che ha il seguente contenuto:
<?xml
version="1.0">
<colors>
<color>red<color>
<color>green</color>
<color>blue</color>
</colors>
Aprite il documento XMLDisplay2.htm
ed osservatene il codice:
<html>
<head>
<script
language = "javascript">
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function getData()
{
if(XMLHttpRequestObject)
{
XMLHttpRequestObject.open("GET",
"colors.xml?timestamp=" + new Date().getTime());
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
var
xmlDocument=XMLHttpRequestObject.responseXML;
var colors =
xmlDocument.getElementsByTagName("color");
document.getElementById("targetParagraph").innerHTML
= "Il secondo colore è: " + colors[1].firstChild.nodeValue;
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
</head>
<body>
</br>
<p
style="text-align:center;font-size:120%;font-weight:bold;">
Un esempio di acquisizione di dati da un
documento XML in modo asincrono da parte del browser tramite ajax:</br>
La chiamata al file <span
style="font-family:Courier
New;font-size:90%">colors.xml</span> restituisce il documento
<span style="font-family:Courier
New;font-size:90%">xmlDoc</span>.</br>
Il codice javascript di questa pagina legge
i colori contenuti nei tag <span style="font-family:Courier
New;font-size:90%"><color></span>.</br>
I nomi dei colori vengono poi visualizzati
nel box, senza che il resto della pagina subisca il
<i>refresh</i>.
</p>
</br></br>
<form
style="text-align:center;">
<input type = "button" value =
"Acquisisci il messaggio" onclick = "getData();">
</form>
</br></br>
<div align="center">
<p id="targetParagraph"
style="font-size:110%;color:red;border:1px solid
black;height:40px;width:400px;margin:auto;padding-top:20px;padding-bottom:0px;">Il
messaggio acquisito apparirà qui</p>
</div>
</body>
</html>
Il codice evidenziato in colore contiene
le istruzioni per acquisire e leggere il documento XML:
XMLHttpRequestObject.open("GET",
"colors.xml?timestamp=" + new Date().getTime());
... ... ...
var
xmlDocument=XMLHttpRequestObject.responseXML;
var colors =
xmlDocument.getElementsByTagName("color");
document.getElementById("targetParagraph").innerHTML
= "Il secondo colore è: " + colors[1].firstChild.nodeValue;
La prima riga configura l'oggetto XMLHttpRequestObject
per una chiamata ajax, che poi viene effettuata con:
XMLHttpRequestObject.send(null);
Seguono poi delle righe che abbiamo omesso
per controllare se il download dei dati sia avvenuto con successo, e poi la
lettura dei dati inviati in formato XML e il loro salvataggio nella variabile xmlDocument:
var
xmlDocument=XMLHttpRequestObject.responseXML;
Successivamente viene creato un array che
contiene tutti i nodi <color> del documento XML:
var colors =
xmlDocument.getElementsByTagName("color");
Infine, viene letto il valore del secondo
nodo (dato che la numerazione degli array sovente inizia da "0", il
secondo nodo avrà il numero "1"):
document.getElementById("targetParagraph").innerHTML
= "Il secondo colore è: " + colors[1].firstChild.nodeValue;
Questo valore viene poi mostrato nel box
"targetParagraph":
document.getElementById("targetParagraph").innerHTML
= "Il secondo colore è: " + colors[1].firstChild.nodeValue;
❍ Acquisire codice javascript dal
server ed eseguirlo immediatamente tramite la funzione eval()
Allo stesso modo in cui ajax può
effettuare il download di testo e
XML, può scaricare dal server codice javascript ed eseguirlo immediatamente.
Aprite il file AjaxExample4.htm ed osservatene il codice:
<html>
<head>
<script
language = "javascript">
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function getData()
{
if(XMLHttpRequestObject)
{
XMLHttpRequestObject.open("GET",
"data4.php");
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
eval(XMLHttpRequestObject.responseText);
}
}
XMLHttpRequestObject.send(null);
}
}
function show()
{
document.getElementById("targetParagraph").innerHTML="La
funzione show() è stata attivata";
}
</script>
</head>
<body>
</br>
<p
style="text-align:center;font-size:120%;font-weight:bold;">
Un esempio di acquisizione di dati in modo
asincrono da parte del browser tramite ajax:</br>
La chiamata al file <span
style="font-family:Courier
New;font-size:90%">data4.php</span> acquisisce il codice
javascript della funzione <span style="font-family:Courier
New;font-size:90%">show()</span> e lo esegue.</br>
La funzione <span
style="font-family:Courier New;font-size:90%">show()</span>
fa apparire una stringa nel box.
</p>
</br></br>
<form
style="text-align:center;">
<input type = "button" value =
"Acquisisci il messaggio" onclick = "getData();">
</form>
</br></br>
<div align="center">
<p id="targetParagraph"
style="font-size:110%;color:red;border:1px solid
black;height:40px;width:400px;margin:auto;padding-top:20px;padding-bottom:0px;">Il
messaggio acquisito apparirà qui</p>
</div>
</body>
</html>
La prima linea di codice evidenziata in
colore acquisisce l'echo del file data4.php, che consiste di
una sola riga di codice javascript:
<?php
echo 'show()';
?>
la stringa 'show()' viene eseguita come codice javascript dalla funzione eval(), e richiama la
funzione definita nelle righe successive evidenziate in colore: questa funzione
farà apparire un testo nel box della pagina.
❍ Creare un oggetto javascript
che incorpori una pagina html esterna e manipolarla
E' possibile incorporare un documento html
esterno in un oggetto javascript da poter trattare con una interfaccia DOM allo
stesso modo dell'oggetto document che
rappresenta la pagina corrente?
In alternativa, è possibile acquisirlo
come pagina XML e leggerlo secondo la sintassi javascript per i files XML?
Quando una stringa è passata come
parametro alla funzione $(…), jQuery controlla se abbia dei tag html; se non li
ha, la stringa è interpretata come selettore; se li ha, viene creato un nuovo
DOM element, sul quale possono essere effettuate tutte le operazioni jQuery.
Primo sistema: utilizzare
l'istruzione .load di jQuery
Con jQuery disponiamo dell'istruzione:
$("#targetParagraph").load("MyPage2.htm
#MyFirstParagraph");
che consente di caricare un elemento di
una pagina web esterna (in questo caso "MyPage2.htm") direttamente in un elemento della pagina
corrente (tipicamente un <div> o un <p> o un <td>). Mediante una stringa come "#MyFirstParagraph"
si può selezionare uno specifico elemento tramite il suo id. Si ricordi solo di
distanziare di uno spazio l'id dal nome del documento. Questa istruzione può
caricare files di tipo diverso da html: files di testo o xml.
Secondo sistema: utilizzare
una routine php che scarichi la pagina e la invii tramite ajax al computer client (sconsigliato)
Esistono delle istruzioni php che possono
inviare un documento tramite la funzione echo:
var
XMLHttpRequestObject = false;
if (window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function getData()
{
if(XMLHttpRequestObject)
{
XMLHttpRequestObject.open("GET",
"data5.php");
XMLHttpRequestObject.responseType =
"document";
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
alert(XMLHttpRequestObject.responseXML.getElementsByTagName("body")[0].nodeName);
}
}
XMLHttpRequestObject.send(null);
}
}
Questa routine ajax richiama il file data5.php, che fa il
dowload di un file da un server qualsiasi della rete (in questo caso dal server
learningsources.altervista.org):
<?php
$filehandle =
fopen("www.learningsources.altervista.org/MyPage2.htm",
"r");
while (!feof($filehandle))
{
$download = fgets($filehandle);
echo $download;
}
fclose($filehandle);
?>
Il codice ajax genera un alert che reca
scritto "body" (che è il
nome dell'elemento selezionato). L'utilizzo di php serve, in alternativa al
caricamento diretto, a impedire che il processo di download sia interrotto da
una richiesta di autorizzazione da parte del browser, che viene spesso
visualizzata se il server dal quale si importa il file è diverso dal server a
cui è collegato il browser. Ma il codice impiega
circa trenta secondi per ultimare il caricamento e visualizzare
l'informazione sul documento, pertanto è di scarsa utilità.
Stesso rallentamento inaccettabile
utilizzando in alternativa una routine jQuery:
function
getData()
{
$.ajax
({
url:"data5.php",
dataType:"html",
success:function(htmlDocument)
{
alert(XMLHttpRequestObject.responseXML.getElementsByTagName("body")[0].nodeName);
}
});
}
Terzo sistema: utilizzare il
metodo document.implementation.createHTMLDocument
Esiste un metodo di recente introduzione
per acquisire una pagina html esterna come oggetto document di javascript, che
permette di utilizzare tutti i metodi e le proprietà di un modello DOM. Esso è
supportato da Internet Explorer versione 9 e successive, da Chrome, Opera,
Safari tra gli altri browser. Ecco la sintassi per creare tramite una routine
ajax un simile documento e leggerne un tag <div> (con jQuery le istruzioni possono essere
significativamente accorciate):
var
XMLHttpRequestObject = false;
if
(window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if
(window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function
getData()
{
if(XMLHttpRequestObject)
{
XMLHttpRequestObject.open("GET",
"MyPage2.htm");
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
var doc =
document.implementation.createHTMLDocument("MyDocument");
doc.documentElement.innerHTML =
XMLHttpRequestObject.responseText;
alert(doc.getElementById("MyFirstParagraph").innerHTML);
}
}
XMLHttpRequestObject.send(null);
}
}
Il documento MyPage2.htm cui fa
riferimento la routine (vedi istruzioni evidenziate in colore) ha il seguente
contenuto:
<html>
<head>
</head>
<body>
<p
id="MyFirstParagraph">Questo e' il primo paragrafo</p>
<p
id="MySecondParagraph">Questo e' il secondo paragrafo</p>
</body>
</html>
Nell'alert box comparirà la stringa "Questo
è il primo paragrafo". Anche gli altri metodi DOM javascript sono
applicabili a questo oggetto, come ad esempio l'istruzione:
alert(doc.getElementById("MyFirstParagraph").attributes.id.value);
oppure l'istruzione:
alert(doc.getElementsByTagName("p")[0].innerHTML);
Quarto sistema: caricare la
pagina in un tag <iframe> e leggerla (non funziona)
Ormai tutti i browser supportano il tag <iframe>, ottimizzato per
il caricamento di elementi da altre pagine web. La sintassi per utilizzarlo è
molto semplice:
<iframe src="http://www.w3schools.com"></iframe>
In questo caso si è caricata nella
finestra la HomePage del consorzio w3schools. Una serie di attributi opzionali
consente di settare la posizione, la larghezza della finestra, ecc. Per i
nostri scopi l'iframe dovrebbe essere nascosto. Ma in realtà questa soluzione
non funziona, perché quando si va a far eseguire l'istruzione:
alert(document.getElementById("MyIframe").childNodes.length);
Si ottiene il messaggio "0":
cioè non ci sono nodi nel contenuto di "MyIframe".
ulteriore
documentazione consultabile:
https://developer.mozilla.org/en-US/Add-ons/Code_snippets/HTML_to_DOM : contiene una descrizione del metodo document.implementation.createHTMLDocument,
nel paragrafo "Parsing Complete HTML to DOM"
❍ Come ottenere l'esatto
indirizzo di una pagina internet che si vuole utilizzare con javascript
Per poter utilizzare elementi di una
pagina internet con javascript (vedi l'articolo sui vari modi di farlo) occorre
disporre dell'indirizzo completo
della pagina web. L'indirizzo andrebbe sempre digitato preceduto da "http://www.", per
evitare malfunzionamenti di routines javascript o jQuery, e non semplicemente
preceduto dal solo "www." (ad esempio questo indirizzamento non funziona
con la funzione .load() di jQuery). Indirizzi come: "www.usatoday.com" o "www.flowersgallery.com"
sono solo indirizzi di directory
all'interno delle quali si trova il file-indice che viene inviato al browser,
non di rado annidato in sottodirectory.
I server web sono configurati in modo da
inviare una pagina di default ogni volta che un browser richiede un nome di directory.
Per esempio, se il vostro link è "www.example.com/about/", un tipico server web cercherà in quella
directory un file chiamato "index.html". Normalmente, una volta caricato questo file,
esso non sarà mostrato nella barra degli indirizzi, che continuerà a mostrare
la stringa sopra indicata.
Purtroppo, normalmente i server web
disabilitano il listing della directory, che quindi non può essere ottenuto con
nessun tipo di richiesta ajax o di altro tipo. In questi casi, si può solo
tirare ad indovinare, provando i nomi più comuni, come "index.htm", "index.html", "index.php", "index.asp", ma se
questo non funziona, non c'è modo di ottenere l'esatto indirizzo della pagina
web.
Un modo di ottenerlo può essere l'utilizzo
di GNU Wget, un programma open source
che consente il download di files dai
server usando HTTP, HTTPS, FTP, e che può essere usato per ottenere il listato
della directory. Caratteristiche simili ha il programma cURL.
❍ Una pagina per sperimentare
semplice codice javascript, jQuery, ajax, php
Aprite la pagina Experiments_1.htm
, provate a cliccare sui vari elementi e visualizzatene il codice con l'opzione
"visualizza sorgente pagina" del tasto destro del mouse (per Explorer
l'opzione è "HTML").
❍ Alcune cose che con ajax non si
possono fare, anche se apparentemente sembrerebbero semplici
Per quanto questo possa lasciare
increduli, è praticamente impossibile esportare i valori che si ottengono entro
una routine che utilizza l'oggetto XMLHttpRequest, del tipo:
<script
language = "javascript">
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
function getData()
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET",
"MiaPagina.php");
XMLHttpRequestObject.onreadystatechange =
function()
{
if
(XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status ==
200) {
document.Message=
XMLHttpRequestObject.responseText;
}
}
XMLHttpRequestObject.send(null);
}
}
</script>
La funzione function getData() si collega al
documento MiaPagina.php presente sul server e riceve in risposta la stringa XMLHttpRequestObject.responseText, che provvede a memorizzare nella variabile globale document.Message.
Ma
questo codice non funziona, nel senso che
nessuna routine javascript esterna alla funzione getData() sarà in grado di leggere e utilizzare il contenuto
della variabile document.Message.
Il contenuto è stato acquisito con
successo (per verificarlo è sufficiente scrivere, entro la routine getData(), l'istruzione alert(document.Message)); ma non è visibile all'esterno.
In altre parole: tutto il codice che fa
riferimento al contenuto di document.Message deve essere scritto entro la routine getData().
Provare per credere. Impiegate tutti i
trucchi che vi vengono in mente (memorizzazione entro un tag, richiamo di una
funzione esterna a cui passare il valore e che lo scrive in una qualche parte,
ecc.), niente funzionerà.
E questo è vero sia per javascript sia per
una libreria sofisticata come jQuery
❍ Cos'è un documento XML e come
lo si può gestire
Un documento XML è simile ad un documento
HTML, nel senso che entrambi sono strutturati mediante tag, meglio detti nel
caso di XML nodi o elementi:
<?xml
version="1.0">
<friends>
<friend>
<FirstName>Cary</FirstName>
<LastName>Grant</LastName>
</friend>
<friend>
<FirstName>Myrna</FirstName>
<LastName>Loy</LastName>
</friend>
<friend>
<FirstName>James</FirstName>
<LastName>Stewart</LastName>
</friend>
</friends>
A differenza di un documento HTML, in cui
il tipo di elementi o tag è rigidamente predefinito, in un documento XML si può
attribuire ad un tag un nome qualsiasi, come si vede sopra.
Tutti i documenti XML iniziano con una
dichiarazione del tipo:
<?xml
version="1.0">
E' necessario indicare la versione. Una
versione comunemente usata è "1.0", ma si può indicare anche
"1.1". Gli altri argomenti che possono essere inclusi sono standalone ed encoding, come ad esempio:
<?xml
version="1.0" standalone="yes" encoding="UTF-8">
Standalone = "yes" indica che indica che il documento
non include altri documenti XML.
Encoding = "UTF-8" stabilisce che si intende
utilizzare il set di caratteri UTF-8, che è quello utilizzato da WordPad e
altri standard editor di testo.
I nomi dei tag non possono iniziare con
numeri, non possono contenere spazi o alcuni caratteri non consentiti come
virgolette.
Tutti i documenti XML necessitano di un document element, cioè un singolo nodo o
elemento che contiene tutti gli altri nodi o elementi del documento. Nell'esempio
sottostante il document element è il
nodo <colors>
del file colors.xml:
<?xml
version="1.0">
<colors>
<color>red<color>
<color>green</color>
<color>blue</color>
</colors>
Ogni altro elemento deve essere contenuto
nel document element.
Possono esistere, come in HTML, empty elements, cioè elementi costituiti
da un solo tag, che quindi non racchiudono alcun contenuto (il tag <img> in HTML è uno di
questi). In XML un empty element deve
terminare sempre con lo slash:
<evening/>
Questi elementi sono un'alternativa ad un nodo
contenente l'informazione:
<party>
<evening/>
…
…
</party>
equivale a:
<party>
<time>evening</time>
…
…
</party>
Gli elementi XML possono anche includere attributi (che sono anch'essi
considerati nodi):
<party
type="winter">
In XML ad un attributo va sempre dato un valore.
Entro un nodo XML si può inserire del
testo:
<PartyTitle>Snow
Day</PartyTitle>
I nodi possono essere di vario tipo, e la
proprietà nodeType restituisce un numero corrispondente:
Tipo di nodo |
nodeType |
Element node |
1 |
Attribute node |
2 |
Text Node |
3 |
CDATA (XML character data) section node |
4 |
XML entity reference node |
5 |
XML entity node |
6 |
XML processing instruction node |
7 |
XML comment node |
8 |
XML document node |
9 |
XML DTD node |
10 |
XML document fragment node |
11 |
XML notation node |
12 |
Un file XML può essere caricato in memoria
sia dall'hard-disk del computer client
che dall'hard-disk del server.
Per caricarlo dal server utilizziamo Ajax
(il codice sarà commentato in seguito):
var
XMLHttpRequestObject = false;
if
(window.XMLHttpRequest)
{
XMLHttpRequestObject = new XMLHttpRequest();
}
else if
(window.ActiveXObject)
{
XMLHttpRequestObject = new
ActiveXObject("Microsoft.XMLHTTP");
}
if(XMLHttpRequestObject)
{
XMLHttpRequestObject.open("GET",
"colors.xml", true);
XMLHttpRequestObject.onreadystatechange =
function()
{
if (XMLHttpRequestObject.readyState == 4
&& XMLHttpRequestObject.status == 200)
{
var sourceDocument =
XMLHttpRequestObject.responseXML;
var xmlDocument =
sourceDocument.documentElement;
alert("Il nome del nodo principale è
" + xmlDocument.nodeName);
alert("Il nodo principale contiene
" + xmlDocument.childNodes.length);
}
}
XMLHttpRequestObject.send(null);
}
Il codice eseguito dopo il caricamento del
documento fa apparire un box di dialogo con la stringa "colors", che
è il nome del nodo documentElement, e
successivamente un altro box con la stringa "3", che è il numero dei
tag <color>
contenuti nel documentElement.
Per caricare invece un documento presente
sull'hard-disk del computer client si
usa l'istruzione:
xmlSource=loadXMLDoc("colors.xml");
Supponiamo di avere un documento XML come
il seguente:
<?xml
version="1.0"?>
<parties>
<party type="winter">
<party_title>Snow
Day</party_title>
<party_number>63</party_number>
<subject>No school
today!</subject>
<date>2/2/2009</date>
<people>
<person
attendence="present">
<first_name>Ralph</first_name>
<last_name>Kramden</last_name>
</person>
<person
attendance="absent">
<first_name>Alice</first_name>
<last_name>Kramden</last_name>
</person>
<person
attendance="present">
<first_name>Ed</first_name>
<last_name>Norton</last_name>
</person>
</people>
</party>
</parties>
Supponiamo di aver già acquisito il document element del file party.xml
mediante le istruzioni:
xmlSource=loadXMLDoc("party.xml");
xmlDocument
= xmlSource.documentElement;
Vediamo ora come fare per estrarre il
cognome del terzo ospite del party (Ed Norton) dal documento party.xml. Per far questo dobbiamo
conoscere gli oggetti che javacript mette a disposizione per acquisire i nodi:
Oggetto
javascript |
Descrizione |
element.childNodes |
Array
che contiene tutti i nodi di livello immediatamente inferiore a quello del
nodo element, ed inclusi in esso (nel
caso dell’elemento document element
i childnodes sono costituiti dal solo nodo <party>, mentre nel caso
dell’elemento <people> i childnodes sono i nodi <person>) |
element.firstChild |
Il
primo dei childnodes del nodo element, secondo la disposizioone che hanno nel
documento. (nel
caso dell’elemento <people> il firstChld è il nodo <person> di
Ralph Kramer) |
element.lastChild |
L’ultimo
dei childnodes del nodo element, secondo la disposizioone che hanno nel
documento. (nel
caso dell’elemento <people> il lastChld è il nodo <person> di Ed
Norton) |
element.nextSibling |
Il
successivo nodo di pari livello rispettto al nodo element (nel
caso dell’elemento <date> il nextSibling è il nodo <people>) |
element.previousSibling |
Il
nodo precedente tra quelli di pari grado rispetto al nodo element (nel
caso dell’elemento <people> il previousSibling è il nodo <date>) |
Con queste premesse, per ottenere la
stringa “Norton” occorre utilizzare l’espressione:
xmlDocument.documentElement.firstChild.lastChild.lastChild.lastChild.firstChild.nodeValue
infatti si hanno le seguenti
corrispondenze:
xmlDocument.documentElement.firstChild |
nodo
<party> |
xmlDocument.documentElement.firstChild.lastsChild |
nodo
<people> |
xmlDocument.documentElement.firstChild.lastChild.lastChild |
nodo
<person> di Ed Norton |
xmlDocument.documentElement.firstChild.lastChild.lastChild.lastChild |
nodo
<last_name> di Ed Norton |
xmlDocument.documentElement.firstChild.lastChild.lastChild.lastChild.firstChild |
nodo
di testo costituito dalla stringa “Norton” |
La proprietà nodeValue consente di
acquisire il contenuto dell’oggetto, che non può essere manipolato come dato o
mostrato come tale nella pagina web (se si provasse a mettere l’espressione senza
.nodeValue in un alert box
il valore sarebbe “undefined”, il tipico risultato che si ottienne trattando un
oggetto come un dato),
Equivalentemente, utilizzando l’oggetto nextSibling si può ottenere
la stringa “Norton” con l’espressione:
xmlDocument.documentElement.firstChild.lastChild.firstChild.nextSibling.nextSibling.lastChild.firstChild.nodeValue
Proviamo ora un'altra via per acquisire la
stringa "Norton", utilizzando l'array creato mediante
getElementsByTagName:
var
LastNames = xmlDocument.getElementsByTagName("last_name");
var
EdNortonLastName = LastNames[2].firstChild.nodeValue;
(si tenga presente che la numerazione
dell'array inizia con "0" e non con "1")
Cerchiamo ora di acquisire gli attributi
di un nodo, ad esempio l'attributo "attendance" di Ralph Kramden:
var
RalphKramdenAttendance =
xmlDocument.getElementsByTagName("person")[0].attributes.getNamedItem("attendance");
Un utile trucco per individuare uno
specifico nodo che ci interessa è quello di creare un loop che scorra tutti i
nodi e verifichi una condizione che ci consenta di identificare il nodo che ci
interessa. Supponiamo di voler trovare lo stesso dato dell'esempio precedente,
cioè la presenza di Ralph Kramden. Carichiamo party.xml in memoria ed
acquisiamo il document element con le
istruzioni:
xmlSource=loadXMLDoc("party.xml");
xmlDocument
= xmlSource.documentElement;
Successivamente scorriamo tutti i nodi <person>
del document element, alla ricerca
del nodo di Ed Norton:
Guests =
xmlDocument.getElementsByTagName("person");
var
LoopIndex;
for(LoopIndex=0;LoopIndex<Guests.length;LoopIndex++)
{
if (Guests[LoopIndex].LastChild.nodeValue =
"Kramden")
{
RalphKramdenAttendance = Guests[LoopIndex].attributes.getNamedItem("attendance");
alert(RalphKramdenAttendance);
}
}
Ecco il riepilogo di alcune istruzioni con
cui è possibile manipolare il documento
xmlDocument.documentElement.Childnodes
xmlDocument.documentElement.Childnodes.length
xmlDocument.documentElement.Child
xmlDocument.documentElement.getElementsByTagName("colore")[0]
xmlDocument.documentElement.firstChild.nodeValue
❍ Leggere un documento XML posto
sul server e farne apparire il contenuto nella pagina web
Consideriamo la seguente pagina XMLDisplay1.htm
:
<html>
<head>
<style
type ="text/css">
.AjaxBox {
margin-left: auto;
margin-right: auto;
width:40%;
height:auto;
text-align:center;
border:1px solid black;
padding-top:10px;
padding-bottom:10px;
background-color:AliceBlue;
text-align:center;
vertical-align : center;
position : absolute;
left : 30%;
top : 100px;
}
</style>
<script
type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script
type="text/javascript">
function
DisplayXML()
{
$.get("XMLSend.php",function(xmldoc)
{
var
ArrayPoesie=xmldoc.getElementsByTagName("Testo");
var LoopIndex;
document.getElementById("Poesie").innerHTML="";
for(LoopIndex = 0;
LoopIndex<xmldoc.documentElement.childNodes.length; LoopIndex++)
{
document.getElementById("Poesie").innerHTML=document.getElementById("Poesie").innerHTML+"<p
align='center'>"+ArrayPoesie[LoopIndex].firstChild.nodeValue+"</p>";
}
},"xml");
}
</script>
</head>
<body>
<div
id="Poesie" class="AjaxBox">
<p><a
id="MyAnchor" href="#"
onclick="DisplayXML();">Clicca qui per acquisire e leggere un file
XML tramite ajax</a></p>
</div>
</body>
</html>
Il blocco di codice:
<div
id="Poesie" class="AjaxBox">
<p><a
id="MyAnchor" href="#"
onclick="DisplayXML();">Clicca qui per acquisire e leggere un file
XML tramite ajax</a></p>
</div>
crea un box nella pagina web dove
comparirà il testo delle poesie.
Il blocco di codice:
function
DisplayXML()
{
$.get("XMLSend.php",function(xmldoc)
{
var
ArrayPoesie=xmldoc.getElementsByTagName("Testo");
var LoopIndex;
document.getElementById("Poesie").innerHTML="";
for(LoopIndex = 0;
LoopIndex<xmldoc.documentElement.childNodes.length; LoopIndex++)
{
document.getElementById("Poesie").innerHTML=document.getElementById("Poesie").innerHTML+"<p
align='center'>"+ArrayPoesie[LoopIndex].firstChild.nodeValue+"</p>";
}
},"xml");
}
definisce la funzione DisplayXML() che si attiva quando si clicca sul testo posto nel
box, e vi inserisce il testo delle poesie.
Mediante l'istruzione:
$.get("XMLSend.php",function(xmldoc){...},"xml");
(dove, al posto dei puntini ci sono le
istruzioni che commenteremo) la funzione DisplayXML() apre in modo ajax (asincrono) il file XMLSend.php, che legge il file Haiku.xml e lo invia come documento XML (xmldoc):
<?php
$Haiku = simplexml_load_file('Haiku.xml');
$xmlDocument ="<?xml
version='1.0'?><dataroot>";
foreach($Haiku->children() as $item)
{
$xmlDocument=$xmlDocument."<Haiku>";
$xmlDocument=$xmlDocument."<Autore>".$item->Autore."</Autore>";
$xmlDocument=$xmlDocument."<Testo>".$item->Testo."</Testo>";
$xmlDocument=$xmlDocument."</Haiku>";
}
$xmlDocument=$xmlDocument."</dataroot>";
echo $xmlDocument;
?>
Il file Haiku.xml (e il documento xmldoc) si presenta così:
<?xml
version="1.0" encoding="UTF-8"?>
<dataroot>
<Haiku>
<Indice>1</Indice>
<Autore>Ito
Shintoku</Autore>
<Epoca>1634-1698</Epoca>
<Paese>Giappone</Paese>
<Soggetto>pioggia</Soggetto>
<Testo>pioggia:
attraversa il mio cancello un mazzo di iris</Testo>
</Haiku>
...
<Haiku>
<Indice>7</Indice>
<Autore>Konishi
Raizan</Autore>
<Epoca>1653-1716</Epoca>
<Paese>Giappone</Paese>
<Soggetto>campi
di neve</Soggetto>
<Testo>nei
campi di neve verdissimo il verde delle erbe nuove</Testo>
</Haiku>
...
<Haiku>
<Indice>10</Indice>
<Autore>Konishi
Raizan</Autore>
<Epoca>1653-1716</Epoca>
<Paese>Giappone</Paese>
<Soggetto>alzo
il capo</Soggetto>
<Testo>alzo
il capo e vedo me coricato nel freddo</Testo>
</Haiku>
</dataroot>
Torniamo alla funzione richiamata con
l'istruzione ajax:
$.get("XMLSend.php",function(xmldoc){...},"xml");
che ora ha a disposizione il documento
xmldoc, ed analizziamone le istruzioni:
{
var ArrayPoesie=xmldoc.getElementsByTagName("Testo");
var LoopIndex;
document.getElementById("Poesie").innerHTML="";
for(LoopIndex = 0;
LoopIndex<xmldoc.documentElement.childNodes.length; LoopIndex++)
{
document.getElementById("Poesie").innerHTML=document.getElementById("Poesie").innerHTML+"<p
align='center'>"+ArrayPoesie[LoopIndex].firstChild.nodeValue+"</p>";
}
L'istruzione:
xmldoc.getElementByTagName("..")
consente di creare degli array che
contengono ad esempio tutti i campi (nodi) <Soggetto>…</Soggetto>, o tutti i campi (nodi) <Autore>…</Autore>
ecc. del documento XML (xmldoc).
Nel nostro caso abbiamo creato un array
che contiene tutti i campi (nodi) <Testo>…</Testo>
var ArrayPoesie=xmldoc.getElementsByTagName("Testo");
Questo array è indicizzato in modo
numerico a partire dal numero zero. Ad esempio l'espressione:
ArrayPoesie[0]
restituisce il nodo:
<Testo>pioggia:
attraversa il mio cancello un mazzo di iris</Testo>
che
contiene la prima poesia.
La stringa contenuta nel nodo è
rappresentata dall'espressione:
ArrayPoesie[0].firstChild.nodeValue
Il codice javascript effettua un ciclo che
acquisisce una per una queste stringhe e le aggiunge al contenuto del tag
"Poesie":
for(LoopIndex = 0;
LoopIndex<xmldoc.documentElement.childNodes.length; LoopIndex++)
{
document.getElementById("Poesie").innerHTML=document.getElementById("Poesie").innerHTML+"<p
align='center'>"+ArrayPoesie[LoopIndex].firstChild.nodeValue+"</p>";
}
L'istruzione che aggiunge la nuova riga
alle precedenti è precisamente:
document.getElementById("Poesie").innerHTML=document.getElementById("Poesie").innerHTML+"<p
align='center'>"+ArrayPoesie[LoopIndex].firstChild.nodeValue+"</p>";
Ecco ora una seconda variante della
funzione DisplayXML, che, pur utilizzando la variabile xmldoc utilizza un altro
tipo di istruzioni javascript:
function
DisplayXML()
{
$.get("XMLSend.php",function(xmldoc)
{
var Poesie = xmldoc.documentElement;
var LoopIndex;
document.getElementById("Poesie").innerHTML="";
for(LoopIndex = 0;
LoopIndex<Poesie.childNodes.length; LoopIndex++)
{
document.getElementById("Poesie").innerHTML=document.getElementById("Poesie").innerHTML+"<p
align='center'>"+Poesie.childNodes[LoopIndex].lastChild.firstChild.nodeValue;+"</p>";
}
},"xml");
}
Anziché l'array
xmldoc.getElementsByTagName("Testo")
viene utilizzato l'oggetto
xmldoc.documentElement
i cui nodi rappresentano un tag <Haiku>
… </Haiku>, all'interno del quale lastChild rappresenta il tag <Testo>
… </Testo> il cui contenuto è
rappresentato da lastChild.firstChild.nodeValue, perché il testo contenuto tra i tag rappresenta a
sua volta un nodo (di testo).
Ricordate che una pagina contenente codice
php non eseguirà quel codice se il
file avrà l'estensione ".htm" anziché quella ".php"
Per forzare l'editor di WordPad o di
BloccoNote a salvare un file di testo con l'estensione che volete, dovete
virgolettarne il nome, ad esempio: "MyScript.php"
Il codice php non verrà eseguito a meno che il file che lo contiene non sia stato
caricato sul server php e richiamato da lì.
Ricordate che javascript usa due segni di uguaglianza per operare i
confronti tra stringhe o numeri, mentre usa un
solo segno solo per impostare il valore di una variabile: tenere presente
questa importante distinzione vi eviterà tempo inutile a caccia del perché il
vostro codice non funziona.
Non usate mai il bottone con type="submit" per triggerare una modifica del documento html
operata tramite una funzione javascript: questo è impossibile, perché la
pressione di questo tipo di bottone provoca
immancabilmente un refresh della pagina che annulla qualsiasi modifica apportata
con javascript. Utilizzate invece il bottone con type="button", e tutto filerà liscio.
Quando settate le dimensioni di un box
state attenti a scrivere "px" senza spazi accanto alla misura:
width : 100px
e non:
width : 100
px
che non funzionerebbe!
Quando si scrivono le istruzioni per la
lettura di un documento XML si tenga presente che purtroppo Firefox considera
eventuali caratteri usati per l’indentazione dei tag come nodi autonomi. E’
consigliabile in tal caso l’uso di una routine che rilevi se il browser è
Firefox e in caso affermativo proceda a rimuovere tutti gli spazi:
var loopIndex;
for (loopIndex = 0; loopIndex <
xml.childNodes.length; loopIndex++)
{
var currentNode = xml.childNodes[loopIndex];
if (currentNode.nodeType == 1)
{
removeWhitespace(currentNode);
}
if (((/^\s+$/.test(currentNode.nodeValue)))
&& currentNode.nodeType == 3))
{
xml.removeChild(xml.childNodes[loopIndex--]);
}
}
Cos'è un server Apache
Robin Nixon, Learning PHP, MySQL, JavaScript & CSS, O'Reilly
Brevi cenni sugli elementi più importanti di una
pagina web
<title></title> Contiene il titolo del documento web che è mostrato
nella barra/linguetta del titolo nel browser
<body></body> Contiene tutti gli elementi che appaiono nella
pagina. Gli elementi che non sono posti qui non sono visibili
<style></style> Controlla il modo di apparire e il comportamento dei
vostri elementi web
<script></script> Qui viene inserito codice javascript o di altro
linguaggio
<div></div> Molto usato come contenitore generico dove possono
essere posti gli altri tipi di tag che compaiono in <body>
<p></p>
Crea un paragrafo: prima del testo sarà inserito un ritorno a capo
</br>
Inserisce una linea vuota
<button></button> Crea un bottone che può essere collegato in evento,
in alternativa al codice: <input
type="button">
<form></form> Crea una maschera per l'immissione di dati, che
normalmente contiene elementi <input> come bottoni o caselle di testo
<input>
Crea l'elemento di un form: caselle di spunta, caselle di testo, bottoni
<table></table> Crea una tabella
Caricare una immagine in una pagina web
Il tag di una immagine ha la seguente
struttura:
<img
src="House.gif" height="30" width="30"
alt="Immagine di una casa" />
Usare files javascript esterni
Il comando per utilizzare il codice che
abbiamo inserito in un file chiamato "MyScript.js", posto nella
stessa directory della pagina web è il seguente:
<script
language="javascript" src="MyScript.js">
Se il file "MyScript.js" non è
nella stessa directory va indicato l'indirizzo completo, che può anche esserre
un URL, come nel caso della libreria jQuery:
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
Selezionare un elemento
della pagina
Se si è dotato un tag di un id, come ad
esempio:
<p
id="MyParagraph">Questo e' il mio paragrafo</p>
in javascript si può semplicemente
utilizzare l'id, per leggere/scrivere nell'elemento:
MyParagraph.innerHTML
= "Questo e' sempre il mio paragrafo";
Utilizzare la sintassi XML
per muoversi nell'oggetto document
Per muoversi nell'oggetto document, che
incorpora gli elementi della pagina html in cui è scritto il codice javascript,
è anche possibile utilizzare l'oggetto document.documentElement, che permette
di accedere ai tag visti come nodi di un documento XML con la stessa sintassi
utilizzata per tali documenti, come ad esempio:
alert(document.documentElement.childNodes.length);
alert(document.documentElement.childNodes[0].nodeName);
alert(document.documentElement.getElementsByTagName("p")[1].firstChild.nodeValue);
alert(document.documentElement.childNodes[2].firstChild.nextSibling.nextSibling.nextSibling.attributes.getNamedItem("id").value);
alert(document.getElementById("myDIV").childNodes.length);
Quando si scrive il codice per navigare in
un documento html, i tag <script> costituiscono un tag di tipo 3 (text), e occorre fare
attenzione se si sono richiamati dei files javascript esterni, che sono inclusi
nel documento e che aggiungono altri nodi alla struttura della pagina, di cui
occorre tenere conto. Uguale cautela occorre usare se nella pagina sono
inseriti automaticamente dall'Host dei contatori, come ad es. con
altervista.org, perché in tal caso si aggiungono altri nodi alla pagina.
Aprire nella pagina una
finestra in cui è visualizzata un'altra pagina internet
Ormai tutti i browser supportano il tag <iframe>, ottimizzato per
il caricamento di elementi da altre pagine web. La sintassi per utilizzarlo è
molto semplice:
<iframe src="http://www.w3schools.com"></iframe>
In questo caso si è caricata nella
finestra la HomePage del consorzio w3schools. L'effetto nella pagina web è il
seguente:
Una serie di attributi opzionali consente
di settare la posizione, la larghezza della finestra, ecc.
La funzione jQuery $(document).ready(){…} è utile
anche con semplice codice javascript
La funzione jQuery $(document).ready(){…}
è utile anche con semplice codice javascript, perché consente ad istruzioni che
fanno riferimento ad elementi che devono essere caricati, di funzionare.
Consideriamo ad esempio il seguente codice:
<html>
<head>
<script
language = "javascript">
alert(document.getElementById("MyIframe").nodeName);
</script>
</head>
<body>
<iframe
id="MyIframe" style="position:absolute;left:30%;top:35%;"
src="http://www.w3schools.com"></iframe>
</body>
</html>
Ma con la funzione $(document).ready(),
esso funzioa e genera l'alert "IFRAME":
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script
language = "javascript">
$(document).ready(function(){
alert(document.getElementById("MyIframe").nodeName);
});
</script>
</head>
<body>
<iframe
id="MyIframe" style="position:absolute;left:30%;top:35%;"
src="http://www.w3schools.com"></iframe>
</body>
</html>
La funzione setTimeout()
Consideriamo il seguente codice:
javascript
function
DisplayData(Testo)
{
var MyBox =
document.getElementById("targetDiv");
MyBox.style.color = "red";
MyBox.innerHTML = Testo;
setTimeout(attentionGetter, 500);
}
function
attentionGetter()
{
var target =
document.getElementById("targetDiv");
target.style.color = "black";
}
html
<form>
<input
type = "button" value = "Cambia il testo" onclick =
"DisplayData('Questo è il nuovo testo');">
</form>
<div
id="targetDiv">
<p>I nuovi dati appariranno qui</p>
</div>
Quando si preme il bottone, in "targetDiv" la stringa
"I nuovi dati appariranno qui" viene sostituita dalla stringa "Questo
è il nuovo testo", che per mezzo secondo apparirà colorato in rosso per
poi tornare di colore nero. Questo è ottenuto con l'istruzione:
setTimeout(attentionGetter,
500);
Che lascia passare mezzo secondo (500
millisecondi) prima di chiamare la funzione attentionGetter(), che colora di nero la stringa inserita
temporaneamente col colore rosso.
I caratteri speciali in
javascript
Una istruzione come:
<input
type = "button" value = "Cambia il testo" onclick =
"DisplayData('QUESTO E' IL NUOVO TESTO');">
non funziona, perché compare il carattere
" ' " entro la stringa che è l'argomento della funzione DisplayData().
Librerie javascript concorrenti
rispetto a jQuery
AngularJS è una libreria sviluppata da un programmatore di
Google, Miško Hevery, attualmente patrocinata da Google e distribuita come
software gratuito open source. Da una recente ricerca risulta che 7000 siti
web, su un milione testato, usano questa libreria, tra cui NBC, Walgreens, Intel, Sprint, ABC News. Non è di facile
apprendimento, e per padroneggiarne appieno le funzionalità è necessaria una
notevole esperienza di programmazione. Le statistiche delle ricerche in rete
confermano questo dato: mostrano che il numero di ricerche riguardanti
chiarimenti su Angular.js è nettamente superiore a quello delle ricerche che
riguardano javascript, jQuery o altri linguaggi del web. Rispetto ad essa
jQuery è più semplice e intuitiva. Per questo motivo non pochi programmatori
pensano che, malgrado il supporto di Google, sia destinata ad essere
abbandonata, come in passato è precisamente avvenuto con librerie molto valide
ma poco intuitive.
Backbone.js è una libreria javascript conosciuta anche come
CoffeeScript, creata dal programmatore Jeremy Ashkenas.
Prototype
Javascript Framework è una libreria
creata da Sam Stephenson nel 2005 e pensata come supporto di Ajax.
Moo
Tools è una delle più popolari
librerie javascript ed è distribuita open source con licenza del MIT.
YUI
Library (Yahoo! User Interface Library) è stata creata nel 2005 da un team
di sviluppatori Yahoo!, ma lo sviluppo attivo è cessato nel 2014, quando Yahoo!
ha annunciato l'abbandono del supporto a causa della evoluzione degli standard
javascript, del declinante interesse per larghe librerie javascript e per la
proliferazione di soluzioni server-side.
Ember.js
Knockout
Concatenabilità di jQuery
jQuery consente di concatenare i comandi
evitando di ripeterne ogni volta la parte iniziale. Ad esempio, si considerino
i seguenti comandi javascript:
var links =
$("a");
links.css(
"color", "red" );
links.bind(
"click", myFunctionPointer );
links.show(
"1000" );
links.css(
"width", "150px" );
Esso può essere sostituito da:
$("a").css({color:"red",
width:"150px"}).bind("click",
myFunctionPointer).show("1000");
Che ha la stessa leggibilità e si riduce
ad una sola riga.
I codici dei colori
Un colore, ad esempio di un bordo, può
essere indicato, in un foglio di stile, in tre modi:
border-color
: #000000;
border-color
: rgb(0,0,0);
border-color
: black;
Il terzo caso riguarda solo i colori
principali, che hanno dei nomi individuali.
ulteriore
documentazione consultabile:
http://www.w3schools.com/html/html_colors.asp : Tutorial sui colori
http://www.w3schools.com/html/html_colornames.asp : Elenco dei colori che possiedono dei nomi
individuali.