Fred
Brack Raleigh, NC |
by Fred Brack
Last Updated
This is not a full tutorial on AJAX but rather an introduction and an example of how you can use it to access text data. I created this web page to help me document my understanding of AJAX ... and because I like to document stuff for others! I hope you find it useful.
This article was written prior to my series on JavaScript. It is my introduction to AJAX and demonstration how it can be used with JavaScript to access data as a text file. My second article on AJAX addresses how to access a secondary file of HTML with the Document Object Model methods. |
I maintain a website whose Home Page is updated once per week; but other pages on the site are updated several times a week. I wanted to extract a number from one of those pages dynamically to display as part of the Home Page, and that's how I got into learning about AJAX. This page shares the result of my learning how to achieve my objective, and hopefully it will help you also. It took awhile, as I was a JavaScript novice at the time; but even it you are a novice, hopefully this will get you most of the way there.
Per TutorialsPoint:
XMLHttpRequest (XHR) is an API that can be used by JavaScript, JScript, VBScript, and other web browser scripting languages to transfer and manipulate XML data to and from a webserver using HTTP, establishing an independent connection channel between a webpage's Client-Side and Server-Side. ... Besides XML, XMLHttpRequest can be used to fetch data in other formats, e.g. JSON or even plain text.
The highlighting of "or even plain text" is mine, because that's all I'm going to talk about on this page. XHR (the abbreviation for XMLHttpRequest) was designed primarily to give you access to a "database" of information coded in XML (Extensible Markup Language) format, and that's the default assumption. But since the API (Application Program Interface) must first read the file of XML, it can also just pass you the raw file data for you to process. And that's what we want: the data from a file of our choosing, be it HTML, or TXT, or something else.
A fundamental limitation of XHR is that it will only access a file from the host's server on the same domain. You cannot use it to read just any old file. This is standard web protocol known as Same-Origin Policy (SOP).
Here then is the approach we will use to access a "piece of data" contained in a file on our web server.
That's it! Two statements in your main HTML; two functions in JavaScript; plus your data file. Easy when you know how ...
Let's spend a moment talking about the data file. In my case, I wanted to extract a single number from somewhere in one HTML page and display it on another page which was updated less frequently -- thus a dynamic presentation of the number. To understand the approach I took, there is one thing you should understand about how XHR operates: XHR reads an ENTIRE file and returns ALL the data in one object! In my case, it would have returned nearly a million bytes of data just to extract 4 of them. I felt that was too inefficient, so I chose a different approach. The number I wanted was also contained in a file of a little over 1,000 bytes. It turns out that the HTML file where that number would have been accessed is programmatically created, so I simply added one line to the program to copy the data file to the server at the same time as the HTML. And my JavaScript specifies the URL of the data file. For your purposes, you may simply wish to access an existing HTML file, and that's fine. [With the speed of modern computers, my reservation about reading in a million bytes was probably unwarranted. I subsequently wrote another routine which reads that original HTML file every time it is invoked to search for something, and it is fast!]
As mentioned above, XHR returns all the data in the entire file as one long stream in the "responseText" property of XHR. While you can simply search the text for what you want, I chose to break the text stream down into the "lines" that originally made up the data. To do this, I search the stream for the end-of-line character ("\n" in JavaScript), first counting all of them to determine how many lines there are, then to look for the "next" one to be able to pick off only the current line. It is that line, the current line, that I examine for the specific data I am seeking.
In the data file (called ADPvariables.ini in my example below), the line I am looking for looks like this:
@mastertitles = 4321 /* date */
So I will be searching first for each new line, then examining each line for "@mastertitles" so I can pick off the number associated with it (4321). I don't care about the date field which follows. In JavaScript notation, numbering starts with 0, not 1; so when I break the line into an array (simply one way of approaching the problem), the 4321 is field 2, not field 3. (Field 1 is the "=" sign.)
IMPORTANT! XHR defaults to returning data in XML format. You MUST override the expected data type to force "plain text," as seen below, if you are not processing the file as XML.
This section was written prior to finding a "better
way" to test for your data being ready to access. I am including it here because you may still wish to know what the return codes are, or you may possibly wish to use the "readyState" method anyway. |
After you "send" your request to XHR, you need to wait until XHR is done successfully transferring your data. Along the way, it changes its "state" several times, returned in the 'readyState' property as five values ranging from uninitialized (0) to sent (2) to completed (4). You only care about completion. At that point, you care about the 'status' property, and there you only care if it is OK (code 200). As a programmer, you might care about code 404 ('Not Found'), but you are unlikely to send that message to your user's screen, so we don't check it here. Thus we only check for success with the following line, where the term "this" is JavaScript for the object that received the event (XHR in our case):
if (this.readyState == 4 && this.status == 200) { ... }
For reference, here is the chart of status codes taken from w3schools.com:
Property | Description |
---|---|
onreadystatechange | Defines a function to be called when the readyState property changes |
readyState | Holds the status of the XMLHttpRequest. 0: request not initialized 1: server connection established 2: request received 3: processing request 4: request finished and response is ready |
status | 200: "OK" 403: "Forbidden" 404: "Page not found" For a complete list go to the Http Messages Reference |
statusText | Returns the status-text (e.g. "OK" or "Not Found") |
Note from experience: There is another status code of interest: 0. It means an error occurred, which could be lots of things including some limitation of your server in the amount of data allowed to be returned.
Here then is the JavaScript file I am using to accomplish the objective described above. Please note: Since writing this originally, I have discovered a more compact way of issuing the XHR request which does not involve the "onreadystatechange" event handler. See Using AJAX to Access Another Web Page Using the DOM for the alternative method. You can substitute that method in the getdata code below for all the statements in maroon. Note that "true" in the "open" parameters is the default and means operate asynchronously. We added it only to emphasize you should not attempt "false" to force synchronous operation because it is bad practice and won't operate with many browsers anyway.
// GetADPCounts.js: Read the ADPvariables.ini file to acquire current AD title countsNote: I struggled with understanding part of the statement let lines = (data.match(/\n/g)||[]).length+1, so let me explain the entire statement.
Want more detail or someone else's explanation? I found this site after I wrote all of the above, but I thought it was very well written: XMLHttpRequest at JavaScript.info. |
# # # # #
Fred