diff options
Diffstat (limited to 'files/it/web/api/xmlhttprequest/usare_xmlhttprequest/index.html')
-rw-r--r-- | files/it/web/api/xmlhttprequest/usare_xmlhttprequest/index.html | 741 |
1 files changed, 741 insertions, 0 deletions
diff --git a/files/it/web/api/xmlhttprequest/usare_xmlhttprequest/index.html b/files/it/web/api/xmlhttprequest/usare_xmlhttprequest/index.html new file mode 100644 index 0000000000..4f55ac07ff --- /dev/null +++ b/files/it/web/api/xmlhttprequest/usare_xmlhttprequest/index.html @@ -0,0 +1,741 @@ +--- +title: Usare XMLHttpRequest +slug: Web/API/XMLHttpRequest/Usare_XMLHttpRequest +translation_of: Web/API/XMLHttpRequest/Using_XMLHttpRequest +--- +<p>Per inviare una richiesta HTTP, crea un oggetto {{domxref("XMLHttpRequest")}}, apri un URL, ed invia la richiesta. Dopo che la transazione è completata, l'oggetto conterrà informazioni utili come il testo di risposta e lo <a href="/en-US/docs/HTTP/HTTP_response_codes" title="HTTP response codes">stato HTTP</a>. Questa pagina illustra alcuni dei più comuni e oscuri casi d'uso di questo potente oggetto <code>XMLHttpRequest</code>.</p> + +<pre class="brush: js">function reqListener () { + console.log(this.responseText); +} + +var oReq = new XMLHttpRequest(); +oReq.onload = reqListener; +oReq.open("GET", "http://www.example.org/example.txt"); +oReq.send();</pre> + +<h2 id="Tipi_di_Richieste">Tipi di Richieste</h2> + +<p>Una richiesta inviata con XMLHttpRequest può essere restituita in due modi, sincrona o asincrona. Il tipo di richiesta viene deciso dall'argomento opzionale <code>async</code> (il terzo argomento) che viene impostato nel metodo <a href="/en-US/docs/DOM/XMLHttpRequest#open()" title="DOM/XMLHttpRequest#open()">open()</a> di {{domxref("XMLHttpRequest.open()")}}. Se l'argomento è <code>true</code> o se non è specificato, il <code>XMLHttpRequest</code> è processato in maniera asincrona, in caso contrario è processato in maniera sincrona. Una discussione dettagliata è una dimostrazione di queste due tipologie di richieste possono essere trovate nella pagina <a href="/en-US/docs/DOM/XMLHttpRequest/Synchronous_and_Asynchronous_Requests" title="Synchronous and Asynchronous Requests">richieste sincrone ed asincrone</a>. In generale, dovresti usare raramente le richieste sincrone, se mai ne farai uso.</p> + +<div class="note"><strong>Nota:</strong> Da Gecko 30.0 {{ geckoRelease("30.0") }}, le richieste sincrone sul thread principale sono state deprecate a causa degli effetti negativi sull'esperienza utente.</div> + +<h2 id="Gestire_le_risposte">Gestire le risposte</h2> + +<p>Ci sono vari tipi di <a href="http://www.w3.org/TR/XMLHttpRequest2/#response" title="http://www.w3.org/TR/XMLHttpRequest2/#response">attributi di risposta</a> definite dallo standard W3C sul costruttore XMLHttpRequest. Questi sono in grado di fornire al client che effettua la richiesta importanti informazioni sullo stato della risposta. In alcuni casi in cui si lavora con risposte di tipo non testuale possono riguardare alcuni elementi di analisi e manipulazioni come evidenziato dai paragrafi seguenti.</p> + +<h3 id="Analizzare_e_modificare_la_proprietà_responseXML">Analizzare e modificare la proprietà <code>responseXML</code></h3> + +<p>Se si usa l'oggetto <code>XMLHttpRequest</code> per ricevere il contenuto di un documento XML remoto, la proprietà <code>responseXML</code> dell'oggetto stesso sarà assegnata a un oggetto DOM contentente un il documento XML a cui è stata effettuata una operazione di parsing. Se si lavora con tale proprietà può essere difficile analizzare e modificare tale proprietà. Di seguito sono riportate i quattro principali metodi per lavorare con tale documento XML:</p> + +<ol> + <li>Utilizzare <a href="/en-US/docs/XPath" title="XPath">XPath</a> per indirizzare (cioè puntare a) parti di esso.</li> + <li>Usare <a href="/en-US/docs/JXON" title="JXON">JXON</a> per convertire il documento in un albero JavaScript Object.</li> + <li>Effettuare il <a href="/en-US/docs/Parsing_and_serializing_XML" title="Parsing_and_serializing_XML">Parsing e la serializzazione XML</a> manualmente su stringhe e oggetti.</li> + <li>Utilizzare un <a href="/en-US/docs/XMLSerializer" title="XMLSerializer">XMLSerializer</a> per serializzare <strong>alberi DOM su stringhe o file</strong>.</li> + <li><a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp" title="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp">RegExp </a>possono essere utilizzate se si conosce sempre il contenuto del documento XML a priori. In tal caso, se si utilizzano delle espressioni regolari con coscienza dei ritorni di riga, può essere necessario o consigliato di rimuovere le interruzioni di riga. In ogni caso è sempre sconsigliato utilizzare questo metodo e di considerarlo solo come "ultima spiaggia" in quanto se il documento XML dovesse cambiare anche in modo irrisorio questa metodologia potrebbe fallire.</li> +</ol> + +<h3 id="Analizzare_e_manipolare_una_proprietà_responseText_contenentente_un_documento_HTML">Analizzare e manipolare una proprietà <code>responseText</code> contenentente un documento HTML</h3> + +<div class="note"><strong>Nota:</strong> La W3C <a href="http://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html">XMLHttpRequest</a> specification permette il parse del codice HTML tramite la proprietà <code>XMLHttpRequest.responseXML</code>. SI legga l'articolo a riguardo <a href="/en-US/docs/HTML_in_XMLHttpRequest" title="HTML_in_XMLHttpRequest">HTML in XMLHttpRequest</a> per dettagli.</div> + +<p>Se si utilizza l'oggetto <code>XMLHttpRequest</code> per ottenere il contenuto di una pagina HTML remota, la proprietà <code>responseText</code> conterrà un amalgama di tutti i tag HTML. Ciò può essere difficile da manipolare e analizzare. Ci sono principalmente tre divere metodologie per analizzare questo insieme:</p> + +<ol> + <li>Utilizzare la proprietà <code>XMLHttpRequest.responseXML</code>.</li> + <li>Iniettare il contenuto nel corpo di un <a href="/en-US/docs/Web/API/DocumentFragment">document fragment</a> attraverso la proprietà <code>fragment.body.innerHTML</code> e navigare il codice DOM del fragment.</li> + <li>Ancora una volta <a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp" title="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/regexp">RegExp </a>possono essere utlizzate se si conosce sempre il contenuto della risposta HTML. Questo metodo è, comuqnue, sconsigliato perchè anche una piccola modifica del codice HTML sorgente potrebbe protare questa metodologia a fallire.</li> +</ol> + +<h2 id="Gestire_dati_binari">Gestire dati binari</h2> + +<p>Nonostante l'oggetto <code>XMLHttpRequest</code> è principalmente utilizzato per ricevere e inviare dati testuali, può essere utilizzato per inviare e ricevere dati dal contenuto binario. Esistono svariati metodi ben testati per fare sì che l'oggetto in questione invii dati binari. Questi metodo prevedono l'utilizzo del metodo <code>.overrideMimeType(...)</code> sull'oggetto.</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); +oReq.open("GET", url, true); +// riceve dei dati non porcessati come una stringa binaria +oReq.overrideMimeType("text/plain; charset=x-user-defined"); +/* ... */ +</pre> + +<p>La XMLHttpRequest Level 2 Specification aggiunge un nuovo <a href="http://www.w3.org/TR/XMLHttpRequest2/#the-responsetype-attribute" title="http://www.w3.org/TR/XMLHttpRequest2/#the-responsetype-attribute">attributo responseType</a> che permette di inviare e ricevere dati binari in modo molto più semplice.</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); + +oReq.open("GET", url, true); +oReq.responseType = "arraybuffer"; +oReq.onload = function(e) { + var arraybuffer = oReq.response; // non responseText + /* ... */ +} +oReq.send(); +</pre> + +<p>Per più esempi si veda la pagina <a href="/en-US/docs/DOM/XMLHttpRequest/Sending_and_Receiving_Binary_Data" title="DOM/XMLHttpRequest/Sending_and_Receiving_Binary_Data">Sending and Receiving Binary Data</a>.</p> + +<h2 id="Monitoraggio_del_progresso">Monitoraggio del progresso</h2> + +<p>L'oggetto <code>XMLHttpRequest</code> fornisce la possibilità di ascoltare svariati eventi che possono occorrere mentre la richiesta è processata. Questo inclulde periodici aggiornamenti sul progresso, notificazione di errori e così via.</p> + +<p>Il supporto agli eventi di monitoraggio del progresso DOM dell'oggetto <code>XMLHttpRequest</code> ripetta le API <a href="http://dev.w3.org/2006/webapi/progress/Progress.html" title="http://dev.w3.org/2006/webapi/progress/Progress.html">specification progress events</a>: tali eventi implementano l'interfaccia {{domxref("ProgressEvent")}}.</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); + +oReq.addEventListener("progress", updateProgress, false); +oReq.addEventListener("load", transferComplete, false); +oReq.addEventListener("error", transferFailed, false); +oReq.addEventListener("abort", transferCanceled, false); + +oReq.open(); + +// ... + +// progress on transfers from the server to the client (downloads) +function updateProgress (oEvent) { + if (oEvent.lengthComputable) { + var percentComplete = oEvent.loaded / oEvent.total; + // ... + } else { + // Impossibile elaborare il progresso perche' non si conosce la grandezza totale + } +} + +function transferComplete(evt) { + alert("Trasferimento completato!"); +} + +function transferFailed(evt) { + alert("E' avvenuto un errore nel trasferimento"); +} + +function transferCanceled(evt) { + alert("Il trasferimento è stato cancellato dall'utente"); +}</pre> + +<p>Le linee 3-6 aggiungono degli event listener per i vari eventi che sono inviati mentre si performa un trasferimento di dati con l'oggetto <code>XMLHttpRequest</code>.</p> + +<div class="note"><strong>Nota:</strong> Quando si assegnano degli event listeners è necessario farlo prima di chiamare il metodo <code>open()</code> sulla richiesta. Se ciò non viene effettuato gli eventi non vengono inviati.</div> + +<p>L'event handler per il progresso, specificato dalla funzione <code>updateProgress()</code> in questo esempio, riceve il numero totale di byte da trasferire e il numero di byte trasferiti finora nei campi <code>total</code> e <code>loaded</code> rispettivamente. In ogni caso, se il campo <code>lengthComputable</code> risulta falsa, la lunghezza totale risulta sconosciuta e sarà riportata come zero.</p> + +<p>Gli eventi di progresso esistono sia per il download che per l'upload. Gli eventi di download sono notificati sull'oggetto <code>XMLHttpRequest</code> stesso, come indicato dall'esempio sopra. Quelli di upload, invece, sono notificati sull'attributo <code>XMLHttpRequest.upload</code> come mostrato sotto:</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); + +oReq.upload.addEventListener("progress", updateProgress, false); +oReq.upload.addEventListener("load", transferComplete, false); +oReq.upload.addEventListener("error", transferFailed, false); +oReq.upload.addEventListener("abort", transferCanceled, false); + +oReq.open(); +</pre> + +<div class="note"><strong>Nota:</strong> Gli eventi di progresso non sono disponibili per il protocollo <code>file://</code>.</div> + +<div class="note"><strong>Nota</strong>: Correntemente ci sono dei bug aperti per gli eventi di progresso che affliggono la versione 25 di Firefox su <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=908375">OS X</a> e <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=786953">Linux</a>.</div> + +<div class="note"> +<p><strong>Nota:</strong> A partire da {{Gecko("9.0")}}, gli eventi di progresso possono essere lanciati per ogni parte di dato ricevuta, inclusa l'ultima parte dove l'ultimo pacchetto è ricevuto e la connesione chiusa prima che l'evento di progresso sia notificato. In questo caso l'evento di progresso è notificato automaticamente quando occorre l'evento di "load" per tale pacchetto. Questo permette di creare un monitoraggio affidabile solamente osservando gli eventi di progresso.</p> +</div> + +<div class="note"> +<p><strong>Nota:</strong> A partire da {{Gecko("12.0")}}, se l'evento di progresso è chiamato con un <code>responseType</code> di tipo <code>moz-blob</code>, il valore di risposta sarà un {{domxref("Blob")}} contenente i dati ricevuti fino a quel punto.</p> +</div> + +<p>Si puà anche rilevare tutti e tre le tipologie di terminazione del caricamento(<code>abort</code>, <code>load</code> o <code>error</code>) utilizzando l'evento <code>loadend</code>:</p> + +<pre class="brush:js">req.addEventListener("loadend", loadEnd, false); + +function loadEnd(e) { + alert("Trasferimento terminato (anche se non sappiamo come)."); +} +</pre> + +<p>Si noti che non c'è modo di essere sicuri di conoscere con le informazioni ricevute dall'evento <code>loadend</code> quali condizioni hanno causato il termine dell'operazione. In ogni caso si può usare questo per gestire operazioni che devono essere eseguite al termine del trasferimento.</p> + +<h2 id="Inviare_form_e_caricare_file">Inviare form e caricare file</h2> + +<p>Istanze di un oggetto <code>XMLHttpRequest</code> possono essere usate per inviare form in principalmente due modi:</p> + +<ul> + <li>utilizzando AJAX</li> + <li>utilizzando le API fornite dall'oggetto <a href="/en-US/docs/DOM/XMLHttpRequest/FormData" title="DOM/XMLHttpRequest/FormData"><code>FormData</code></a></li> +</ul> + +<p>Il <strong>secondo modo</strong> (utilizzando l'oggetto <code>FormData</code>) è il più semplice e veloce, ma ha lo svantaggio che i dati raccolto non possono essere <a href="/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify" title="/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify">trasformati in stringa</a>.<br> + Il<strong> primo modo</strong>, invece, è più complesso, ma è anche in cambio più potente e flessibile.</p> + +<h3 id="Usando_loggetto_XMLHttpRequest">Usando l'oggetto <code>XMLHttpRequest</code></h3> + +<p>Inviare form senza le API dell'oggetto <a href="/en-US/docs/DOM/XMLHttpRequest/FormData" title="DOM/XMLHttpRequest/FormData"><code>FormData</code></a> non richiede l'utilizzo di altre API tranne nel caso di <a href="/en-US/docs/DOM/FileReader" title="/en-US/docs/DOM/FileReader"><code>FileReader</code></a> nel caso <strong>si voglia caricare più di un file</strong>.</p> + +<h4 id="Una_breve_introduzione_del_metodo_submit">Una breve introduzione del metodo submit</h4> + +<p>Un html {{ HTMLElement("form") }} può essere inviata in quattro possibili modi:</p> + +<ul> + <li>utilizzando il metodo <code>POST</code> e assegnando all'attributo <code>enctype</code> il valore <code>application/x-www-form-urlencoded</code> (default);</li> + <li>utilizzando il metodo <code>POST</code> e assegnando all'attributo <code>enctype</code> il valore <code>text/plain</code>;</li> + <li>utilizzando il metodo <code>POST</code> e assegnando all'attributo <code>enctype</code> il valore <code>multipart/form-data</code>;</li> + <li>utilizzando il metodo <code>GET</code> (in tal caso l'attributo <code>enctype</code> sarà ignorato).</li> +</ul> + +<p>Ora, si consideri di inviare una form contenente solo due campi, chiamati <code>foo</code> e <code>baz</code>. Se si sta utilizzando il metodo <code>POST</code> il server riceverà una stringa simile a una delle seguenti tre linee a seconda del tipo di encoding utilizzato:</p> + +<ul> + <li> + <p>Metodo: <code>POST</code>; Encoding type: <code>application/x-www-form-urlencoded</code> (default):</p> + + <pre>Content-Type: application/x-www-form-urlencoded + +foo=bar&baz=The+first+line.&#37;0D%0AThe+second+line.%0D%0A</pre> + </li> + <li> + <p>Metodo: <code>POST</code>; Encoding type: <code>text/plain</code>:</p> + + <pre>Content-Type: text/plain + +foo=bar +baz=The first line. +The second line.</pre> + </li> + <li> + <p>Metodo: <code>POST</code>; Encoding type: <code>multipart/form-data</code>:</p> + + <pre style="height: 100px; overflow: auto;">Content-Type: multipart/form-data; boundary=---------------------------314911788813839 + +-----------------------------314911788813839 +Content-Disposition: form-data; name="foo" + +bar +-----------------------------314911788813839 +Content-Disposition: form-data; name="baz" + +The first line. +The second line. + +-----------------------------314911788813839--</pre> + </li> +</ul> + +<p>Invece, se si utilizza un metodo <code>GET</code> una stringa simile alla seguente sarà semplicemente aggiunta all'URL:</p> + +<pre>?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.</pre> + +<h4 id="Un_piccolo_framwork_vanilla">Un piccolo framwork vanilla</h4> + +<p>Tutte queste cose sono eseguite automaticamente dal web browser ogni volta che si esegue il submit di una {{ HTMLElement("form") }}. Ma se si vuole fare lo stesso usando JavaScript bisogna istruire l'interprete su <em>tutte</em> le operazioni da eseguire. Inviare delle form in AJAX <em>puro</em> risulta troppo complesso per essere spiegato qui; per questa ragione abbiamo creato un <strong>framework completo (ma comunque puramente didattico)</strong> che possa essere usato in tutti e quattro i metodi di submit e anche per caricare dei file.</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: html"><!doctype html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<title>Sending forms with pure AJAX &ndash; MDN</title> +<script type="text/javascript"> + +"use strict"; + +/*\ +|*| +|*| :: XMLHttpRequest.prototype.sendAsBinary() Polyfill :: +|*| +|*| https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#sendAsBinary() +\*/ + +if (!XMLHttpRequest.prototype.sendAsBinary) { + XMLHttpRequest.prototype.sendAsBinary = function(sData) { + var nBytes = sData.length, ui8Data = new Uint8Array(nBytes); + for (var nIdx = 0; nIdx < nBytes; nIdx++) { + ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff; + } + /* send as ArrayBufferView...: */ + this.send(ui8Data); + /* ...or as ArrayBuffer (legacy)...: this.send(ui8Data.buffer); */ + }; +} + +/*\ +|*| +|*| :: AJAX Form Submit Framework :: +|*| +|*| https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest +|*| +|*| This framework is released under the GNU Public License, version 3 or later. +|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html +|*| +|*| Syntax: +|*| +|*| AJAXSubmit(HTMLFormElement); +\*/ + +var AJAXSubmit = (function () { + + function ajaxSuccess () { + /* console.log("AJAXSubmit - Success!"); */ + alert(this.responseText); + /* you can get the serialized data through the "submittedData" custom property: */ + /* alert(JSON.stringify(this.submittedData)); */ + } + + function submitData (oData) { + /* the AJAX request... */ + var oAjaxReq = new XMLHttpRequest(); + oAjaxReq.submittedData = oData; + oAjaxReq.onload = ajaxSuccess; + if (oData.technique === 0) { + /* method is GET */ + oAjaxReq.open("get", oData.receiver.replace(/(?:\?.*)?$/, oData.segments.length > 0 ? "?" + oData.segments.join("&") : ""), true); + oAjaxReq.send(null); + } else { + /* method is POST */ + oAjaxReq.open("post", oData.receiver, true); + if (oData.technique === 3) { + /* enctype is multipart/form-data */ + var sBoundary = "---------------------------" + Date.now().toString(16); + oAjaxReq.setRequestHeader("Content-Type", "multipart\/form-data; boundary=" + sBoundary); + oAjaxReq.sendAsBinary("--" + sBoundary + "\r\n" + oData.segments.join("--" + sBoundary + "\r\n") + "--" + sBoundary + "--\r\n"); + } else { + /* enctype is application/x-www-form-urlencoded or text/plain */ + oAjaxReq.setRequestHeader("Content-Type", oData.contentType); + oAjaxReq.send(oData.segments.join(oData.technique === 2 ? "\r\n" : "&")); + } + } + } + + function processStatus (oData) { + if (oData.status > 0) { return; } + /* the form is now totally serialized! do something before sending it to the server... */ + /* doSomething(oData); */ + /* console.log("AJAXSubmit - The form is now serialized. Submitting..."); */ + submitData (oData); + } + + function pushSegment (oFREvt) { + this.owner.segments[this.segmentIdx] += oFREvt.target.result + "\r\n"; + this.owner.status--; + processStatus(this.owner); + } + + function plainEscape (sText) { + /* how should I treat a text/plain form encoding? what characters are not allowed? this is what I suppose...: */ + /* "4\3\7 - Einstein said E=mc2" ----> "4\\3\\7\ -\ Einstein\ said\ E\=mc2" */ + return sText.replace(/[\s\=\\]/g, "\\$&"); + } + + function SubmitRequest (oTarget) { + var nFile, sFieldType, oField, oSegmReq, oFile, bIsPost = oTarget.method.toLowerCase() === "post"; + /* console.log("AJAXSubmit - Serializing form..."); */ + this.contentType = bIsPost && oTarget.enctype ? oTarget.enctype : "application\/x-www-form-urlencoded"; + this.technique = bIsPost ? this.contentType === "multipart\/form-data" ? 3 : this.contentType === "text\/plain" ? 2 : 1 : 0; + this.receiver = oTarget.action; + this.status = 0; + this.segments = []; + var fFilter = this.technique === 2 ? plainEscape : escape; + for (var nItem = 0; nItem < oTarget.elements.length; nItem++) { + oField = oTarget.elements[nItem]; + if (!oField.hasAttribute("name")) { continue; } + sFieldType = oField.nodeName.toUpperCase() === "INPUT" ? oField.getAttribute("type").toUpperCase() : "TEXT"; + if (sFieldType === "FILE" && oField.files.length > 0) { + if (this.technique === 3) { + /* enctype is multipart/form-data */ + for (nFile = 0; nFile < oField.files.length; nFile++) { + oFile = oField.files[nFile]; + oSegmReq = new FileReader(); + /* (custom properties:) */ + oSegmReq.segmentIdx = this.segments.length; + oSegmReq.owner = this; + /* (end of custom properties) */ + oSegmReq.onload = pushSegment; + this.segments.push("Content-Disposition: form-data; name=\"" + oField.name + "\"; filename=\""+ oFile.name + "\"\r\nContent-Type: " + oFile.type + "\r\n\r\n"); + this.status++; + oSegmReq.readAsBinaryString(oFile); + } + } else { + /* enctype is application/x-www-form-urlencoded or text/plain or method is GET: files will not be sent! */ + for (nFile = 0; nFile < oField.files.length; this.segments.push(fFilter(oField.name) + "=" + fFilter(oField.files[nFile++].name))); + } + } else if ((sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") || oField.checked) { + /* field type is not FILE or is FILE but is empty */ + this.segments.push( + this.technique === 3 ? /* enctype is multipart/form-data */ + "Content-Disposition: form-data; name=\"" + oField.name + "\"\r\n\r\n" + oField.value + "\r\n" + : /* enctype is application/x-www-form-urlencoded or text/plain or method is GET */ + fFilter(oField.name) + "=" + fFilter(oField.value) + ); + } + } + processStatus(this); + } + + return function (oFormElement) { + if (!oFormElement.action) { return; } + new SubmitRequest(oFormElement); + }; + +})(); + +</script> +</head> +<body> + +<h1>Sending forms with pure AJAX</h1> + +<h2>Using the GET method</h2> + +<form action="register.php" method="get" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h2>Using the POST method</h2> +<h3>Enctype: application/x-www-form-urlencoded (default)</h3> + +<form action="register.php" method="post" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h3>Enctype: text/plain</h3> + +<form action="register.php" method="post" enctype="text/plain" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + Your name: <input type="text" name="user" /> + </p> + <p> + Your message:<br /> + <textarea name="message" cols="40" rows="8"></textarea> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h3>Enctype: multipart/form-data</h3> + +<form action="register.php" method="post" enctype="multipart/form-data" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Upload example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /><br /> + Sex: + <input id="sex_male" type="radio" name="sex" value="male" /> <label for="sex_male">Male</label> + <input id="sex_female" type="radio" name="sex" value="female" /> <label for="sex_female">Female</label><br /> + Password: <input type="password" name="secret" /><br /> + What do you prefer: + <select name="image_type"> + <option>Books</option> + <option>Cinema</option> + <option>TV</option> + </select> + </p> + <p> + Post your photos: + <input type="file" multiple name="photos[]"> + </p> + <p> + <input id="vehicle_bike" type="checkbox" name="vehicle[]" value="Bike" /> <label for="vehicle_bike">I have a bike</label><br /> + <input id="vehicle_car" type="checkbox" name="vehicle[]" value="Car" /> <label for="vehicle_car">I have a car</label> + </p> + <p> + Describe yourself:<br /> + <textarea name="description" cols="50" rows="8"></textarea> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +</body> +</html></pre> +</div> + +<p>Per testarlo, create una pagina chiamata <strong>register.php </strong>(al quale fanno riferimento gli attributi action di queste form) e inserite il seguente contenuto.</p> + +<pre class="brush: php"><?php +/* register.php */ + +header("Content-type: text/plain"); + +/* +NOTE: You should never use `print_r()` in production scripts, or +otherwise output client-submitted data without sanitizing it first. +Failing to sanitize can lead to cross-site scripting vulnerabilities. +*/ + +echo ":: data received via GET ::\n\n"; +print_r($_GET); + +echo "\n\n:: Data received via POST ::\n\n"; +print_r($_POST); + +echo "\n\n:: Data received as \"raw\" (text/plain encoding) ::\n\n"; +if (isset($HTTP_RAW_POST_DATA)) { echo $HTTP_RAW_POST_DATA; } + +echo "\n\n:: Files received ::\n\n"; +print_r($_FILES); + +</pre> + +<p>La sintassi per attivare lo script è semplicemente:</p> + +<pre class="syntaxbox">AJAXSubmit(myForm);</pre> + +<div class="note"><strong>Nota: </strong>Questo framework utilizza l'API <a href="/en-US/docs/DOM/FileReader" title="/en-US/docs/DOM/FileReader"><code>FileReader</code></a> per eseguire l'upload dei file. QUesta è una API recente e non ancora implementata nei browser come IE9 o inferiori. Per questa ragione l'upload AJAX-only è considerato una <strong>tecnica sperimentale</strong>. Se non si ha bisogno dell'upload di file binari questo framework funzionera egregiamente nella maggior parte dei browser.</div> + +<div class="note"><strong>Nota:</strong> Il modo migliore per inviare dei contenuti binari è attraverso <a href="/en-US/docs/JavaScript/Typed_arrays/ArrayBuffer" title="/en-US/docs/JavaScript/Typed_arrays/ArrayBuffer">ArrayBuffers</a> o <a href="/en-US/docs/DOM/Blob" title="/en-US/docs/DOM/Blob">Blobs</a> attraverso il metodo <a href="/en-US/docs/DOM/XMLHttpRequest#send%28%29" title="/en-US/docs/DOM/XMLHttpRequest#send()"><code>send()</code></a> e possibilmente il metodo <a href="/en-US/docs/DOM/FileReader#readAsArrayBuffer()" title="/en-US/docs/DOM/FileReader#readAsArrayBuffer()"><code>readAsArrayBuffer()</code></a> dell'API <a href="/en-US/docs/DOM/FileReader" title="/en-US/docs/DOM/FileReader"><code>FileReader</code></a>. Ma, siccome l'obiettivo di questo script è di fuonzionare con dei dati <a href="/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify" title="/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify">stringifiabli</a>, si è usato il metodo <a href="/en-US/docs/DOM/XMLHttpRequest#sendAsBinary%28%29" title="/en-US/docs/DOM/XMLHttpRequest#sendAsBinary()"><code>sendAsBinary()</code></a> assieme al metodo <a href="/en-US/docs/DOM/FileReader#readAsBinaryString%28%29" title="/en-US/docs/DOM/FileReader#readAsBinaryString()"><code>readAsBinaryString()</code></a> delle API <a href="/en-US/docs/DOM/FileReader" title="/en-US/docs/DOM/FileReader"><code>FileReader</code></a>. Per questo, lo script sopra funziona sono quando si stanno gestendo file di piccole dimensioni. Se non si intende caricare del contenuto binario, considerare anche l'utilizzo delle API <a href="/en-US/docs/DOM/XMLHttpRequest/FormData" title="DOM/XMLHttpRequest/FormData"><code>FormData</code></a>.</div> + +<h3 id="Usare_oggetti_FormData">Usare oggetti FormData</h3> + +<p>Il costruttore <a href="/en-US/docs/DOM/XMLHttpRequest/FormData" title="DOM/XMLHttpRequest/FormData"><code>FormData</code></a> permette di compliare una serie di coppie chiave/valore da inviare utilizzando una <code>XMLHttpRequest</code>. Si utilizza principalmente per inviare dati in una form, ma può essere usato indipendentemente dalle form per inviare dei dati con chiavi. I dati trasmessi sono gli stessi del formato utilizzato dal metodo <code>submit()</code> che le form usano per inviare i dati se il tipo encoding indicato è "multipart/form-data". Gli oggetti FormData possono essere utilizzati in uno svariato numero possibile con una XMLHttpRequest. Per esempi o speigazioni di come utilizzare una FormData con XMLHttpRequest si veda la pagina <a href="/en-US/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects" title="Using FormData Objects">Usare l'oggetto FormData</a>. Per fini didattici di seguito una traduzione dell'<strong><a href="#A_little_vanilla_framework" title="#A_little_vanilla_framework">esempio precedente</a> modificato per accettare l'API delle <code>FormData</code></strong>. Si noti la brevità del codice.</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: html"><!doctype html> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<title>Sending forms with FormData &ndash; MDN</title> +<script type="text/javascript"> +"use strict"; + +function ajaxSuccess () { + alert(this.responseText); +} + +function AJAXSubmit (oFormElement) { + if (!oFormElement.action) { return; } + var oReq = new XMLHttpRequest(); + oReq.onload = ajaxSuccess; + if (oFormElement.method.toLowerCase() === "post") { + oReq.open("post", oFormElement.action, true); + oReq.send(new FormData(oFormElement)); + } else { + var oField, sFieldType, nFile, sSearch = ""; + for (var nItem = 0; nItem < oFormElement.elements.length; nItem++) { + oField = oFormElement.elements[nItem]; + if (!oField.hasAttribute("name")) { continue; } + sFieldType = oField.nodeName.toUpperCase() === "INPUT" ? oField.getAttribute("type").toUpperCase() : "TEXT"; + if (sFieldType === "FILE") { + for (nFile = 0; nFile < oField.files.length; sSearch += "&" + escape(oField.name) + "=" + escape(oField.files[nFile++].name)); + } else if ((sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") || oField.checked) { + sSearch += "&" + escape(oField.name) + "=" + escape(oField.value); + } + } + oReq.open("get", oFormElement.action.replace(/(?:\?.*)?$/, sSearch.replace(/^&/, "?")), true); + oReq.send(null); + } +} +</script> +</head> +<body> + +<h1>Sending forms with FormData</h1> + +<h2>Using the GET method</h2> + +<form action="register.php" method="get" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h2>Using the POST method</h2> +<h3>Enctype: application/x-www-form-urlencoded (default)</h3> + +<form action="register.php" method="post" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Registration example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +<h3>Enctype: text/plain</h3> + +<p>The text/plain encoding is not supported by the FormData API.</p> + +<h3>Enctype: multipart/form-data</h3> + +<form action="register.php" method="post" enctype="multipart/form-data" onsubmit="AJAXSubmit(this); return false;"> + <fieldset> + <legend>Upload example</legend> + <p> + First name: <input type="text" name="firstname" /><br /> + Last name: <input type="text" name="lastname" /><br /> + Sex: + <input id="sex_male" type="radio" name="sex" value="male" /> <label for="sex_male">Male</label> + <input id="sex_female" type="radio" name="sex" value="female" /> <label for="sex_female">Female</label><br /> + Password: <input type="password" name="secret" /><br /> + What do you prefer: + <select name="image_type"> + <option>Books</option> + <option>Cinema</option> + <option>TV</option> + </select> + </p> + <p> + Post your photos: + <input type="file" multiple name="photos[]"> + </p> + <p> + <input id="vehicle_bike" type="checkbox" name="vehicle[]" value="Bike" /> <label for="vehicle_bike">I have a bike</label><br /> + <input id="vehicle_car" type="checkbox" name="vehicle[]" value="Car" /> <label for="vehicle_car">I have a car</label> + </p> + <p> + Describe yourself:<br /> + <textarea name="description" cols="50" rows="8"></textarea> + </p> + <p> + <input type="submit" value="Submit" /> + </p> + </fieldset> +</form> + +</body> +</html></pre> +</div> + +<div class="note"><strong>Nota:</strong> Come si è detto,gli oggetti<strong> {{domxref("FormData")}} non sono <a href="/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify" title="/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify">stringifiabli</a></strong>. Se si desidera porre in stringa dei dati inviati, utilizzare il <a href="#A_little_vanilla_framework" title="#A_little_vanilla_framework">precedente esempio in AJAX puro</a>. Si noti che ci sono degli elementi <code>file</code> nel campo {{ HTMLElement("input") }}, <strong>quando si invia una form attraverso l'API <code>FormData</code> API non è necessario utilizzare le API <a href="/en-US/docs/DOM/FileReader" title="/en-US/docs/DOM/FileReader"><code>FileReader</code></a></strong>: i file sono automaticamente caricati.</div> + +<h2 id="Get_last_modified_date">Get last modified date</h2> + +<pre class="brush: js">function getHeaderTime () { + alert(this.getResponseHeader("Last-Modified")); /* A valid GMTString date or null */ +} + +var oReq = new XMLHttpRequest(); +oReq.open("HEAD" /* use HEAD if you only need the headers! */, "yourpage.html", true); +oReq.onload = getHeaderTime; +oReq.send();</pre> + +<h3 id="Do_something_when_last_modified_date_changes">Do something when last modified date changes</h3> + +<p>Let's create these two functions:</p> + +<pre class="brush: js">function getHeaderTime () { + + var + nLastVisit = parseFloat(window.localStorage.getItem('lm_' + this.filepath)), + nLastModif = Date.parse(this.getResponseHeader("Last-Modified")); + + if (isNaN(nLastVisit) || nLastModif > nLastVisit) { + window.localStorage.setItem('lm_' + this.filepath, Date.now()); + isFinite(nLastVisit) && this.callback(nLastModif, nLastVisit); + } + +} + +function ifHasChanged(sURL, fCallback) { + var oReq = new XMLHttpRequest(); + oReq.open("HEAD" /* use HEAD - we only need the headers! */, sURL, true); + oReq.callback = fCallback; + oReq.filepath = sURL; + oReq.onload = getHeaderTime; + oReq.send(); +}</pre> + +<p>Test:</p> + +<pre class="brush: js">/* Let's test the file "yourpage.html"... */ + +ifHasChanged("yourpage.html", function (nModif, nVisit) { + alert("The page '" + this.filepath + "' has been changed on " + (new Date(nModif)).toLocaleString() + "!"); +});</pre> + +<p>If you want to know <strong>whether <em>the current page</em> has changed</strong>, please read the article about <a href="/en-US/docs/Web/API/document.lastModified" title="/en-US/docs/Web/API/document.lastModified"><code>document.lastModified</code></a>.</p> + +<h2 id="Cross-site_XMLHttpRequest">Cross-site XMLHttpRequest</h2> + +<p>Modern browsers support cross-site requests by implementing the web applications working group's <a href="/en-US/docs/HTTP_access_control" title="HTTP access control">Access Control for Cross-Site Requests</a> standard. As long as the server is configured to allow requests from your web application's origin, <code>XMLHttpRequest</code> will work. Otherwise, an <code>INVALID_ACCESS_ERR</code> exception is thrown.</p> + +<h2 id="Bypassing_the_cache">Bypassing the cache</h2> + +<p><span style="line-height: 1.572;">A, cross-browser compatible approach to bypassing the cache is to append a timestamp to the URL, being sure to include a "?" or "&" as appropriate. For example:</span></p> + +<pre>http://foo.com/bar.html -> http://foo.com/bar.html?12345 +http://foo.com/bar.html?foobar=baz -> http://foo.com/bar.html?foobar=baz&12345 +</pre> + +<p>Since the local cache is indexed by URL, this causes every request to be unique, thereby bypassing the cache.</p> + +<p>You can automatically adjust URLs using the following code:</p> + +<pre class="brush:js">var oReq = new XMLHttpRequest(); + +oReq.open("GET", url + ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime(), true); +oReq.send(null);</pre> + +<h2 id="Security">Security</h2> + +<p>{{fx_minversion_note(3, "Versions of Firefox prior to Firefox 3 allowed you to set the preference <code>capability.policy.<policyname>.XMLHttpRequest.open</policyname></code> to <code>allAccess</code> to give specific sites cross-site access. This is no longer supported.")}}</p> + +<p>{{fx_minversion_note(5, "Versions of Firefox prior to Firefox 5 could use <code>netscape.security.PrivilegeManager.enablePrivilege(\"UniversalBrowserRead\");</code> to request cross-site access. This is no longer supported, even though it produces no warning and permission dialog is still presented.")}}</p> + +<p>The recommended way to enable cross-site scripting is to use the <code>Access-Control-Allow-Origin </code> HTTP header in the response to the XMLHttpRequest.</p> + +<h3 id="XMLHttpRequests_being_stopped">XMLHttpRequests being stopped</h3> + +<p>If you end up with an XMLHttpRequest having <code>status=0</code> and <code>statusText=null</code>, it means that the request was not allowed to be performed. It was <code><a href="http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-unsent" title="http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-unsent">UNSENT</a></code>. A likely cause for this is when the <a href="http://www.w3.org/TR/XMLHttpRequest/#xmlhttprequest-origin" style="outline: 1px dotted; outline-offset: 0pt;"><code>XMLHttpRequest</code> origin</a> (at the creation of the XMLHttpRequest) has changed when the XMLHttpRequest is then <code>open()</code>. This case can happen for example when one has an XMLHttpRequest that gets fired on an onunload event for a window: the XMLHttpRequest gets in fact created when the window to be closed is still there, and then the request is sent (ie <code>open()</code>) when this window has lost its focus and potentially different window has gained focus. The way to avoid this problem is to set a listener on the new window "activate" event that gets set when the old window has its "unload" event fired.</p> + +<h2 id="Using_XMLHttpRequest_from_JavaScript_modules_XPCOM_components">Using XMLHttpRequest from JavaScript modules / XPCOM components</h2> + +<p>Instantiating <code>XMLHttpRequest</code> from a <a href="/en-US/docs/JavaScript_code_modules/Using" title="https://developer.mozilla.org/en/JavaScript_code_modules/Using_JavaScript_code_modules">JavaScript module</a> or an XPCOM component works a little differently; it can't be instantiated using the <code>XMLHttpRequest()</code> constructor. The constructor is not defined inside components and the code results in an error. The best way to work around this is to use the XPCOM component constructor.</p> + +<pre class="brush: js">const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1", "nsIXMLHttpRequest"); +</pre> + +<p>Unfortunately in versions of Gecko prior to Gecko 16 there is a bug which can cause requests created this way to be cancelled for no reason. If you need your code to work on Gecko 15 or earlier, you can get the XMLHttpRequest constructor from the hidden DOM window like so.</p> + +<pre class="brush:js">const { XMLHttpRequest } = Components.classes["@mozilla.org/appshell/appShellService;1"] + .getService(Components.interfaces.nsIAppShellService) + .hiddenDOMWindow; +var oReq = new XMLHttpRequest();</pre> + +<h2 id="See_also">See also</h2> + +<ol> + <li><a href="/en-US/docs/AJAX/Getting_Started" title="AJAX/Getting_Started">MDN AJAX introduction</a></li> + <li><a href="/en-US/docs/HTTP_access_control" title="HTTP access control">HTTP access control</a></li> + <li><a href="/en-US/docs/How_to_check_the_security_state_of_an_XMLHTTPRequest_over_SSL" title="How to check the security state of an XMLHTTPRequest over SSL">How to check the security state of an XMLHTTPRequest over SSL</a></li> + <li><a href="http://www.peej.co.uk/articles/rich-user-experience.html">XMLHttpRequest - REST and the Rich User Experience</a></li> + <li><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/xmobjxmlhttprequest.asp">Microsoft documentation</a></li> + <li><a href="http://developer.apple.com/internet/webcontent/xmlhttpreq.html">Apple developers' reference</a></li> + <li><a href="http://jibbering.com/2002/4/httprequest.html">"Using the XMLHttpRequest Object" (jibbering.com)</a></li> + <li><a href="http://www.w3.org/TR/XMLHttpRequest/">The XMLHttpRequest Object: W3C Specification</a></li> + <li><a href="http://dev.w3.org/2006/webapi/progress/Progress.html" title="http://dev.w3.org/2006/webapi/progress/Progress.html">Web Progress Events specification</a></li> + <li></li> +</ol> |