-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.html
387 lines (378 loc) · 25.3 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>FCC project: Technical documentation page</title>
<meta name="description" content="FreeCodeCamp project: Build a technical documentation page">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Fira+Mono:400,700|Fira+Sans:400,700" rel="stylesheet">
<link rel="stylesheet" href="assets/normalize.css">
<link href="assets/prism/prism.css" rel="stylesheet" />
<link rel="stylesheet" href="main.css">
</head>
<body>
<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<nav id="navbar" class="navbar">
<header>AJAX basics</header>
<ul>
<a href="#What's_AJAX?" class="nav-link">
<li>What's AJAX?</li>
</a>
<a href="#How_to_make_an_HTTP_request" class="nav-link">
<li>How to make an HTTP request</li>
</a>
<a href="#Handling_the_server_response" class="nav-link">
<li>Handling the server response</li>
</a>
<a href="#A_Simple_Example" class="nav-link">
<li>A Simple Example</li>
</a>
<a href="#Working_with_the_XML_response" class="nav-link">
<li>Working with the XML response</li>
</a>
<a href="#Working_with_data" class="nav-link">
<li>Working with data</li>
</a>
<a href="#Reference" class="nav-link">
<li>Reference</li>
</a>
</ul>
</nav>
<main class="main" id="main-doc">
<section class="main-section" id="What's_AJAX?">
<header><span class="section-header">What's AJAX?</span></header>
<p>AJAX stands for Asynchronous JavaScript And XML. In a nutshell, it is the use of the
<a href="https://developer.mozilla.org/en/DOM/XMLHttpRequest">
<code class="language-javascript">XMLHttpRequest</code>
</a> object to communicate with servers. It can send and receive information in various formats, including
JSON, XML, HTML, and text files. AJAX’s most appealing characteristic is its "asynchronous" nature, which
means it can communicate with the server, exchange data, and update the page without having to refresh the
page.</p>
<p>The two major features of AJAX allow you to do the following:</p>
<ul>
<li>Make requests to the server without reloading the page</li>
<li>Receive and work with data from the server</li>
</ul>
</section>
<section class="main-section" id="How_to_make_an_HTTP_request">
<header><span class="section-header">How to make an HTTP request</span></header>
<p>In order to make an
<a href="https://developer.mozilla.org/en/HTTP">
<code class="language-javascript">HTTP</code>
</a> request to the server with JavaScript, you need an instance of an object with the necessary functionality.
This is where
<code class="language-javascript">XMLHttpRequest</code> comes in. Its predecessor originated in Internet Explorer as an ActiveX object called
<code class="language-javascript">XMLHTTP</code>. Then, Mozilla, Safari, and other browsers followed, implementing an
<code class="language-javascript">XMLHttpRequest</code> object that supported the methods and properties of Microsoft's original ActiveX object. Meanwhile, Microsoft
implemented XMLHttpRequest as well.</p>
<pre><code class="language-javascript line-numbers">// Old compatibility code, no longer needed.
if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+ ...
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 6 and older
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}</code></pre>
<p class="note">
<strong>Note:</strong> For illustration purposes, the above is a somewhat simplified version of the code to be used
for creating an XMLHttp instance. For a more realistic example, see step 3 of this article.</p>
<p>After making a request, you will receive a response back. At this stage, you need to tell the XMLHttp request
object which JavaScript function will handle the response, by setting the
<code class="language-javascript">onreadystatechange</code> property of the object and naming it after the function to call when the request changes state, like this:</p>
<pre><code class="language-javascript line-numbers">httpRequest.onreadystatechange = nameOfTheFunction;</code></pre>
<p>Note that there are no parentheses or parameters after the function name, because you're assigning a reference
to the function, rather than actually calling it. Alternatively, instead of giving a function name, you can
use the JavaScript technique of defining functions on the fly (called "anonymous functions") to define the
actions that will process the response, like this:</p>
<pre><code class="language-javascript line-numbers">httpRequest.onreadystatechange = function(){
// Process the server response here.
};</code></pre>
<p>Next, after declaring what happens when you receive the response, you need to actually make the request, by calling
the
<code class="language-javascript">open()</code> and
<code class="language-javascript">send()</code> methods of the HTTP request object, like this:</p>
<pre><code class="language-javascript line-numbers">httpRequest.open('GET', 'http://www.example.org/some.file', true);
httpRequest.send();</code></pre>
<ul>
<li>
The first parameter of the call to
<code class="language-javascript">open()</code> is the HTTP request method – GET, POST, HEAD, or another method supported by your server. Keep the method
all-capitals as per the HTTP standard, otherwise some browsers (like Firefox) might not process the request.
For more information on the possible HTTP request methods, check the
<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">W3C specs</a>.
</li>
<li>
The second parameter is the URL you're sending the request to. As a security feature, you cannot call URLs on 3rd-party domains
by default. Be sure to use the exact domain name on all of your pages or you will get a "permission denied"
error when you call
<code class="language-javascript">open()</code>. A common pitfall is accessing your site by
<code class="language-javascript">domain.tld</code>, but attempting to call pages with
<code class="language-javascript">www.domain.tld</code>. If you really need to send a request to another domain, see
<a href="https://developer.mozilla.org/En/HTTP_access_control">HTTP access control</a>.
</li>
<li>
The optional third parameter sets whether the request is asynchronous. If
<code class="language-javascript">true</code> (the default), JavaScript execution will continue and the user can interact with the page while the
server response has yet to arrive. This is the first A in AJAX.
</li>
</ul>
<p>The parameter to the
<code class="language-javascript">send()</code> method can be any data you want to send to the server if
<code class="language-javascript">POST</code>-ing the request. Form data should be sent in a format that the server can parse, like a query string:</p>
<pre><code class="language-javascript line-numbers">"name=value&anothername="+encodeURIComponent(myVar)+"&so=on"</code></pre>
<p>or other formats, like
<code class="language-javascript">multipart/form-data</code>, JSON, XML, and so on.</p>
<p>Note that if you want to
<code class="language-javascript">POST</code> data, you may have to set the MIME type of the request. For example, use the following before calling
<code class="language-javascript">send()</code> for form data sent as a query string:</p>
<pre><code class="language-javascript line-numbers">httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');</code></pre>
</section>
<section class="main-section" id="Handling_the_server_response">
<header><span class="section-header">Handling the server response</span></header>
<p>When you sent the request, you provided the name of a JavaScript function to handle the response:</p>
<pre><code class="language-javascript line-numbers">httpRequest.onreadystatechange = nameOfTheFunction;</code></pre>
<p>What should this function do? First, the function needs to check the request's state. If the state has the value
of
<code class="language-javascript">XMLHttpRequest.DONE</code> (corresponding to 4), that means that the full server response was received and it's OK for you to continue
processing it.</p>
<pre><code class="language-javascript line-numbers">if (httpRequest.readyState === XMLHttpRequest.DONE) {
// Everything is good, the response was received.
} else {
// Not ready yet.
}</code></pre>
<p>The full list of the
<code class="language-javascript">readyState</code> values is documented at
<a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState">
<code class="language-javascript">XMLHTTPRequest.readyState</code>
</a> and is as follows:</p>
<ul>
<li>0 (uninitialized) or
<strong>(request not initialized)</strong>
</li>
<li>1 (loading) or
<strong>(server connection established)</strong>
</li>
<li>2 (loaded) or
<strong>(request received)</strong>
</li>
<li>3 (interactive) or
<strong>(processing request)</strong>
</li>
<li>4 (complete) or
<strong>(request finished and response is ready)</strong>
</li>
</ul>
<p>Next, check the
<a href="https://developer.mozilla.org/en/HTTP#HTTP_Response_Codes">response code</a> of the HTTP response. The possible codes are listed at the
<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">W3C</a>. In the following example, we differentiate between a successful and unsuccessful AJAX call by checking
for a
<a href="https://developer.mozilla.org/en/HTTP/HTTP_response_codes#200">
<code class="language-javascript">200 OK</code>
</a> response code.</p>
<pre><code class="language-javascript line-numbers">if (httpRequest.status === 200) {
// Perfect!
} else {
// There was a problem with the request.
// For example, the response may have a 404 (Not Found)
// or 500 (Internal Server Error) response code.
}</code></pre>
<p>After checking the state of the request and the HTTP status code of the response, you can do whatever you want
with the data the server sent. You have two options to access that data:</p>
<ul>
<li>
<code class="language-javascript">httpRequest.responseText</code> – returns the server response as a string of text</li>
<li>
<code class="language-javascript">httpRequest.responseXML</code> – returns the response as an
<code class="language-javascript">XMLDocument</code> object you can traverse with JavaScript DOM functions</li>
</ul>
<p>Note that the steps above are valid only if you used an asynchronous request (the third parameter of
<code class="language-javascript">open()</code> was unspecified or set to
<code class="language-javascript">true</code>). If you used a
<strong>synchronous</strong> request you don't need to specify a function, but this is highly discouraged as it makes
for an awful user experience.</p>
</section>
<section class="main-section" id="A_Simple_Example">
<header><span class="section-header">A Simple Example</span></header>
<p>Let's put it all together with a simple HTTP request. Our JavaScript will request an HTML document,
<code class="language-javascript">test.html</code>, which contains the text "I'm a test." Then we'll
<code class="language-javascript">alert()</code> the contents of the response. Note that this example uses vanilla JavaScript — no jQuery is involved. Also,
the HTML, XML and PHP files should be placed in the same directory.</p>
<pre><code class="language-markup line-numbers"><button id="ajaxButton" type="button">Make a request</button>
<script>
(function() {
var httpRequest;
document.getElementById("ajaxButton").addEventListener('click', makeRequest);
function makeRequest() {
httpRequest = new XMLHttpRequest();
if (!httpRequest) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
httpRequest.onreadystatechange = alertContents;
httpRequest.open('GET', 'test.html');
httpRequest.send();
}
function alertContents() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
alert(httpRequest.responseText);
} else {
alert('There was a problem with the request.');
}
}
}
})();
</script></code></pre>
<p>In this example:</p>
<ul>
<li>The user clicks the "Make a request" button;</li>
<li>The event handler calls the
<code class="language-javascript">makeRequest()</code> function;</li>
<li>The request is made and then (
<code class="language-javascript">onreadystatechange</code>) the execution is passed to
<code class="language-javascript">alertContents()</code>;</li>
<li>
<code class="language-javascript">alertContents()</code> checks if the response was received and OK, then
<code class="language-javascript">alert()</code>s the contents of the
<code class="language-javascript">test.html</code> file.</li>
</ul>
<p class="note">
<strong>Note:</strong> If you're sending a request to a piece of code that will return XML, rather than a static
HTML file, you must set response headers to work in Internet Explorer. If you do not set header
<code class="language-javascript">Content-Type: application/xml</code>, IE will throw a JavaScript "Object Expected" error after the line where you tried to access an XML element.
</p>
<p class="note">
<strong>Note 2:</strong> If you do not set header
<code class="language-javascript">Cache-Control: no-cache</code> the browser will cache the response and never re-submit the request, making debugging challenging. You can
also add an always-different GET parameter, like a timestamp or random number (see
<a href="https://developer.mozilla.org/en/DOM/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache">bypassing the cache</a>)
</p>
<p class="note">
<strong>Note 3:</strong> If the
<code class="language-javascript">httpRequest</code> variable is used globally, competing functions calling
<code class="language-javascript">makeRequest()</code> can overwrite each other, causing a race condition. Declaring the
<code class="language-javascript">httpRequest</code> variable local to a
<a href="https://developer.mozilla.org/en/JavaScript/Guide/Closures">closure</a> containing the AJAX functions avoids this.
</p>
<p>In the event of a communication error (such as the server going down), an exception will be thrown in the
<code class="language-javascript">onreadystatechange</code> method when accessing the response status. To mitigate this problem, you could wrap your
<code class="language-javascript">if...then</code> statement in a
<code class="language-javascript">try...catch</code>:</p>
<pre><code class="language-javascript line-numbers">function alertContents() {
try {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
alert(httpRequest.responseText);
} else {
alert('There was a problem with the request.');
}
}
}
catch( e ) {
alert('Caught Exception: ' + e.description);
}
}</code></pre>
</section>
<section class="main-section" id="Working_with_the_XML_response">
<header><span class="section-header">Working with the XML response</span></header>
<p>In the previous example, after receiving the response to the HTTP request we used the request object's
<code class="language-javascript">responseText</code> property, which contained the contents of the
<code class="language-javascript">test.html</code> file. Now let's try the
<code class="language-javascript">responseXML</code> property.</p>
<p>First off, let's create a valid XML document that we'll request later on. The document (
<code class="language-javascript">test.xml</code>) contains the following:</p>
<pre><code class="language-markup line-numbers"><?xml version="1.0" ?>
<root>
I'm a test.
</root></code></pre>
<p>In the script we only need to change the request line to:</p>
<pre><code class="language-javascript line-numbers">...
onclick="makeRequest('test.xml')">
...</code></pre>
<p>Then in
<code class="language-javascript">alertContents()</code>, we need to replace the line
<code class="language-javascript">alert(httpRequest.responseText);</code> with:</p>
<pre><code class="language-javascript line-numbers">var xmldoc = httpRequest.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);</code></pre>
<p>This code takes the
<code class="language-javascript">XMLDocument</code> object given by
<code class="language-javascript">responseXML</code> and uses DOM methods to access some of the data contained in the XML document. You can see the
<code class="language-javascript">test.xml</code>
<a href="http://www.w3clubs.com/mozdev/test.xml">here</a> and the updated test script
<a href="http://www.w3clubs.com/mozdev/httprequest_test_xml.html">here</a>.</p>
</section>
<section class="main-section" id="Working_with_data">
<header><span class="section-header">Working with data</span></header>
<p>Finally, let's send some data to the server and receive a response. Our JavaScript will request a dynamic page
this time,
<code class="language-javascript">test.php</code>, which will take the data we send and return a "computed" string - "Hello, [user data]!" - which we'll
<code class="language-javascript">alert()</code>.</p>
<p>First we'll add a text box to our HTML so the user can enter their name:</p>
<pre><code class="language-markup line-numbers"><label>Your name:
<input type="text" id="ajaxTextbox" />
</label>
<span id="ajaxButton" style="cursor: pointer; text-decoration: underline">
Make a request
</span></span></code></pre>
<p>We'll also add a line to our event handler to get the user's data from the text box and send it to the
<code class="language-javascript">makeRequest()</code> function along with the URL of our server-side script:</p>
<pre><code class="language-javascript line-numbers">document.getElementById("ajaxButton").onclick = function() {
var userName = document.getElementById("ajaxTextbox").value;
makeRequest('test.php',userName);
};</code></pre>
<p>We need to modify
<code class="language-javascript">makeRequest()</code> to accept the user data and pass it along to the server. We'll change the request method from
<code class="language-javascript">GET</code> to
<code class="language-javascript">POST</code>, and include our data as a parameter in the call to
<code class="language-javascript">httpRequest.send()</code>:</p>
<pre><code class="language-javascript line-numbers">function makeRequest(url, userName) {
...
httpRequest.onreadystatechange = alertContents;
httpRequest.open('POST', url);
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
httpRequest.send('userName=' + encodeURIComponent(userName));
}</code></pre>
<p>The function
<code class="language-javascript">alertContents()</code> can be written the same way it was in Step 3 to alert our computed string, if that's all the server returns.
However, let's say the server is going to return both the computed string and the original user data. So
if our user typed "Jane" in the text box, the server's response would look like this:</p>
<pre><code class="language-javascript line-numbers">{"userData":"Jane","computedString":"Hi, Jane!"}</code></pre>
<p>To use this data within
<code class="language-javascript">alertContents()</code>, we can't just alert the
<code class="language-javascript">responseText</code>, we have to parse it and alert
<code class="language-javascript">computedString</code>, the property we want:</p>
<pre><code class="language-javascript line-numbers">function alertContents() {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
var response = JSON.parse(httpRequest.responseText);
alert(response.computedString);
} else {
alert('There was a problem with the request.');
}
}
}</code></pre>
<p>The
<code class="language-javascript">test.php</code> file should contain the following:</p>
<pre><code class="language-php line-numbers">$name = (isset($_POST['userName'])) ? $_POST['userName'] : 'no name';
$computedString = "Hi, " . $name;
$array = ['userName' => $name, 'computedString' => $computedString];
echo json_encode($array);</code></pre>
<p>For more on DOM methods, be sure to check Mozilla's DOM implementation documents.</p>
</section>
<section class="main-section" id="Reference">
<header><span class="section-header">Reference</span></header>
<p>All the documentation in this page is taken from
<a href="https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started">MDN</a>.</p>
</section>
</main>
<script src="assets/prism/prism.js"></script>
<!-- <script src="https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js"></script> -->
</body>
</html>