Thursday, February 5, 2009
Ajax Tutorial 6
8:54 AM |
Posted by
Hari Kiran |
Edit Post
I don't really enjoy writing articles that are primarily about something that you shouldn't do. Most of the time, it's a pretty silly type of thing to write. I spend half an article explaining something, just so I can spend the rest of the article explaining what a bad idea it is to use the techniques you've just learned about. Such was the case, to a large degree, with previous article, which taught you how to use XML as the data format for your Ajax apps' requests.
Hopefully, this article will redeem the time you spent learning about XML requests. In Ajax apps, while there are very few reasons to use XML as the sending data format, there are a lot of reasons why we may want a server to send XML back from a server, to a client. So everything we see about XML in the last article will definitely start to have some value in this article.
Servers can't say much (sometimes)
Before we go deeper into the technical details of getting an XML response from a server, we need to understand why it's such a good idea for a server to send XML in response to a request (and how that's different from a client sending that request in XML).
Clients speak in name/value pairs
As we recall from the last article, clients don't need to use XML in most cases because they can send requests using name/value pairs. So we might send a name like this: name=haki . We can stack those up by simply adding an ampersand ( & ) between successive name/value pairs, like this: name=haki&job=programmer . Using simple text and these name/value pairs; clients can send requests with multiple values to a server easily. There's rarely a need for the additional structure (and overhead) that XML provides.
In fact, almost all the reasons we'd need to send XML to a server can be grouped into two basic categories:
- The server only accepts XML requests. In these cases, we don't have a choice. The basics in last month's article should give us all the tools you need to send these sorts of requests.
- We're calling a remote API that only accepts XML or SOAP requests. This is really just a specialized case of the previous point, but it's worth mentioning on its own. If we want to use the APIs from Google or Amazon in an asynchronous request, there are some particular considerations. We'll look at those, and a few examples of making requests to APIs like this, in next month's article.
Servers can't send name/value pairs (in a standard way)
When we send name/value pairs, the Web browser sending the requests and the platform responding to that request and hosting a server program cooperate to turn those name/value pairs into data that a server program can work with easily. Practically every server-side technology -- from servlets to PHP to Perl to Ruby on Rails -- allows you to call a variety of methods to get at values based on a name. So getting the name attribute is trivial.
This isn't the case going in the other direction. If a server replied to an app with the string name=haki&job=programmer , the client has no standardized, easy way to break up the two name/value pairs, and then break each pair into a name and value. You'll have to parse the returned data manually. If a server returns a response made up of name/value pairs, that response is no easier (or harder) to interpret than a response with elements separated by semicolons, or pipe symbols, or any other nonstandard formatting character.
What that leaves us with, then, is no easy way to use plain text in our responses and have the client get that response and interpret it in a standard way, at least when the response contains multiple values. If our server simply sent back the number 42, say, plain text would be great. But what about if it's sending back the latest ratings for Movies Aundathi, Neninthe, and king, all at once? While we can chose many ways to send this response using plain text (see listing below for few examples), none are particularly easy to interpret without some work by the client, and none are standardized at all.
Listing.. Server response for movie ratings (various types)
movie=arundathi&ratings=14.2|movie=Neninthe&ratings=6.5|movie=King&rating=9.1
arundathi =14.2| Neninthe =6.5|King =9.1
arundathi|14.2|Neninthe|6.5|King|9.1
Even though it's not too hard to figure out how to break up these response strings, a client will have to parse and split the string up based on the semicolons, equal signs, pipes, and ampersands. This is hardly the way to write robust code that other developers can easily understand and maintain.
Enter XML
When we realize that there's no standard way for a server to respond to clients with name/value pairs, the reason behind using XML becomes pretty clear. When sending data to the server, name/value pairs are a great choice because servers and server-side languages can easily interpret the pairs; the same is true for using XML when returning data to a client. We saw the use of the DOM to parse XML in several earlier articles, and will see how JSON provides yet another option to parse XML in a future article. And on top of all that, we can treat XML as plain text, and get values out of it that way. So there are several ways to take an XML response from a server, and, with fairly standard code, pull the data out and use it in a client.
As an added bonus, XML is generally pretty easy to understand. Most people who program can make sense of the data in listing below, for example.
<ratings>
<movie>
<title>Arundathi</title><rating>14.2</rating>
</movie>
<movie>
<title>Neninthe</title><rating>6.5</rating>
</movie>
<movie>
<title>King</title><rating>9.1</rating>
</movie>
</ratings>
The code in above has no consideration about what a particular semicolon or apostrophe means.
Receiving XML from a server
Because the focus of this series is on the client side of the Ajax equation, we won't bother into much detail about how a server-side program can generate a response in XML. However, we need to know about some special considerations when your client receives XML.
First, you can treat an XML response from a server in two basic ways:
- As plain text that just happens to be formatted as XML
- As an XML document, represented by a DOM Document object.
Second, presume a simple response XML from a server for example's sake. Listing below shows the same TV listings as detailed above (this is, in fact, the same XML as in listing above reprinted for your convenience). I'll use this sample XML in the discussions in this section.
Listing.. XML-formatted movie for examples
<ratings> <movie> <title>Arundathi</title> <rating>14.2</rating> </movie> < movie> <title>Neninthe</title> <rating>6.5</rating> </movie > < movie > <title>King</title> <rating>9.1</rating> </movie> </ratings>
Dealing with XML as plain text
The easiest option to handle XML, at least in terms of learning new programming techniques, is to treat it like any other piece of text returned from a server. In other words, we basically ignore the data format, and just grab the response from the server.
In this situation, we use the responseText property of your request object, just as you would when the server sends you a non-XML response (see Listing below).
Listing.. Treating XML as a normal server response
function updatePage()
{
if (request.readyState == 4)
{
if (request.status == 200)
{
var response = request.responseText;
// response has the XML response from the server
alert(response);
}
}
}
In this code fragment, updatePage() is the callback, and request is the XMLHttpRequest object. You end up with the XML response, all strung together, in the response variable. If you printed out that variable, we'd have something like Listing below. (Note that the code in listing below normally is one, continuous line. Here, it is shown on multiple lines for display purposes.)
Listing.. Value of response variable
<ratings><movie><title>Arundathi</title><rating>14.2</rating></movie> <movie><title>Neninthe</title><rating>6.5</rating></movie> <movie><title>King</title><rating>9.1</rating></movie></ratings>
The most important thing to note here is that the XML is all run together. In most cases, servers will not format XML with spaces and carriage returns; they'll just string it all together, like you see in Listing above. Of course, our apps don't care much about spacing, so this is no problem; it does make it a bit harder to read, though.
At this point, we can use the JavaScript split function to break up this data, and basic string manipulation to get at the element names and their values. Of course, that's a pretty big pain, and it ignores the handy fact that you spent a lot of time looking at the DOM, the Document Object Model, earlier in this series. So I'll urge you to keep in mind that you can use and output a server's XML response easily using responseText , but I won’t show you much more code; we shouldn't use this approach to get at the XML data when you can use the DOM, as you'll see next.
Treating XML as XML
While we can treat a server's XML-formatted response like any other textual response, there's no good reason to do so. First, if you've read this series faithfully, you know how to use the DOM, a JavaScript-friendly API with which we can manipulate XML. Better yet, JavaScript and the XMLHttpRequest object provide a property that is perfect for getting the server's XML response, and getting it in the form of a DOM Document object.
To see this in action, check out listing below. This code is similar to listing above, but rather than use the responseText property, the callback uses the responseXML property instead. This property, available on XMLHttpRequest , returns the server's response in the form of a DOM document.
Listing.. Treating XML as XML
function updatePage()
{
if (request.readyState == 4)
{
if (request.status == 200)
{
var xmlDoc = request.responseXML;
// work with xmlDoc using the DOM
}
}
}
Now we have a DOM Document , and we can work with it just like any other XML. For example, we might then grab all the show elements, as in listing below
Listing.. Grabbing all the show elements
function updatePage()
{
if (request.readyState == 4)
{
if (request.status == 200)
{
var xmlDoc = request.responseXML;
var movieElements = xmlDoc.getElementsByTagName("movie");
}
}
}
{
if (request.readyState == 4)
{
if (request.status == 200)
{
var xmlDoc = request.responseXML;
var movieElements = xmlDoc.getElementsByTagName("movie");
}
}
}
If one are familiar with DOM, they should start to feel familiar. Here, we can use all the DOM methods that are already learned, and easily manipulate the XML you received from the server.
We can also, of course, mix in normal JavaScript code. For instance,we might iterate through all the show elements, as in listing below.
Listing.. Iterating through all the show elements
function updatePage()
{
if (request.readyState == 4)
{
if (request.status == 200)
{
var xmlDoc = request.responseXML;
var showElements = xmlDoc.getElementsByTagName("movie");
for (var x=0; x<showElements.length; x++)
{ // We know that the first child of show is title, and the second is rating
var title = showElements[x].childNodes[0].value;
var rating = showElements[x].childNodes[1].value;
// Here every thing can be done to title and ratings to display…
}
}
}
}
{
if (request.readyState == 4)
{
if (request.status == 200)
{
var xmlDoc = request.responseXML;
var showElements = xmlDoc.getElementsByTagName("movie");
for (var x=0; x<showElements.length; x++)
{ // We know that the first child of show is title, and the second is rating
var title = showElements[x].childNodes[0].value;
var rating = showElements[x].childNodes[1].value;
// Here every thing can be done to title and ratings to display…
}
}
}
}
With this relatively simple code, we treated an XML response like its XML, not just plain unformatted text, and used a little DOM and some simple JavaScript to deal with a server's response. Even more importantly, we worked with a standardized format XML, instead of comma-separated values or pipe-delimited name/value pairs. In other words, we’ve used XML where it made sense, and avoided it when it didn't, like in sending requests to the server.
XML on the server: A brief example
Although I haven't talked much about how to generate XML on the server, it's worth seeing a brief example, without much commentary, just so one can come up with their own ideas on how to deal with such a situation. Listing below shows a simple PHP script that outputs XML in response to a request, presumably from an asynchronous client.
This is the raw approach, where the PHP script is really just pounding out the XML output manually. We can find a variety of toolkits and APIs for PHP and most other server-side languages that also allow you to generate XML responses. In any case, this at least gives us an idea of what server-side scripts that generate and reply to requests with XML look like.
Listing.. PHP script that returns XML
<?php
// Connect to a MySQL database
$conn = @mysql_connect("localhost", "username", "secret-password");
if (!conn) die("Error connecting to database: " . mysql_error());
if (!mysql_select_db("movie", $conn)) die("Error selecting movie database: " . mysql_error());
// Get ratings for all TV shows in database
$query = 'SELECT title, rating from ratings';
$queryResult = mysql_query($query);
if (!$queryResult) die("Error retrieving ratings for movies.');
// Let the client know we're sending back XML
header("Content-Type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
echo "<ratings>";
while ($row = mysql_fetch_array($queryResult))
{
$title = $row['title'];
$rating = $row['rating'];
echo "<movie> echo "<title>" . $title . "</title>"; echo "<rating>" . $rating . "</rating>"; echo "</movie>";
}
echo "</ratings>";
mysql_close($conn);
?>
You can be able to output XML in a similar way using your own favorite server-side language.
Other options for interpreting XML
One very popular options for dealing with XML, beyond treating it as unformatted text or using the DOM, is important and worth mentioning. That's JSON, short for JavaScript Object Notation, and it's a free text format that is bundled into JavaScript. I don't have space to cover JSON in this article. You'll probably hear about it as soon as you mention XML and Ajax apps, however, so now you'll know what your co-workers are talking about.
In general, everything that you can do with JSON, you can do with the DOM, or vice versa; it's mostly about preference, and choosing the right approach for a specific application. For now, stick with the DOM, and get familiar with it in the context of receiving a server's response. In next articles, we'll have a good amount of time on JSON, and then you'll be ready to choose between the two on your next app. Lots of more XML could be in next articles.
In conclusion
I've talked about XML nearly non-stop since the last article in this series began, but have still really only scratched the surface of XML's contribution to the Ajax equation.
Your biggest task in the short term, though, is to really think about when XML makes sense for your own applications. In many cases, if your app is working well, then XML is nothing more than a technology buzzword that can cause you headaches, and you should resist the temptation to use it just so you can say you have XML in your application.
If you've a situation where the data the server sends you is limited, though, or in a strange comma- or pipe-delimited format, then XML might offer you real advantages. Consider working with or changing your server-side components so that they return responses in a more standard way, using XML, rather than a proprietary format that almost certainly isn't as robust as XML.
Most of all, realize that the more you learn about the technologies around Ajax, the more careful you have to be about your decisions. It's fun to write these Web 2.0 apps (and in coming articles, you'll return to the user interface and see some of the cool things that you can do), but it also takes some caution to make sure you don't throw technologies at a working Web page just to impress your friends. I know you can write a good app, so go out and do just that. When you're finished, come back here for article, and even more XML.
Labels:
Ajax
|
0
comments
Wednesday, February 4, 2009
Ajax Tutorial 5
5:09 AM |
Posted by
Hari Kiran |
Edit Post
Using XML format for request
Even casual Ajax developers will notice the x in Ajax, and realize that it stands for XML. XML is one of the most popular data formats in any programming medium, and offers real advantages for server responses in asynchronous applications. In this article, we'll see how servers can send XML in response to a request.We really can't do any significant programming today without running across XML. Whether you're a Web page designer considering the move to XHTML, a Web programmer working with JavaScript, a server-side programmer using deployment descriptors and data binding, or a back-end developer investigating XML-based databases, the eXtensible Markup Language (XML) is everywhere. Then it is no surprise that, XML is considered one of the core technologies that lie under Ajax.
However, this opinion reflects the poor choice of names for the core object used in Ajax applications, XMLHttpRequest more than it does technical reality. In other words, most people think XML is a core part of Ajax because they assume that the XMLHttpRequest object actually always uses XML. But that's not the case, and the reasons why are the subject of the first part of this article. We can see that in most Ajax applications, XML rarely makes an appearance at all.
XML does have real uses in Ajax, and XMLHttpRequest allows for these as well. There's certainly nothing keeping us from sending XML to a server. Apart from normal data, XML is also a usable format. In this article; we'll look at how to do that. More importantly, though, we'll talk about why we might use XML for our request format, and where, it shouldn’t be used.
XML: Is it really there at all?
It's easy to make assumptions about Ajax applications and their usage of XML; both the technology name (Ajax) and the core object it uses (XMLHttpRequest) imply the use of XML, and we'll hear XML linked with Ajax applications all the time. However, this perception is simply wrong, and if we want to really know the stuff when it comes to writing asynchronous applications, we need to know that the perception is wrong -- and, better yet, know why it's wrong.XMLHttpRequest: Poor names and HTTP
One of the worst things that can happen to a technology is for it becomes so hot that changing core pieces of it becomes impossible. That's exactly what's happened with XMLHttpRequest, the basic object used in Ajax apps. It sounds like it's designed to either send XML over HTTP requests, or perhaps make HTTP requests in some sort of XML format. Whatever the object's name sounds like, though, what it actually does is simply provide a way for your client code (usually JavaScript in your Web page) to send an HTTP request. More than that, nothing is there.Thus, it would be nice to simply change XMLHttpRequest's name to something more accurate, like HttpRequest, or perhaps simply Request. However, millions of developers are now throwing Ajax into their applications, and because we all know that it takes years, if not decades -- for the majority of users to move to new browser versions like Internet Explorer 7.0 or Firefox 1.5, such a move is simply not feasible. The end result is that will be sucked up with XMLHttpRequest, and it's up to developers to realize that the thing is just poorly named.
It's somewhat telling that one of the best known fallback methods for dealing with a browser (especially on Windows) that doesn't support XMLHttpRequest is to use the Microsoft IFRAME object. Hardly sounds like XML, HTTP, or even a request, does it? Obviously, all those things might be involved, but this should simply make clear the fact that the XMLHttpRequest object is a lot more about making requests without requiring a page reload than it is about XML, or even HTTP.
The requests are HTTP, not XML
When we write code in a Web page to communicate with a server, whether it's using Ajax or a normal form POST or even a hyperlink, we're just talking HTTP.Given that pretty much all Web communication between browsers and servers takes place through HTTP, the idea that XML is somehow the transport or technology used by XMLHttpRequest under the covers just doesn't make any sense. It's certainly possible for XML to be sent in the HTTP request, but HTTP is a very precisely defined standard that isn't going away any time soon. Unless you're specifically using XML in your request, or the server is sending you a response in XML, there's nothing but plain old HTTP used in the XMLHttpRequest object. So the next time someone tells you, "Yeah, it's called XMLHttpRequest because it uses XML behind the scenes," just smile and patiently explain to them what HTTP is, and let them know that while XML can be sent over HTTP, XML is a data format, not a transfer protocol.
Using XML (for real)
So far, I've told you about all the places where XML isn't used in Ajax. But the x in Ajax and the XML in XMLHttpRequest are still very real, and you may have several options for using XML in Web applications. we'll look at the basic options first, and then really go in to detail in the rest of this article.Options for XML
In our asynchronous apps, we'll find two basic applications of XML:- To send a request from a Web page to a server in XML format
- To receive a request from a server in your Web page in XML format
The second of these options, to receive a request in XML; requires you to take a response from a server, and extract the data from XML (again, using either an API or more of a raw coding approach). In this case, focus is on the data from the server, and it just so happens that we've got to pull that data out of XML to use it in any constructive way. This is the subject of the next article in this series, and we'll go deeper then.
An introductory warning
Before we go to the details of using XML, a short cautionary word is in order: XML is not a small, fast, space-saving format. As we'll see in the next several sections and in the next article in this series, there are some great reasons to use XML in this context, and some advantages that XML has over plain text requests and responses (especially for responses). However, XML is almost always going to take up more space and be slower than plain text, because several tags and semantics required for XML in messages.If we want to write a tremendous fast application that feels like a desktop app, XML might not be the best place to start. If we begin with plain text, and find a specific need for XML, then that's great; however, if we use XML from the beginning, we are certainly slowing down application's responsiveness. In most cases, it's faster to send plain text, using name/value pairs like name=haki -- than to turn the text into XML like this:
<name>haki</name>
Think of all the places where using XML adds time: wrapping the text in XML; sending across extra information (note that we didn't have any surrounding elements, an XML header, or anything else that would probably be part of a more realistic request); having the server parse the XML, generate a response, wrap the response back in XML, and send it back to a Web page; and then webpage parsing the response and finally using it. So learn when to use XML, but don't start out by thinking that it's going to make application faster in many situations; rather, it adds flexibility, as we'll begin to talk about now. XML from the client to the server
Let's look at using XML as the format to send data from a client to a server. First, we'll see how to do this technically, and then spend some time examining when this is a good idea, and when it's not.Sending name/value pairs
In about 90 percent of the Web apps we write, we'll end up with name/value pairs to send to a server. For example, if a user types their name and address into a form on your Web page, you might have data like this from the form:firstName=HakiIf you were just using plain text to send this data to a server, you might use code that looks something like listing below. (This is similar to an example used in the first article in this series.)
lastName=P
street= Rajendra Dall Mill Road
city= Vijayawada
state=Andhra Pradesh
zipCode=520012
Listing.. Sending name/value pairs in plain text
function callServer()
{
// Get the city and state from the Web form
var firstName = document.getElementById("firstName").value;
var lastName = document.getElementById("lastName").value;
var street = document.getElementById("street").value;
var city = document.getElementById("city").value;
var state = document.getElementById("state").value;
var zipCode = document.getElementById("zipCode").value;
// Build the URL to connect
var url = "noteUser.php?firstName=" + escape(firstName) +
"&lastName=" + escape(lastName) +
"&street=" + escape(street) + "&city=" + escape(city)
+ "&state=" + escape(state) + "&zipCode=" + escape(zipCode);
// Open a connection to the server
xmlHttp.open("GET", url, true);
// Set up a function for the server to run when it's done
xmlHttp.onreadystatechange = confirmUpdate;
// Send the request
xmlHttp.send(null); }
Converting name/value pairs to XML
The first thing we need to do if we need to use XML as a format for data like this is to come up with some basic XML format in which to store the data. Obviously, your name/value pairs can all turn into XML elements, where the element name is the name of the pair, and the content of the element is the value:<firstName>Haki</firstName>Of course, XML requires that we have a root element, or, if we're just working with a document fragment (a portion of an XML document), an enclosing element. So you might convert the XML above to something like this:
<lastName>P</lastName>
<street>Rajendra Dall Mill Road</street>
<city>Vijayawada</city>
<state>Andhra Pradesh</state>
<zipCode>520012</zipCode>
<address>Now we're almost ready to create this structure in your Web client, and send it to the server
<firstName>Haki</firstName>
<lastName>P</lastName>
<street>Rajendra Dall Mill Road</street>
<city>Vijayawada</city>
<state>Andhra Pradesh</state>
<zipCode>520012</zipCode>
</address>
Communication, of the verbal kind
Before we’re ready to start tossing XML over the network, we need to make sure that the server and script -- to which you send data actually accepts XML. For many of us it may not seem as a point to be noted, but for beginners, I thought it would be better to mention here only.In fact, we need to take two steps to ensure that the data sent in XML will be received correctly:
- Ensure that the script to which XML is sent, accepts XML as a data format.
- Ensure the script will accept the particular XML format and structure in which data is sent.
<profile>
<firstName>Haki</firstName>
<lastName>P</lastName>
<street Rajendra Dall Mill Road</street>
<city>Vijayawada</city>
<state>Andhra Pradesh</state>
<zip-Code>520012</zip-Code>
</profile>
This looks similar to the XML above, except for two things:
- The XML from the client is wrapped within an address element, but the server expects the data to be wrapped within a profile element.
- The XML from the client uses a zipCode element, while the server expects the zip code to be in a zip-code element.
Sending XML to the server
When it comes to sending XML to the server, we'll spend more of your code taking your data and wrapping it XML than you will actually transmitting the data. In fact, once you have the XML string ready to send to the server, you send it exactly as you would send any other plain text; check out listing below to see this in action.Listing.. Sending name/value pairs in XML
function callServer()Much of this is self-explanatory with just a few points worth noting. First, the data in your request must be manually formatted as XML. That's a bit of a letdown after three articles on using the Document Object Model, isn't it? And while nothing forbids you from using the DOM to create an XML document using JavaScript, we'd then have to convert that DOM object to text before sending it over the network with a GET or POST request. So it turns out to be easier to simply format the data using normal string manipulation. Of course, this introduces room for error and typographical mistakes, so one need to be extra careful when you write code that deals with XML.
{
// Get the city and state from the Web form
var firstName = document.getElementById("firstName").value;
var lastName = document.getElementById("lastName").value;
var street = document.getElementById("street").value;
var city = document.getElementById("city").value;
var state = document.getElementById("state").value;
var zipCode = document.getElementById("zipCode").value;
var xmlString = "<profile>" + " <firstName>" + escape(firstName) + "</firstName>" + " <lastName>" + escape(lastName) + "</lastName>" + " <street>" + escape(street) + "</street>" + " <city>" + escape(city) + "</city>" + " <state>" + escape(state) + "</state>" + " <zip-code>" + escape(zipCode) + "</zip-code>" + "</profile>";
// Build the URL to connect to
var url = "noteUser.php";
// Open a connection to the server
xmlHttp.open( "POST", url, true);
// Tell the server you're sending it XML
xmlHttp.setRequestHeader("Content-Type", "text/xml");
// Set up a function for the server to run when it's done
xmlHttp.onreadystatechange = confirmUpdate;
// Send the request
xmlHttp.send(xmlString);
//Generally for text, This would be null or blank.
}
Once XML is constructed, open a connection in largely the same way as it would be when sending text. I tend to prefer using POST requests for XML, since few browsers places a length limitation on GET query strings, and XML can get pretty long; we'll see that Listing above switches from GET to POST accordingly. Additionally, the XML is sent through the send() method, rather than as a parameter tacked on to the end of the URL you're requesting. These are all fairly trivial differences, easy for adjusting.
We need to write one entirely new line of code:
xmlHttp.setRequestHeader("Content-Type", "text/xml");This isn't hard to understand: it just tells the server that we're sending it XML, rather than plain old name/value pairs. In either case, we send data as text, but use text/xml here, or XML sent as plain text. If you just used name/value pairs, this line would read:
xmlHttp.setRequestHeader("Content-Type", "text/plain");If we forget mentioning Request type, server code will not work properly.
Once we get all this put together, all you need to do is call send() and pass in the XML string. The server will get our XML request, and (assuming we've done your pre-work) accept the XML, parse it, and send you back a response. That's really all there is to it -- XML requests with just a few changes of code.
Sending XML: Good or bad?
Before leaving XML requests (and this article) for XML responses, let's spend some real time thinking about the sensibility of using XML in your requests. I've already mentioned that XML is by no means the fastest data format in terms of transfer, but there's a lot more to think about.XML is not simple to construct
The first thing we need to realize is that XML is just not that easy to construct for use in requests. As we observed in listing above, our data quickly becomes pretty convoluted with the semantics of XML:var xmlString = "<profile>" +This might not seem so bad, but it's also an XML fragment that has only six fields. Most of the Web forms developed will have ten to fifteen; although we won't use Ajax for all of your requests, it is a consideration. we're spending at least as much time dealing with angle brackets and tag names as you are with actual data, and the potential to make little typing is tremendous.
" <firstName>" + escape(firstName) + "</firstName>" +
" <lastName>" + escape(lastName) + "</lastName>" +
" <street>" + escape(street) + "</street>"
+ " <city>" + escape(city) + "</city>"
+ " <state>" + escape(state) + "</state>"
+ " <zip-code>" + escape(zipCode) + "</zip-code>" +
"</profile>";
Another problem here is that, as already mentioned; we will have to construct this XML by hand. Using the DOM isn't a good option, as there aren't good, simple ways to turn a DOM object into a string that you request can be sent. So working with strings like this is really the best option; but it's also the option that's hardest to maintain, and hardest to understand for new developers. In this case, we constructed all the XML in one line; things only get more confusing when this is done in several steps.
For Requests, Nothing is added by XML
Beyond the issue of complexity, using XML for our requests really doesn't offer us much of an advantage, if any over plain text and name/value pairs. Consider that everything in this article has been focused on taking the same data we could already send using name/value pairs refer first listing in article and sending it using XML. At no point was anything said about data that you can send with XML that we could not send using plain text; that's because there almost never is anything that we can send using XML that you can't send using plain text.And that's really the bottom line with XML and requests: there's just rarely a compelling reason to do it. We'll see in the next article in this series that a server can use XML for some things that are much harder to do when using plain text; but it's just not the case with requests. So unless you're talking to a script that only accepts XML (and there are some out there), we're better off using plain text in almost every request situation.
In conclusion
We should definitely feel like we're starting to get the XML in Ajax figured out. We know that Ajax apps don't have to use XML, and that XML isn't some sort of magic bullet for data transfer. We should also feel pretty comfortable in sending XML from a Web page to a server. Even more importantly, we know what's involved in making sure that a server will actually handle and respond to your requests: we've got to ensure that the server script accepts XML, and that it accepts it in the format that we're using to send the data over.We also should have a good idea now of why XML isn't always that great a choice for a data format for requests. In future articles, you'll see some cases where it helps, but in most requests, it simply slows things down and adds complexity. So while I'd normally suggest that you immediately start using the things you learned in an article, I'll instead suggest that you be very careful about using what you've learned here. XML requests have their place in Ajax apps, but that place isn't as vastly as its thought of.
In the next article in this series, you'll look at how servers can respond using XML, and how your Web applications can handle those responses. Happily, there are a much larger number of reasons for a server to send XML back to a Web app than the other way around, so you'll get even more use out of that article's technical detail; for now, be sure you understand why XML isn't always a great idea -- at least for sending requests. We might even want to try and implement some Web apps using XML as the data format for requests, and then convert back to plain text, and see which seems both faster and easier to us.
Labels:
Ajax
|
0
comments
Monday, February 2, 2009
Ajax Tutorial 4
1:04 AM |
Posted by
Hari Kiran |
Edit Post
Overview of DOM
Understanding what a DOM tree is, and even knowing how it represents your HTML and CSS, is just the first step in taking control of your Web pages. Next, we need to know how to work with the DOM tree for a particular Web page. For instance, if we add an element to the DOM tree, that element immediately appears in a user's Web browser; without the page reloading. Remove some text from the DOM tree, and that text vanishes from the user's screen. We can change and interact with the user interface through the DOM, which gives us tremendous programming power and flexibility. Once we learn how to work with a DOM tree we've taken huge step toward mastering rich, interactive, dynamic Web sites
Cross browser, cross language
The Document Object Model is a W3C standard. Because of that, all modern Web browsers support the DOM, at least to some extent. While there is some variance among browsers, if we use core DOM functionality and pay attention to a few special cases and exceptions, our DOM code will work on any browser in the same way. The code you write to modify a Web page in Opera will work on Apple's Safari, Firefox, Microsoft’s Internet Explorer, and Mozilla.
The DOM is also a cross-language specification; in other words, we can use it from most of the popular programming languages. The W3C defines several language bindings for the DOM. A language binding is simply an API defined to let us use the DOM for a specific language. For example, we can find well-defined DOM language bindings for C, Java, and JavaScript. So we can use the DOM from any of these languages. Language bindings are also available for several other languages, although many of these are not defined by the W3C, but instead by third parties.
In this series we will have focus on JavaScript bindings into DOM. That makes sense because most asynchronous application development is based on writing JavaScript code to run in a Web browser. With JavaScript and the DOM, we can modify the user interface on the fly; respond to user events and input, and more -- all using fairly standardized JavaScript.
All that said, I encourage you to check out the DOM language bindings in other languages. For instance, you can use the Java language bindings to work not only with HTML, but also XML, as we'll discuss in a later article. So the lessons you'll learn here apply to far more than HTML, in many more environments than just client-side JavaScript.
The conceptual node
A node is the most basic object type in the DOM. In fact, as we'll see in this article, almost every other object defined by the DOM extends from the node object. But, before we get too far into deeper, we need to understand the concept that is represented by a node; then, to learn the actual properties and methods of a node is like a piece of cake.
In a DOM tree, almost everything we'll come across is a node. Every element is at its most basic level a node in the DOM tree. Every attribute is a node. Every piece of text is a node. Even comments, special characters (like ©, which represents a copyright symbol), and a DOCTYPE declaration (if we have one in our HTML or XHTML) all are nodes. So before we get into the specifics of each of these individual types, we really need to grasp what a node is.
A node is...
In simplest terms, a node is just one single thing in a DOM tree. The vagueness of "thing" is intentional, because that's about as specific as it gets. For example, it's probably not obvious that an element in our HTML, like img, and a piece of text in HTML, like "Scroll down for more details" have much in common. But that's because we're probably thinking about the function of those individual types, and focusing on how different they are.
Consider, that each element and piece of text in a DOM tree has a parent; that parent is either the child of another element (like when an img is nested inside a p element), or is the top-most element in the DOM tree (which is a one-time special case for each document, and is where we use the html element). Also consider that both elements and text have a type. The type for an element is obviously an element; the type for text is text. Each node also has some fairly well-defined structure to it: does it have a node (or nodes) below it, such as child elements? Does it have sibling nodes (nodes "next to" the element or text)? What document does each node belong to?
Obviously, much of this sounds pretty abstract. In fact, it might even seem silly to say that the type of an element is ... well ... an element. However, we need to think a bit abstractly to realize the value of having the node as a common object type.
The common node type
The single task we'll perform more than any other in your DOM code is navigating within the DOM tree for a page. For instance, you might locate a form by its "id" attribute, and then begin to work with the elements and text nested within that form . There will be textual instructions, labels for input fields, actual input elements, and possibly other HTML elements like img elements and links ( a elements). If elements and text are completely different types, then we need to write completely different pieces of code to move from one type to another.
Things are different if we use a common node type. In that case we can simply move from node to node, and worry about the type of the node only when we want to do something specific with an element or text. When we just move around in the DOM tree, we'll use the same operations to move to an element's parent or its children; as we would with any other type of node. We only have to work specifically with a node type, like an element or text, when we require something specific from a certain type of node, like an element's attributes. Thinking about each object in the DOM tree simply as a node allows you to operate much more simply. With that in mind, we'll look next at exactly what the DOM Node construct has to offer, starting with properties and methods.
Properties of a node
We want to use several properties and methods when we work with DOM nodes, so let's consider them first. The key properties of a DOM node are:
- nodeName reports the name of the node (see more below).
- nodeValue :gives the "value" of the node (see more below).
- parentNode returns the node's parent. Remember, every element, attribute, and text has a parent node.
- childNodes is a list of a node's children. When working with HTML, this list is only useful when you're dealing with an element; text nodes and attribute nodes don't have any children.
- firstChild is just a shortcut to the first node in the childNodes list.
- lastChild is another shortcut, this time to the last node in the childNodes list.
- previousSibling returns the node before the current node. In other words, it returns the node that precedes the current one, in this node's parent's childNodes list (if that was confusing, again read that last sentence).
- nextSibling is similar to the previousSibling property; it turns the next node in the parent's childNodes list.
- attributes is only useful on an element node; it returns a list of an element's attributes.
The few other properties really apply to more generic XML documents, and aren't of much use when we work with HTML-based Web pages.
Unusual properties
Most of the above-defined properties are pretty self-explanatory, with the exception of the nodeName and nodeValue properties. Rather than simply explain these properties, consider a couple of odd questions: What would the nodeName be for a text node ? And, similarly, What would the nodeValue be for an element ?
If these questions rose for you, then you already understand the potential for confusion inherent in these properties. nodeName and nodeValue really don't apply to all node types (this is also true of a few of the other properties on a node). This illustrates a key concept: any of these properties can return a null value (which sometimes shows up in JavaScript as "undefined"). So, for example, the nodeName property for a text node is null (or "undefined" in some browsers, as text nodes don't have a name. nodeValue returns the text of the node, as we could probably expect.
Similarly, elements have a nodeName ; the name of the element; but the value of an element's nodeValue property is always null. Attributes have values for both the nodeName and nodeValue properties. We'll discuss about these individual types a bit more in the next section, but since these properties are part of every node, they're worth mentioning here.
Now take a look at Listing below, which shows several of the node properties in action.
// These first two lines get the DOM tree for the current Web page,
// and then the <html> element for that DOM tree
var myDocument = document;
var htmlElement = myDocument.documentElement; // What's the name of the <html> element? "html"
alert("The root element of the page is " + htmlElement.nodeName); // Look for the <head>
element var headElement = htmlElement.getElementsByTagName("head")[0];
if (headElement != null)
{
alert("We found the head element, named " + headElement.nodeName); // Print out the title of the page
var titleElement = headElement.getElementsByTagName("title")[0];
}
if (titleElement != null)
{
// The text will be the first child node of the <title> element var titleText = titleElement.firstChild;
// We can get the text of the text node with nodeValue
alert("The page title is '" + titleText.nodeValue + "'");
} // After <head> is <body>
var bodyElement = headElement.nextSibling;
while ( bodyElement.nodeName.toLowerCase() != "body")
{
bodyElement = bodyElement.nextSibling;
} // We found the <body> element... // We'll do more when we know some methods on the nodes.
}//End While
Methods of a node
Next are the methods available to all nodes (as in the case of node properties, I've omitted a few methods, that don't really apply to most HTML DOM operations):
- insertBefore(newChild, referenceNode) inserts the newChild node before the referenceNode . Keep in mind you would call this on the intended parent of newChild .
- replaceChild(newChild, oldChild) replaces the oldChild node with the newChild node.
- removeChild(oldChild) removes the oldChild node from the node the function is run on.
- appendChild(newChild) adds the newChild node to the node this function is run on. newChild is added at the end of the target node's children.
- hasChildNodes() returns true if the node it's called on has children, and false if it doesn't have.
- hasAttributes() returns true if the node it's called on has attributes, and false if there are no attributes.
We can notice that, for the most part, all of these methods deal with the children of a node. That's their primary purpose. If we're just trying to grab the value of a text node or the name of an element, we probably won't find ourselves calling methods much, since we can simply use the properties of a node. Listing below builds on the code from Listing above using several of the above methods.
Listing.. Using node methods in the DOM
// These first two lines get the DOM tree for the current Web page,
// and then the <html> element for that DOM tree
var myDocument = document;
var htmlElement = myDocument.documentElement;
// What's the name of the <html> element? "html"
alert("The root element of the page is " + htmlElement.nodeName);
// Look for the <head> element
var headElement = htmlElement.getElementsByTagName("head")[0];
if (headElement != null)
{
alert("We found the head element, named " + headElement.nodeName);
// Print out the title of the page
var titleElement = headElement.getElementsByTagName("title")[0];
if (titleElement != null)
{
// The text will be the first child node of the <title> element
var titleText = titleElement.firstChild;
// We can get the text of the text node with nodeValue
alert("The page title is '" + titleText.nodeValue + "'");
}
// After <head> is <body>
var bodyElement = headElement.nextSibling;
while (bodyElement.nodeName.toLowerCase() != "body")
{
bodyElement = bodyElement.nextSibling;
}
// We found the <body> element...
// Remove all the top-level <img> elements in the body
if ( bodyElement.hasChildNodes())
{
for (i=0; i<bodyElement.childNodes.length; i++)
{
var currentNode = bodyElement.childNodes[i];
if (currentNode.nodeName.toLowerCase() == "img")
{
bodyElement.removeChild(currentNode);
}
}
}
}
// and then the <html> element for that DOM tree
var myDocument = document;
var htmlElement = myDocument.documentElement;
// What's the name of the <html> element? "html"
alert("The root element of the page is " + htmlElement.nodeName);
// Look for the <head> element
var headElement = htmlElement.getElementsByTagName("head")[0];
if (headElement != null)
{
alert("We found the head element, named " + headElement.nodeName);
// Print out the title of the page
var titleElement = headElement.getElementsByTagName("title")[0];
if (titleElement != null)
{
// The text will be the first child node of the <title> element
var titleText = titleElement.firstChild;
// We can get the text of the text node with nodeValue
alert("The page title is '" + titleText.nodeValue + "'");
}
// After <head> is <body>
var bodyElement = headElement.nextSibling;
while (bodyElement.nodeName.toLowerCase() != "body")
{
bodyElement = bodyElement.nextSibling;
}
// We found the <body> element...
// Remove all the top-level <img> elements in the body
if ( bodyElement.hasChildNodes())
{
for (i=0; i<bodyElement.childNodes.length; i++)
{
var currentNode = bodyElement.childNodes[i];
if (currentNode.nodeName.toLowerCase() == "img")
{
bodyElement.removeChild(currentNode);
}
}
}
}
Test me!
So far, we've seen two examples, in Listings above. But they should give you all sorts of ideas for what's possible when we start manipulating the DOM tree. If we want to try out the code so far, just drop Listing below into an HTML file, save it, and load it into your Web browser.
Listing.. An HTML file with some JavaScript code using the DOM
<html>
<head>
<title>
JavaScript and the DOM
</title>
<script language="JavaScript">
function test()
{
// These first two lines get the DOM tree for the current Web page,
// and then the <html> element for that DOM tree
var myDocument = document;
var htmlElement = myDocument.documentElement;
// What's the name of the <html> element? "html"
alert("The root element of the page is " + htmlElement.nodeName);
//Look for the <head> element var headElement = htmlElement.getElementsByTagName("head")[0];
if (headElement != null)
{
alert("We found the head element, named " + headElement.nodeName);
// Print out the title of the page
var titleElement = headElement.getElementsByTagName("title")[0];
if (titleElement != null)
{
// The text will be the first child node of the <title> element
var titleText = titleElement.firstChild;
// We can get the text of the text node with nodeValue
alert("The page title is '" + titleText.nodeValue + "'");
}
// After <head> is <body>
var bodyElement = headElement.nextSibling;
while (bodyElement.nodeName.toLowerCase() != "body")
{
bodyElement = bodyElement.nextSibling;
}
// We found the <body> element...
// Remove all the top-level <img> elements in the body
if (bodyElement.hasChildNodes())
{
for (i=0; i<bodyElement.childNodes.length; i++)
{
var currentNode = bodyElement.childNodes[i];
if (currentNode.nodeName.toLowerCase() == "img")
{ bodyElement.removeChild(currentNode);
}
}
}
}
}
</script>
</head>
<body>
<p>
JavaScript and DOM are a perfect match. You can read more in <i>Head Rush Ajax</i>.</p>
<img src="http://www.test.com/Images/test_cover-150.jpg" /><!-- Replace with appropriate location of image-->
<input type="button" value="Test me!" onClick="test();" />
</body>
</html>
Once this page is loaded to a browser, one should see some text with an image and some text displayed with a button. When the button is clicked, two message boxes should popup..
- “We found head element, named HEAD” and etc
- After message boxes, images will be removed from the page using JavaScript.
API design notes
Take a look again at the properties and methods available on each node. They illustrate a key point of the DOM for those comfortable with object-oriented (OO) programming: the DOM isn't a very object-oriented API. First, in many cases we'll use an object's properties directly, rather than calling a method on a node object. There's no getNodeName() method, for example; we just use the nodeName property directly. So node objects (as well as the other DOM objects) expose a lot of their data through properties, and not just functions.
Second, the naming of objects and methods in the DOM might seem a bit strange if you're used to working with overloaded objects and object-oriented APIs, especially in languages like Java or C++. The DOM has to work in C, Java, and JavaScript (to name a few languages), so some concessions were made in the design of the API. For instance, you'll see two different methods on the NamedNodeMap methods that look like this:
- getNamedItem(String name)
- getNamedItemNS(Node node)
For OO programmers, this looks pretty odd. Two methods, with the same purpose, but one takes a String and one takes a Node . In most OO APIs, we would use the same method name for both versions. The virtual machine running our code would figure out which method to run based on the type of object you passed into the method.
The problem is that JavaScript doesn't support this technique, called method overloading. In other words, JavaScript requires that you have a single method or function for a given name. So if you have a method called getNamedItem() that takes a string, then we can't have any other method or function named getNamedItem() , even if the second version takes a different type of argument (or even takes an entirely different set of arguments). JavaScript will report an error if we try to do it, and our code won't behave as we think it should.
In essence, the DOM consciously avoids method overloading and other OO programming techniques. It does this to ensure that the API works across multiple languages, including those that don't support OO programming techniques. The end result is simply that we'll have to learn a few extra method names. The upside is that we can learn the DOM in any language; for example, Java -- and know that the same method names and coding constructs will work in other languages that have a DOM implementation; like JavaScript.
Let the programmer beware
If we're into API design at all or perhaps just are paying close attention, we might wonder: "Why are properties on the node type that aren't common to all nodes?" That's a good question, and the answer is more about politics and decision-making than any technical reason. In short, the answer is, "Who knows! But it's a bit annoying, isn't it?"
The property nodeName is meant to allow every type to have a name; but in many cases, that name is either undefined or it's some strange, internal name that has no value to programmers (for example, in Java, the nodeName of a text node is reported as "#text" in a lot of cases). Essentially, we need to assume that error handling is left up to us. It's not safe to simply access myNode.nodeName and then using that value; in many cases, the value will be null. So, as is often the case when it comes to programming, let the programmer beware.
Common node types
Now that we've seen some of the features and properties of a DOM node (and some of its differences as well), we're ready to learn about some of the specific types of nodes that we'll work with. In most Web applications, we'll only work with four types of nodes:
- The document node represents an entire HTML document.
- Element nodes represent HTML elements like a or img .
- Attribute nodes represent the attributes on HTML elements, like href (on the a element) or src (on the img element).
- Text nodes represent text in the HTML document, like "Click on the link below for a complete set list." This is the text that appears inside elements like p , a , or h2 .
When we deal with HTML, we'll work with these node types about 95% of the time. So I'll spend the remainder of this article discussing them in-depth. (When we discuss XML in a future article; we can find some other node types.)
The document node
The first node type is one we'll use in almost every piece of DOM-based code we write: the document node. The document node is actually not an element in an HTML (or XML) page, but the page itself. So in an HTML Web page, the document node is the entire DOM tree. In JavaScript; document node can be accessed using the document keyword:
// These first two lines get the DOM tree for the current Web page,
// and then the <html> element for that DOM tree
var myDocument = document ;
var htmlElement = myDocument.documentElement;
// and then the <html> element for that DOM tree
var myDocument = document ;
var htmlElement = myDocument.documentElement;
The document keyword in JavaScript returns the DOM tree for the current Web page. From there, we can work with all the nodes in the tree.
We can also use the document object to create new nodes, using methods like these:
- createElement(elementName) creates an element with the supplied name.
- createTextNode(text) creates a new text node with the supplied text.
- createAttribute(attributeName) creates a new attribute with the supplied name.
The key thing to note is that these methods create nodes, but do not attach them or insert them into any particular document. For this, we need to use one of the methods we've already seen, like insertBefore() or appendChild() . So we need use code like the following to create and then add a new element to a document:
var pElement = myDocument.createElement("p");
var text = myDocument.createTextNode("Here's some text in a p element.");
pElement.appendChild(text);
bodyElement.appendChild(pElement);
var text = myDocument.createTextNode("Here's some text in a p element.");
pElement.appendChild(text);
bodyElement.appendChild(pElement);
Once we've used the document element to get access to a Web page's DOM tree, we're ready to start working with elements, attributes, and text directly.
Element nodes
Although we'll work with element nodes a lot, for many of operations, we need to perform on elements involve the methods and properties common to all nodes, rather than methods and properties specific to just elements. Only two sets of methods are specific to elements:
- Methods that relate to working with attributes :
- getAttribute(name) returns the value of the attribute named name.
- removeAttribute(name) removes the attribute named name.
- setAttribute(name, value) creates an attribute named name , and sets its value to value.
- getAttributeNode(name) returns the attribute node named name (attribute notes are covered below).
- removeAttributeNode(node) removes the attribute node that matches the supplied node.
- Methods that relate to finding nested elements :
- getElementsByTagName(elementName) returns a list of element nodes with the supplied name.
These are all pretty self-explanatory, but check out some examples anyway.
Working with attributes
Working with attributes is fairly simple; for example.
We may create a new img element with the document object, and element, and some of the methods from above:
var imgElement = document.createElement("img");
imgElement.setAttribute("src", "http://www.tests.com/Images/hraj_cover-150.jpg");
imgElement.setAttribute("width", "130");
imgElement.setAttribute("height", "150");
bodyElement.appendChild(imgElement);
This should look pretty routine by now. In fact, you should start to see that once you understand the concept of a node and know the methods available, working with the DOM in your Web pages and JavaScript code is simple. In the code above, the JavaScript creates a new img element, sets up some attributes, and then adds it to the body of the HTML page.
Finding nested elements
It's also easy to find nested elements. For example, here's the code I used to find and remove all the img elements in the HTML page from above
//Remove all the top-level <img> elements in the body
if (bodyElement.hasChildNodes())
{
for (i=0; i<bodyElement.childNodes.length; i++)
{
var currentNode = bodyElement.childNodes[i];
if (currentNode.nodeName.toLowerCase() == "img")
{
bodyElement.removeChild(currentNode);
}
}
}
if (bodyElement.hasChildNodes())
{
for (i=0; i<bodyElement.childNodes.length; i++)
{
var currentNode = bodyElement.childNodes[i];
if (currentNode.nodeName.toLowerCase() == "img")
{
bodyElement.removeChild(currentNode);
}
}
}
Similar effect can be achieved using getElementsByTagName():
// Remove all the top-level <img> elements in the body
var imgElements = bodyElement.getElementsByTagName("img");
for (i=0; i<imgElements.length; i++)
{
var imgElement = imgElements.item[i];
bodyElement.removeChild(imgElement);
}
Attribute nodes
The DOM represents attributes as nodes, and you can always get an element's attributes using the attributes property of an element, as shown here:
// Remove all the top-level <img> elements in the body
var imgElements = bodyElement.getElementsByTagName("img");
for (i=0; i<imgElements.length; i++)
{
var imgElement = imgElements.item[i];
// Print out some information about this element
var msg = "Found an img element!";
var atts = imgElement.attributes;
for (j=0; j<atts.length; j++)
{
var att = atts.item(j);
msg = msg + "\n " + att.nodeName + ": '" + att.nodeValue + "'";
}
alert(msg);
bodyElement.removeChild(imgElement);
}
It's worth noting that the attributes property is actually on the node type, and not specifically on the element type. A little odd, and it won't affect our coding, but it is worth knowing.
While it's certainly possible to work with attribute nodes, it's often easier to use the methods available on the element class to work with attributes. The methods are as follows:
- getAttribute(name) returns the value of the attribute named name .
- removeAttribute(name) removes the attribute named name .
- setAttribute(name, value) creates an attribute named name and sets its value to value .
These three methods don't require us to work directly with attribute nodes. Instead, you can just set and remove attributes and their values with simple string properties.
Text nodes
The last type of node you need to worry about -- at least in working with HTML DOM trees -- is the text node. Almost all of the properties we'll commonly use to work with text nodes are actually available on the node object. In fact, we'll generally use the nodeValue property to get the text from a text node, as shown here:
var pElements = bodyElement.getElementsByTagName("p");
for (i=0; i<pElements.length; i++)
{
var pElement = pElements.item(i);
var text = pElement.firstChild.nodeValue;
alert(text);
}
for (i=0; i<pElements.length; i++)
{
var pElement = pElements.item(i);
var text = pElement.firstChild.nodeValue;
alert(text);
}
A few other methods are specific to text nodes. These deal with adding to or splitting the data in a node:
- appendData(text) adds the text you supply to the end of the text node's existing text.
- insertData(position, text) allows you to insert data in the middle of the text node. It inserts the text you supply at the position indicated.
replaceData(position, length, text) removes the characters starting from the position indicated, of the length indicated, and puts the text you supply to the method in the place of the removed text.
What type of node?
Most of what we've seen so far assumes we already know what type of node we're working with, which isn't always the case. For example, if we're navigating through a DOM tree, and working with the common node types, we might not know whether we've moved to an element or text. We may get all the children of a p element, and be unsure whether we're working with text, or a b element, or perhaps an img element. In these cases, we'll need to figure out what type of node you have before we can do much with it.
Fortunately, it's pretty simple to figure this out. The DOM node type defines several constants, like this:
- Node.ELEMENT_NODE is the constant for the element node type.
- Node.ATTRIBUTE_NODE is the constant for the attribute node type.
- Node.TEXT_NODE is the constant for the text node type.
- Node.DOCUMENT_NODE is the constant for the document node type.
There are a number of other node types, but we'll rarely deal with any but these four when processing HTML. I've also intentionally left out the value for each of these constants, even though the values are defined in the DOM specification; you should never deal directly with the value, since that's what the constants are for!
The nodeType property
We can also use the nodeType property -- which is defined on the DOM node type, so is available to all nodes -- to compare a node to the above constants, as shown here:
var someNode = document.documentElement.firstChild;
if (someNode.nodeType == Node.ELEMENT_NODE)
{
alert("We've found an element node named " + someNode.nodeName);
}
else if (someNode.nodeType == Node.TEXT_NODE)
{
alert("It's a text node; the text is " + someNode.nodeValue);
}
else if (someNode.nodeType == Node.ATTRIBUTE_NODE)
{
alert("It's an attribute named " + someNode.nodeName + " with a value of '" + someNode.nodeValue + "'");
}
This is a pretty simple example, but that's largely the point: getting the type of a node is simple. What's trickier is figuring out what to do with the node once you know what type it is; but with a firm knowledge of what the node, text, attribute, and elements types offer, you're ready to take on DOM programming yourself.
Well, almost.
A wrench in the works
It sounds like the nodeType property is just the ticket to working with nodes -- it allows us to figure out what type of node we're working with, and then write the code to deal with that node. The problem is that the above-defined Node constants don't work properly on Internet Explorer. So, if we use Node.ELEMENT_NODE, Node.TEXT_NODE, or any of the other constants in your code, Internet Explorer will return an error.
Internet Explorer will report this error; anytime we use the Node constants in our JavaScript. Because most of the world still uses Internet Explorer, you'd do well to avoid constructs like Node.ELEMENT_NODE or Node.TEXT_NODE in your code. Even though Internet Explorer 7.0; the latest version of Internet Explorer – does not have this problem. It will be a number of years before Internet Explorer 6.x falls out of heavy use. So avoid using Node ; it's important that your DOM code (and your Ajax apps) work on all the major browsers.
In conclusion
We've learned quite a bit in the last few articles in this series. At this point, you should not sit back and wait for the next article, expecting that I'll go into all sorts of clever uses for the DOM tree. Explore how you can create fancy effects or quick interfaces using the DOM; it is your homework now. Take what you've learned in these last two articles and start to experiment and play around. See if you can create a Web site that feels a bit more like a desktop application, where objects move around on the screen in response to a user's action.
Better yet, throw a border around every object on the screen, so you can see where the objects in the DOM tree are, and start moving things around. Create nodes and append them to existing child lists; remove nodes that have lots of nested nodes; change the CSS style of a node, and see if those changes are inherited by child nodes. The possibilities are limitless, and every time you try something new, you'll learn something new. Enjoy playing around with your Web pages.
Then, in the upcoming final part of this DOM-specific trilogy, I will show you how to incorporate some cool and interesting applications of the DOM into your programming. I'll stop speaking conceptually and explaining the API, and show you some code. Until then, come up with some clever ideas on your own, and see what you can make happen all by yourself.
Labels:
Ajax
|
0
comments
Subscribe to:
Posts (Atom)
Blog Archive
-
►
2013
(1)
- ► September 2013 (1)
-
►
2011
(7)
- ► April 2011 (7)
-
►
2010
(1)
- ► April 2010 (1)
-
▼
2009
(11)
- ► December 2009 (2)
- ► January 2009 (6)
-
►
2007
(3)
- ► October 2007 (3)
Categories
- Ajax (6)
- Buddha (2)
- Buddhism (2)
- Favorite Movie (1)
- First (1)
- Four Noble Truths (1)
- Ganesha (1)
- Hindu Deities (2)
- Hinduism (3)
- Krishna (1)
- Meditation (1)
- Namasthe (1)
- PHP Basics (3)
- power ful (1)
- respecting others (1)
- salutation (1)
- siva (1)
- siva tandava stotram (1)
- Speed up windows (1)
- Spiritual (1)
- Start up Programs (1)
- stotram (1)
- Windows Services (1)
- XP optimization (2)
- XP Services (1)
Powered by Blogger.