Load realplayer.htminto your browser and, aslong as your browser supports plug-ins or ActiveX controls and the RealPlayer plug-in is installed, youshould see something like what is shown
Trang 1if (navigator.plugins[plugInCounter].name.indexOf(“RealPlayer”) >= 0){
plugInInstalled = true;
break;
}}}else{
if (real1.readyState == 4){
plugInInstalled = true;
}}
if (plugInInstalled == false) {window.location.replace(“NoRealPlayerPage.htm”);
}}
If the browser is Firefox, you use a forloop to go through the navigatorobject’s pluginsarray, ing each installed plug-in’s name for the word RealPlayer If this word is found, you set the variableplugInInstalledto trueand break out of the forloop
check-If you find that this is a Microsoft browser, you use the readyStateproperty of the <object/>ment’s Objectobject to see if the ActiveX control is loaded, initialized successfully, and now ready foraction If its value is 4, you know that all systems are ready to go, and you can use the control, so you setthe variable plugInInstalledto true
ele-Finally, the last ifstatement in the function checks to see if plugInInstalledis trueor false If it isfalse, the user is redirected to another page, called NoRealPlayerPage.htm, where you can eitherprovide alternative ways to display the content or provide a link to load the RealPlayer control Let’s cre-ate a simple page to do this
<html>
<head>
<title>No Real Player Installed</title>
</head>
Trang 2<h2>You don’t have the required RealPlayer plug-in</h2>
<p>
You can download the plug-in from
<a href=”http://www.real.com”>Real Player</a>
</p>
</body>
</html>
Save this as NoRealPlayerPage.htm
Finally, back in the realplayer.htmpage, let’s enable the user to select a sound file as well as to startand stop playing it You add the following code to the top of the script block:
<html>
<head>
<object classid=”clsid:CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA” id=”real1”
width=”0” height=”0”>
<param name=”height” value=”0”>
<param name=”width” value=”0”>
var plugInCounter;
for (plugInCounter = 0; plugInCounter < navigator.plugins.length;
Trang 3if (navigator.plugins[plugInCounter].name.indexOf(“RealPlayer”) >= 0){
plugInInstalled = true;
break;
}}}else{
if (real1.readyState == 4){
plugInInstalled = true;
}}
if (plugInInstalled == false) {window.location.replace(“NoRealPlayerPage.htm”);
}}
<param name=”height” value=”0”>
<param name=”width” value=”0”>
</object>
<script type=”text/javascript”>
var fileName = “”;
function butPlay_onclick() {
document.real1.SetSource(“file:///” + fileName);
document.real1.DoPlay();
}function butStop_onclick()
Trang 4var plugInCounter;
for (plugInCounter = 0; plugInCounter < navigator.plugins.length;
plugInCounter++){
if (navigator.plugins[plugInCounter].name.indexOf(“RealPlayer”) >= 0){
plugInInstalled = true;
break;
}}}else{
if (real1.readyState == 4){
plugInInstalled = true;
}}
if (plugInInstalled == false) {window.location.replace(“NoRealPlayerPage.htm”);
}}
<form id=form1 name=form1>
<input type=”button” value=”Play Sound” id=”butPlay” name=”butPlay”
Trang 5You’ve completed your page, so let’s now resave it Load realplayer.htminto your browser and, aslong as your browser supports plug-ins or ActiveX controls and the RealPlayer plug-in is installed, youshould see something like what is shown in Figure 15-9.
Figure 15-9
Click the Browse button and browse to an MP3 sound file (Budd_Eno.mp3is provided with the codedownload, or you can create your own with Real Producer Basic, also available at www.realnetworks.com) Click the Play Sound and Stop Sound buttons to play and stop the sound
So how does this work?
The form in the body of the page contains three form elements The first two of these are just standardbuttons, but the last is an <input/>element of type=”file” This means that a text box and a buttonare displayed When the button is clicked, a Choose File dialog box opens, enabling you to choose the.rafile you want to hear When chosen, this file’s name appears in the text box
You’ve connected the two buttons’ onclickevent handlers and the file control’s onblurevent handler
to three functions, butPlay_onclick(), butStop_onclick(), and file1_onblur(), respectively,which are defined in the script block in the head of the page
In the function file1_onblur(), you set a global variable, fileName, to the value of the file control Inother words, fileNamewill contain the name and path of the file the user has chosen to play The blurevent will fire whenever the user moves focus from the file control to another control or area of the page
In reality, you would perform checks to see whether the file type selected by the user is actually a validsound file
In the other two functions, you access the RealPlayer plug-in or control that you embedded in the page.You use one function to load the file the user selected and play it, and the other function to stop play
In both functions, you access the RealPlayer control by using its name prefixed with document Thescript will work with IE and Firefox, though under IE it’s accessing the ActiveX control defined in
<object/>, and in Firefox it’s accessing the plug-in defined in the <embed/>tag
In the butPlay_onclick()function, you use the SetSource()method of the RealPlayer object Thismethod takes one parameter — the file that you want the RealPlayer plug-in to load So, in the linedocument.real1.SetSource(“file:///” + fileName);
Trang 6you load the file the user specified Next you use the DoPlay()method of the RealPlayer object, whichstarts the playing of the source file.
1. Get a second computer with a clean install of an operating system and browser, then load yourpages on that computer This is the only 100 percent sure way of checking your pages
2. Uninstall the plug-in Depending on how the plug-in or control was installed, there may be anuninstall program for it Windows users can use the Add/Remove programs option in theControl Panel
3. For Firefox, install a different version of the browser For example, if you have Firefox 2
installed, try installing an older version, say Firefox 1 or even a beta version if you can find it.The plug-ins currently installed are not normally available to a browser installed later, thoughthis may not be true all the time
4. With IE, you can only have one version of the browser installed at once However, IE does make
it quite easy to remove ActiveX controls In IE 5+, choose Internet Options from the Tools menu.Click the Settings button under Temporary Internet Files (Browsing History in IE7), followed bythe View Objects button From here you need to right-click the name of the control you wantremoved and select Remove from the pop-up menu
Potential Problems
Plug-ins and ActiveX controls provide a great way to extend a browser’s functionality, but they do so at
a price — compatibility problems Some of the problems you may face are discussed in the following sections
Similar but Not the Same — Differences Between Browsers
Although a plug-in for Firefox and the equivalent ActiveX control for IE may support many similarproperties and methods, you will often find significant, and sometimes subtle, differences
For example, both the plug-in and ActiveX control versions of RealPlayer support the SetSource()method However, while
document.real1.SetSource(“file:///D:\\MyDir\\MyFile.ra”)
Trang 7will work with IE, it will cause problems with the other browsers To work with Firefox and the like,specify the protocol by which the file will be loaded If it is a URL, specify http://, but for a file on auser’s local hard drive, use file:///.
To make the code work across platforms, you must type this:
document.real1.SetSource(“file:///D:\MyDir\MyFile.ra”)
Differences in the Scripting of Plug-ins
When scripting the RealPlayer plug-in for Firefox, you embedded it like this:
<embed name=”real1” id=”real1”
border=”0”
controls=”play”
height=0 width=0 type=”audio/x-pn-realaudio-plugin”>
You then accessed it via script just by typing this:
document.real1.DoPlay()However, if you are scripting a Flash player, you need to add the following attribute to the <embed/>definition in the HTML:
swliveconnect=”true”
Otherwise any attempts to access the plug-in will result in errors
<embed name=”map”
swLiveConnect=truesrc=”topmenu.swf”
width=300 height=200pluginspage=”http://fpdownload.macromedia.com/get/shockwave/cabs/flash/swflash.cab”Version=ShockwaveFlash”>
It’s very important to study any available documentation that comes with a plug-in to check that thereare no subtle problems like this
Differences Between Operating Systems
Support for ActiveX controls varies greatly between different operating systems IE for the Mac supports
it, but not as well as under Win32 operating systems, such as Windows 95, 98, 2000, and XP
You also need to be aware that an ActiveX control written for Win32 will not work on the Mac; you need
to make sure a Mac-specific control is downloaded
IE on the Mac supports plug-ins as well as ActiveX controls; so, for example, Flash is a plug-in on theMac and an ActiveX control on Win32 Clearly, if you want to support both Mac and Windows users,you need to write more complex code
It’s very important to check which operating system the user is running (for example, using the scriptsgiven at the end of Chapter 5) and deal with any problems that may arise
Trang 8Differences Between Different Versions of the Same Plug-in or
ActiveX Control
Creators of plug-ins and controls will often periodically release new versions with new features If youmake use of these new features, you need to make sure not only that the user has the right plug-in orActiveX control loaded, but also that it is the right version
For example, for Flash Player 4 on Win32, the description given by
navigator.plugins[“Shockwave Flash”].description
is Flash 4.0 r7
Using regular expressions, which were introduced in Chapter 8, you could extract the version numberfrom this string:
Trang 9Changes to Internet Explorer 6 Service Pack 1b and ActiveX Controls
For mostly legal reasons, Microsoft is making changes to how ActiveX controls work in IE Now ever a user browses to a page with an ActiveX control, she gets a warning about the control, and bydefault it’s blocked unless she chooses to unblock it There are two ways around this:
when-1. Don’t access any external data or have any <param/>elements in the definition, as the ing example demonstrates:
follow-<object classid=”CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6”></object>
2. Use the new noexternaldataattribute to specify that no external access of data is used
<object noexternaldata=”true” classid=”CLSid:6BF52A52-394A-11d3-B153-00C04F79FAA6”>
<param name=”URL”
❑ You can find detailed information about what plug-ins are installed on your Firefox browser, aswell as their descriptions and types, by using the About Plug-ins option on the Help menu
Trang 10❑ To use script to check if a user has a certain plug-in, you can use the navigatorobject’s ins[]array property For each plug-in installed, there will be a Pluginobject defined in thisarray Each Pluginobject has the properties name, description, filename, and length,which you can use to determine if a plug-in exists on the user’s computer You can also use thenavigatorobject’s mimeTypes[]array property to check if a certain type of file is supported.
plug-❑ Internet Explorer supports ActiveX controls as an alternative to plug-ins These are embeddedinto a web page using the <object/>element You specify which ActiveX control you want byusing the classidattribute If you want to have controls automatically install for users whodon’t have a particular control already installed, you need to specify the codebaseattribute
❑ Any parameters particular to the control are specified by means of the <param/>element,which is inserted between the opening and closing <object>tags
❑ You can check whether a control has loaded successfully using the readyStateproperty of theObjectobject, which returns a number: 0if the control is not installed, 1if it’s still loading, 2if
it has loaded, 3if you can interact with it, and 4if it’s installed and ready for use
❑ Virtually every different type of plug-in and ActiveX control has its own interface, for which thecontrol’s documentation will provide the details You looked briefly at the RealPlayer control byRealNetworks
❑ You also saw that while plug-ins and controls are great for extending functionality, they are ject to potential pitfalls These include differences in the way plug-ins and ActiveX controls arescripted, differences in operating systems, and differences between versions of the same plug-in
Trang 11Ajax and Remote Scripting
Since its inception, the Internet has used a transaction-like communication model A browsersends a request to a server, which sends a response to the browser, on which it (re)loads the page.This is typical HTTP communication, and it was designed to be this way, but this model is rathercumbersome for developers, as it requires our web applications to consist of several pages Theresulting user experience is disjointed and interrupted
In the early 2000s, a movement began to look for and develop new techniques to enhance theuser’s experience, as well as make applications easier to build and maintain These new tech-niques offered performance and usability usually associated with conventional desktop applica-tions It wasn’t long before developers began to refine these processes to offer richer functionality
At the heart of this movement was one language: JavaScript, and its remote scripting ability
What Is Remote Scripting?
Essentially, remote scripting allows client-side JavaScript to request and receive data from a server
without refreshing the web page This technique enables the developer to create an applicationthat is uninterrupted, making only portions of the page reload with new data
The term “remote scripting” is quite large in scope, as a variety of JavaScript techniques can beused These techniques incorporate the use of hidden frames/iframes, dynamically adding
<script/>elements to the document, and/or using JavaScript to send HTTP requests to theserver; the latter has become quite popular in the last couple of years These new techniquesrefresh only portions of a page, both cutting the size of data sent to the browser and making theweb page feel more like a conventional application
What Can It Do?
The concept of remote scripting opens the doors for advanced web applications — ones that mimicdesktop applications in form and in function
Trang 12A variety of commercial web sites employ the use of remote scripting These sites look and behave morelike desktop applications than like web sites, but that is the whole point of remote scripting The mostnotable remote scripting–enabled web applications come from the search giant Google: Google Mapsand Google Suggest.
Google Maps
Designed to compete with existing commercial mapping sites (and using images from its Google Earth),Google Maps (http://maps.google.com) uses remote scripting to dynamically add map images to theweb page When you enter a location, the main page does not reload at all; the images are dynamicallyloaded in the map area Google Maps also enables you to drag the map to a new location, and onceagain, the map images are dynamically added to the map area (see Figure 16-1)
Figure 16-1
Google Suggest
Google Suggest (http://labs.google.com/suggest/) is another Google innovation that employs theuse of remote scripting Upon first glance, it appears to be a normal Google search page When you starttyping, however, a drop-down box displays suggestions for search terms that might interest you To theright of the suggested word or phrase is the number of results the search term returns (see Figure 16-2)
Trang 13Figure 16-2
Ajax
In 2005, Jesse James Garrett wrote an article entitled “Ajax: A New Approach to Web Applications”(www.adaptivepath.com/publications/essays/archives/000385.php) In it, Garrett states thatthe interactivity gap between web and desktop applications is becoming smaller, and he cites Google
Maps and Google Suggest as proof of this He christened the new approach Asynchronous JavaScript +
XML, or Ajax Although the new term was coined in 2005, the underlying methodology of Ajax, which is
remote scripting, has been around for many years In fact, many developers use the terms remote
script-ing and Ajax interchangeably The entire concept of Ajax can be boiled down to client-server
communica-tion — which is remote scripting
For all intents and purposes, when Ajax is mentioned in this chapter, think of remote scripting.
Browser Support
Ajax is limited to the browser that runs the web application, and like every other advanced JavaScriptconcept we’ve covered in this book, Ajax capabilities differ from browser to browser Thankfully, themost common forms of Ajax work in the following browsers:
Trang 14❑ Internet Explorer 5+
❑ Firefox 1+
❑ Opera 9+
❑ Safari 2+
When using hidden frames, a popular Ajax approach, with these browsers, you’ll notice few differences
in the code, as each BOM handles frames the same way (we’ll cover this approach later in the chapter).However, when you start using other forms of Ajax, the differences in code become apparent
Ajax with JavaScript: The XMLHttpRequest
Object
As stated before, there are a variety of ways that you can create Ajax-enabled applications However,probably the most popular Ajax technique is using the JavaScript XMLHttpRequestobject, which is pre-sent in IE 5+, Firefox, Opera, and Safari
Despite its name, you can retrieve other types of data, like plain text, with XMLHttpRequest.
The XMLHttpRequestobject originated as a Microsoft component, called XmlHttp, in the MSXMLlibrary first released with IE 5 It offered developers an easy way to open HTTP connections and retrieveXML data Microsoft improved the component with each new version of MSXML, making it faster andmore efficient
As the popularity of the Microsoft XMLHttpRequestobject grew, Mozilla decided to include its own sion of the object with Firefox The Mozilla version maintained the same properties and methods used inMicrosoft’s ActiveX component, making cross-browser usage possible Soon after, Opera Software andApple copied the Mozilla implementation, thus bringing the easy-to-use object to all modern browsers
ver-Cross-Browser Issues
The XMLHttpRequestobject is no different from other web standards supported by the browsers, and thedifferences can be divided into two camps: the IE 5 and 6 method, and the IE 7, Firefox, Opera, and Safarimethod Thankfully, the two browser types only differ when you need to create an XMLHttpRequestobject After the object’s creation, the remainder of the code is compatible for every browser
IE 5 and IE 6: Using ActiveX
Because the XMLHttpRequestobject originated as a part of the MSXML library, an ActiveX XML parser,instantiating an XMLHttpRequestunder these browsers, requires the creation of an ActiveX object InChapter 14, you created ActiveX objects to traverse the XML DOM Creating an XMLHttpobject isn’tmuch different
var oHttp = new ActiveXObject(“Microsoft.XMLHttp”);
Trang 15This line creates the first version of Microsoft’s XMLHttpRequest There are many other versions ofMicrosoft’s XmlHttp, but Microsoft recommends using one of the following versions:
❑ MSXML2.XmlHttp.6.0
❑ MSXML2.XmlHttp.3.0You want to use the latest version possible when creating an XmlHttpRequestobject; the latest versioncontains bug fixes and enhanced performance The downside to this is that not everyone will have thesame version installed on their computer However, you can write a function that can do this
With the previous version information, you’ll write a function called createXmlHttpRequest()to ate an XMLHttpRequestobject with the latest version supported by the user’s computer
cre-function createXmlHttpRequest(){
var versions = [
cre-To decide what version to use, use a forloop to loop through the elements in the array and then attempt
to create an XMLHttpRequestobject
function createXmlHttpRequest(){
var versions = [
return oHttp;
}catch (error){
//do nothing here}
}//more code here}
Trang 16Atry catchblock is used inside the loop Unfortunately, this is the only way to determine if a sion is installed on the computer If the following line fails:
ver-var oHttp = new ActiveXObject(versions[i]);
the code execution drops to the catchblock, and since nothing happens in this block, the loop iterates tothe next element in the array until a version is found to work or the loop exits If no version is found onthe computer, then the function returns null, like this:
function createXmlHttpRequest()
{
var versions = [
return oHttp;
}catch (error){
//do nothing here}
}return null;
}
Now you don’t have to worry about ActiveX objects to create an object If you call this function, it’ll doall the work for you
var oHttp = createXmlHttpRequest();
The Other Browsers: Native Support
Unlike IE 5 and IE 6, the IE 7, Firefox, Opera, and Safari browsers boast a native implementation of theXMLHttpRequestobject, in that it is an object located in the windowobject Creating an
XMLHttpRequestobject is as simple as calling its constructor
var oHttp = new XMLHttpRequest();
This line creates an XMLHttpRequestobject, which you can use to connect to, and request and receivedata from, a server Unlike the ActiveX object in the previous section, XMLHttpRequest does not havedifferent versions Simply calling the constructor creates the object, and it is ready to use
Trang 17Playing Together
Just as with all other cross-browser problems, a solution can be found to create an XMLHttpRequestobject in a cross-browser way You already wrote the createXmlHttpRequest()function, so you canexpand it to provide cross-browser functionality
function createXmlHttpRequest(){
if (window.XMLHttpRequest){
var oHttp = new XMLHttpRequest();
return oHttp;
}else if (window.ActiveXObject){
var versions = [
return oHttp;
}catch (error){
//do nothing here}
}}return null;
}This new code first checks to see if window.XMLHttpRequestexists If it does, then anXMLHttpRequestobject can be created with the XMLHttpRequestconstructor If this first test fails, thenthe code checks for window.ActiveXObjectfor IE 5 and 6 and tries to create an object with the latestMSXML version If no XMLHttpRequestobject can be created (both for IE 5 and 6 and the otherbrowsers), then the function returns null
The order in which browsers are tested is important; test for window.XMLHttpRequestfirst because
of IE 7, as the browser supports both window.XMLHttpRequestand window.ActiveXObject.
With this function, you can create an XMLHttpRequestobject easily in both browsers For example:var oHttp = createXmlHttpRequest();
Regardless of the user’s browser, if it supports XMLHttpRequest, an object will be created
Trang 18Using the XMLHttpRequest Object
Once you create the XMLHttpRequestobject, you are ready to start requesting data with it The first step
in this process is to call the open()method to initialize the object
oHttp.open(requestType, url, async);
This method accepts three arguments The first, requestType, is a string value consisting of the type ofrequest to make The values can be either GETor POST The second argument is the URL to send therequest to, and the third is a trueor falsevalue indicating whether the request should be made inasynchronous mode We discussed synchronous and asynchronous modes in Chapter 14, but as arefresher, requests made in synchronous mode halt all JavaScript code from executing until a response isreceived from the server
The next step is to send the request; do this with the send()method This method accepts one ment, which is a string that contains the request body to send along with the request GET requests donot contain any information, so you must pass nullas an argument
argu-var oHttp = createXmlHttpRequest();
oHttp.open(“GET”, “http://localhost/myTextFile.txt”, false);
var oHttp = createXmlHttpRequest();
oHttp.open(“GET”, “http://localhost/myTextFile.txt”, false);
Trang 19If the request was successful (the status is 200), then an alert box tells the user that the file was found If
it could not be found (status is 404), an alert box tells the user that the file could not be found Finally, analert box tells the user that an error occurred if the status code happened to be something other than 200
or 404.There are many different HTTP status codes, and checking for every code is not feasible Most of thetime, you should only be concerned with whether your request is successful Therefore, you can cut theprevious code down to this:
var oHttp = createXmlHttpRequest();
oHttp.open(“GET”, “http://localhost/myTextFile.txt”, false);
oHttp.send(null);
if (oHttp.status == 200){
alert(“The text file was found!”);
}else{alert(“An error occurred while attempting to retrieve the file!”);
}This code performs the same basic function, but you check only for a status code of 200and alert ageneric message to the user if an error occurred
Asynchronous Requests
The previous code samples have demonstrated synchronous requests, and the code is simple
Asynchronous requests, on the other hand, are a little more complex and require more code
The key to asynchronous requests is the onreadystatechangeevent handler In asynchronousrequests, the XMLHttpRequestobject exposes a readyStateproperty, which holds a numeric value;each value refers to a specific ready state of the request
❑ 0— The object has been created, but the open()method hasn’t been called
❑ 1— The open()method has been called, but the request hasn’t been sent
❑ 2— The request has been sent
❑ 3— A response has been received from the server
❑ 4— The requested data have been receivedEvery time the readyStatechanges, the readystatechangeevent fires, calling the onreadystate-changeevent handler Most of the time, you should be interested in only one state, 4, as this lets youknow that the request is complete
It is important to note that even if the request was successful, you may not have the information you wanted An error may have occurred on the server’s end of the request (a 404, 500, or some other error) Therefore, you still need to check the status code of the request.
Trang 20Code to handle the readystatechangeevent could look like this:
var oHttp = createXmlHttpRequest();
function oHttp_readyStateChange()
{
if (oHttp.readyState == 4){
if (oHttp.status == 200){
alert(oHttp.responseText);
}else{alert(“An error occurred while retrieving the text file!”);
}}}
//more code here
This code first defines the oHttp_readyStateChange()function, which is assigned to the statechangeevent handler
onready-First check to see if the readyStateis 4, or complete If so, you know that you can use the receiveddata Next, check the statusproperty to make sure that everything’s okay, and then use the
responseTextproperty, which contains the requested file in plain text format, and alert it to the user
To use the oHttp_readyStateChange()function to handle the readystatechangeevent, assign it tothe onreadystatechangeevent handler
var oHttp = createXmlHttpRequest();
function oHttp_readyStateChange()
{
if (oHttp.readyState == 4){
if (oHttp.status == 200){
alert(oHttp.responseText);
}else{alert(“An error occurred while retrieving the text file!”);
}}}
oHttp.open(“GET”, “http://localhost/myTextFile.txt”, true);
oHttp.onreadystatechange = oHttp_readyStateChange;
oHttp.send(null);
In this new code, first call the open()method, set the request type to GET, and specify the desired URL tosend the request to The call to open()differs from earlier; the final argument is set to true, specifying
Trang 21that you want to make an asynchronous request Before calling send(), assign the onreadystatechangeevent handler to the oHttp_readyStateChange()function you previously wrote.
Asynchronous requests certainly do require more code; however, the benefits of using asynchronouscommunication are well worth the effort, as your other JavaScript code continues to run while therequest is made Perhaps a user-defined class that wraps an XMLHttpRequestobject could make asyn-chronous requests easier to use and manage
An XMLHttpRequestobject also has a property called responseXML,which attempts to load the received data into an XML DOM (whereas responseTextjust returns plain text) This is the only way Safari 2 can load XML data into a DOM.
Creating a Remote Scripting Class
Code reuse is an important idea in programming; it is why we define functions to perform specific, mon tasks In Chapter 4, you learned that object-based and object-oriented languages have a differentconstruct for code reuse: a class A class contains properties that contain data, and/or methods that per-form actions with those data
com-In this section, you’re going to wrap an XMLHttpRequestobject into your own class, calledHttpRequest, thereby making it easier for you to make asynchronous requests Before getting into writ-ing the class, we need to discuss a few properties and methods
In the HttpRequestclass, you need to keep track of only one piece of information: the underlyingXMLHttpRequestobject Therefore, this class will have only one property:
❑ request— Contains the underlying XMLHttpRequestobjectThe methods for this class are equally easy to identify
❑ createXmlHttpRequest()— Creates the XMLHttpRequestobject in a cross-browser fashion
It is essentially a copy of the function of the same name written earlier in the chapter
❑ send()— Sends the request to the server
With the properties and methods identified, you can begin to write the class
The HttpRequest Constructor
A class’s constructor defines its properties and performs any logic needed in order for the class to tion properly
func-function HttpRequest(sUrl, fpCallback){
this.request = this.createXmlHttpRequest();
//more code here}
Trang 22The HttpRequestconstructor accepts two arguments The first, sUrl, is a string containing the URL therequest should be sent to The second, fpCallback, is a callback function It will be called when theserver’s response is received (when the request’s readyStateis 4and its statusis 200) The first line
of the constructor initializes the requestproperty, assigning an XMLHttpRequestobject to it
With the requestproperty created and ready to use, it’s time to prepare the request for sending.function HttpRequest(sUrl, fpCallback)
{
this.request = this.createXmlHttpRequest();
this.request.open(“GET”, sUrl, true);
function request_readystatechange(){
//more code here}
this.request.onreadystatechange = request_readystatechange;
}
The first line of the new code uses the XMLHttpRequestobject’s open()method to initialize the requestobject Set the request type to GET, use the sUrlparameter to specify the URL you want to request, andset the request object to use asynchronous mode The next few lines define the request_readystate-change()function Defining a function within a function may seem weird, but it is legal to do so This
function is called a closure The request_readystatechange()function cannot be accessed outside theconstructor It, however, has access to the variables and parameters of the HttpRequestconstructor.This function handles the request object’s readystatechangeevent, and you bind it to do so by assign-ing it to the onreadystatechangeevent handler
function HttpRequest(sUrl, fpCallback)
{
this.request = this.createXmlHttpRequest();
this.request.open(“GET”, sUrl, true);
var tempRequest = this.request;
function request_readystatechange(){
if (tempRequest.readyState == 4){
if (tempRequest.status == 200){
fpCallback(tempRequest.responseText);
}else{alert(“An error occurred trying to contact the server.”);
}}}this.request.onreadystatechange = request_readystatechange;
}
Trang 23These new lines of code may look strange First is the tempRequestvariable and its value This variable
is a pointer to the current object’s requestproperty, and it lets you get around scoping issues Ideally,you would use this.requestinside the request_readystatechange()function However, inFirefox, thispoints to the request_readystatechange()function instead of to the XMLHttpRequestobject, which would cause the code to not function properly So when you see tempRequest, thinkthis.request
Inside the request_readystatechange()function, you see the following line:
fpCallback(tempRequest.responseText);
This line calls the callback function specified by the constructor’s fpCallbackparameter, and you passthe responseTextproperty to this function This will allow the callback function to use the informationreceived from the server
Creating the Methods
There are two methods in this class: one is used inside the constructor, and the other enables you to sendthe request to the server
Cross-Browser XMLHttpRequest Creation Again
The first method is createXmlHttpRequest() The inner workings of cross-browser object creationwere covered earlier in the chapter, so let’s just see the method definition
HttpRequest.prototype.createXmlHttpRequest = function (){
if (window.XMLHttpRequest){
var oHttp = new XMLHttpRequest();
return oHttp;
}else if (window.ActiveXObject){
var versions = [
return oHttp;
}catch (error){
//do nothing here}
}
Trang 24}alert(“Your browser doesn’t support XMLHttp”);
}
In Chapter 4, you learned that class methods are assigned through the prototypeobject This code lows that rule when writing the createXmlHttpRequest()method and the next method
fol-Sending the Request
Sending a request to the server involves the XMLHttpRequestobject’s send()method This send()issimilar, with the difference being that it doesn’t accept arguments
The Full Code
Now that code’s been covered, open up your text editor and type the following:
function HttpRequest(sUrl, fpCallback)
{
this.request = this.createXmlHttpRequest();
this.request.open(“GET”, sUrl, true);
var tempRequest = this.request;
function request_readystatechange(){
if (tempRequest.readyState == 4){
if (tempRequest.status == 200){
fpCallback(tempRequest.responseText);
}else{alert(“An error occurred trying to contact the server.”);
}}}this.request.onreadystatechange = request_readystatechange;
}
HttpRequest.prototype.createXmlHttpRequest = function ()
{
if (window.XMLHttpRequest){
Trang 25var oHttp = new XMLHttpRequest();
return oHttp;
}else if (window.ActiveXObject){
var versions =[
return oHttp;
}catch (error){
//do nothing here}
}}return null;
}HttpRequest.prototype.send = function (){
this.request.send(null);
}Save this file as httprequest.js You’ll use it later in the chapter
The goal of this class was to make asynchronous requests easier to use, so let’s look at a brief code-onlyexample and see if that goal was accomplished
The first thing you need is a function to handle the data received from the request You’ll pass this tion to the HttpRequestconstructor
func-function handleData(sResponseText){
alert(sResponseText);
}Here is the definition of a function called handleData(): it accepts the value of responseText(of theXMLHttpRequestobject) as its only argument In this example, it merely alerts the data passed to it.Now create an HttpRequestobject and send the request
var request = new HttpRequest(“http://localhost/myTextFile.txt”, handleData);
request.send();
Trang 26Pass the text file’s location and the handleData()function to the constructor Then send the requestwith the send()method If the request was successful, handleData()is called.
This looks much easier to use (and reuse) than XMLHttpRequestcode that you have to repeatedlyrewrite You don’t have to worry about the readyStateand statusproperties; the HttpRequestclassdoes it all
Creating a Smar ter Form with
XMLHttpRequest
You’ve probably seen it many times: registering as a user on a web site’s forum or signing up for based e-mail, only to find that your desired user name is taken Of course, you don’t find this out untilafter you’ve filled out the entire form, submitted it, and watched the page reload with new data (not tomention that you’ve lost some of the data you entered) Thankfully, Ajax can soften this frustrating expe-rience and allow the user to know if a user name is taken well in advance of the form’s submission.You can approach this solution in a variety of ways: The easiest to implement provides a link that initi-ates an HTTP request to the server application to check whether the user’s desired information is avail-able to use
web-The form you’ll build will resemble typical forms used today; it will contain the following fields:
❑ Username(validated) — The field where the user types her desired user name
❑ Email(validated) — The field where the user types her e-mail
❑ Password(not validated) — The field where the user types her password
❑ Verify Password(not validated) — The field where the user verifies her password
Note that the Passwordand Verify Passwordfields are just for show in this example Verifying atyped password is certainly something the server application can do; however, it is far more efficient tolet JavaScript perform that verification
Next to the Usernameand Emailfields will be a hyperlink that calls a JavaScript function to query theserver with the HttpRequestclass you built earlier in this chapter The server application is a simplePHP file PHP programming is beyond the scope of this book However, we should discuss how torequest data from the PHP application, as well as look at the response the application sends back toJavaScript
Requesting Information
The PHP application looks for one of two arguments in the query string: usernameand email
To check the availability of a user name, use the usernameargument The URL to do this looks like thefollowing:
http://localhost/formvalidator.php?username=[usernameToSearchFor]
Trang 27When searching for a user name, replace [usernameToSearchFor]with the actual name.
Searching for an e-mail follows the same pattern The e-mail URL looks like this:
http://localhost/formvalidator.php?email=[emailToSearchFor]
The Received Data
A successful request will result in one of two values:
❑ available— Means that the user name and/or e-mail is available for use
❑ not available— Signifies that the user name and/or e-mail is in use and therefore not available
These values are sent to the client in plain text format A simple comparison will enable you to tell theuser whether her user name or e-mail is already in use
Before You Begin
This is a live-code Ajax example; therefore, your computer must meet a few requirements if you wish torun this example
A Web Server
First, you need a web server If you are using Windows 2000 (Server or Professional), Windows XPProfessional, or Windows Server 2003, you have Microsoft’s web server software, Internet InformationServices, freely available to you To install it, open Add/Remove Programs in the Control Panel and clickAdd/Remove Windows Components Figure 16-3 shows the Windows Component Wizard in Windows
XP Professional
Figure 16-3
Trang 28Check the box next to IIS and click Next to install You may need your operating system’s installation
CD to complete the installation
If your operating system isn’t in the preceding list, or you wish to use another method, you can installApache HTTP Server (www.apache.org) This is an open-source web server and can run on a variety ofoperating systems, such as Linux, Unix, and Windows, to list only a few
PHP
PHP is a popular open source server-side scripting language and must be installed on your computer ifyou wish to run PHP scripts You can download PHP in a variety of forms (binaries, Windows installa-tion wizards, and source code) at www.php.net The PHP code used in this example was written in PHP
4, but it should work just fine in version 5
Try It Out XMLHttpRequest Smart Form
Open your text editor and type the following:
text-align: right;
}.submit{text-align: right;
var userValue = document.getElementById(“username”).value;
if (userValue == “”){
alert(“Please enter a user name to check!”);
return;
}var url = “formvalidator.php?username=” + userValue;
var request = new HttpRequest(url, checkUsername_callBack);
request.send();
}function checkUsername_callBack(sResponseText){
Trang 29var userValue = document.getElementById(“username”).value;
if (sResponseText == “available”){
alert(“The username “ + userValue + “ is available!”);
}else{alert(“We’re sorry, but “ + userValue + “ is not available.”);}
}function checkEmail(){
var emailValue = document.getElementById(“email”).value;
if (emailValue == “”){
alert(“Please enter an email address to check!”);
return;
}var url = “formvalidator.php?email=” + emailValue;
var request = new HttpRequest(url, checkEmail_callBack);
request.send();
}function checkEmail_callBack(sResponseText){
var emailValue = document.getElementById(“email”).value;
if (sResponseText == “available”){
alert(“The email “ + emailValue + “ is currently not in use!”);}
else{alert(“I’m sorry, but “ + emailValue + “ is in use by anotheruser.”);
}}
Trang 31You also need to place httprequest.js(the HttpRequestclass) and the formvalidator.phpfile intothe same directory as validate_form.htm.
Now open your browser and navigate to http://localhost/formvalidator.php If everything isworking properly, you should see the text “PHP is working correctly Congratulations!” as in Figure16-4
Figure 16-4
Now point your browser to http://localhost/validate_form.htm, and you should see somethinglike Figure 16-5
Trang 33How It Works
The body of this HTML page is a simple form whose fields are contained within a table Each form fieldexists in its own row in the table The first two rows contain the fields we’re most interested in, theUsernameand Emailfields
ele-The remaining three rows in the table contain two password fields and the Submit button (the smartform currently does not use these fields) The next two rows also contain three columns: the first is thetext describing the field’s function, the second contains the <input/>tag, and the third is empty
<! HTML continued from earlier >
Trang 34The style declarations used are to align the fields to give the form a clean and aligned look.
As stated earlier, the hyperlinks are key to the Ajax functionality, as they call JavaScript functions whenclicked The first function to discuss, checkUsername(), is responsible for retrieving the text the userentered into the Usernamefield, and performing an HTTP request using that information
function checkUsername()
{
var userValue = document.getElementById(“username”).value;
if (userValue == “”){
alert(“Please enter a user name to check!”);
return;
}var url = “formvalidator.php?username=” + userValue;
var request = new HttpRequest(url, checkUsername_callBack);
request.send();
}
Trang 35To retrieve the user name data, use the document.getElementById()method to retrieve the <input/>element and use the valueproperty to retrieve the text typed into the text box Next, check to see if theuser typed any text by comparing the userValuevariable to an empty string (“”) If the text box isempty, the function alerts the user to input a user name and stops the function from processing further.
If we didn’t do this, the application would make unnecessary requests to the server
Next, construct the URL to make the request to the PHP application The final steps in this function are
to create an HttpRequestobject, pass the URL and the callback function, and send the request
The checkUsername_callBack()function executes when the HttpRequestobject receives a completeresponse from the server This function uses the requested information to tell the user whether the username is available Remember, there are two possible values sent from the server, availableand notavailable; therefore, you need only to check for one of these values
function checkUsername_callBack(sResponseText){
var userValue = document.getElementById(“username”).value;
if (sResponseText == “available”){
alert(“The username “ + userValue + “ is available!”);
}else{alert(“We’re sorry, but “ + userValue + “ is not available.”);
}}
If the server’s response is available, the function tells the user that his desired user name is okay touse If not, the alert box says that his user name is taken
Checking the e-mail’s availability is a similar process The checkEmail()function’s purpose is toretrieve the text typed in the Emailfield, and to pass that information to the server application
function checkEmail(){
var emailValue = document.getElementById(“email”).value;
if (emailValue == “”){
alert(“Please enter an email address to check!”);
return;
}var url = “formvalidator.php?email=” + emailValue;
var request = new HttpRequest(url, checkEmail_callBack);
request.send();
}The checkEmail_callBack()function is similar to checkUsername_callBack() The function usesthe same logic, but it is based on the Emailfield’s value
Trang 36function checkEmail_callBack(sResponseText)
{
var emailValue = document.getElementById(“email”).value;
if (sResponseText == “available”){
alert(“The email “ + emailValue + “ is currently not in use!”);
}else{alert(“I’m sorry, but “ + emailValue + “ is in use by another user.”);}
}
Once again, the function checks to see if the server’s response is available, and if so, to let the userknow that the e-mail address is currently not being used If the address is not available, a different mes-sage tells the user his e-mail is not available
Using XMLHttpRequestisn’t the only way to tackle this form, and we’ll look at implementing this a ferent way in a little bit
dif-Creating a Smar ter Form with an IFrame
One of the advantages of XMLHttpRequestis its ease of use You simply create the object, send therequest, and await the server’s response Unfortunately, the JavaScript object does have a downside: Thebrowser does not log a history of requests made with the object Therefore, XMLHttpRequestessentiallybreaks the browser’s Back button
The solution to this problem lies in an older Ajax technique: using hidden frames/iframes to facilitateclient-server communication You must use two frames in order for this method to work properly Onemust be hidden, and one must be visible
Note that when you are using an iframe, the document that contains the iframe is the visible frame.
The hidden-frame technique consists of a four-step process The first step is taken when the user, ingly or unknowingly, initiates a JavaScript call to the hidden frame This can be done by the user click-ing a link in the visible frame, or some other form of user interaction This call is usually nothing morecomplicated than the redirection of the frame to a different web page This redirection automatically trig-gers the second step: the request is sent to the server
know-After the server finishes processing the request, the third step in the process happens: The server sendsthe response to the hidden frame The server’s response is a web page, as this response is sent to a hid-den frame When the response is completely received, the web page in the hidden frame must contactthe visible frame, telling it that the response is complete This is the fourth step, and it is sometimesaccomplished with the window.onloadevent handler of the hidden frame
The example in this section is based upon the one built in the previous section But this time, you’ll use ahidden iframe to facilitate the communication between the browser and the server Before getting intothe code, we should first talk about the data received from the server
Trang 37The Server Response
When we used XMLHttpRequestto get data from the server, we expected only a few words as theserver’s response With this different approach, we know our response must consist of two things:
❑ The data, which must be in HTML format
❑ A mechanism to contact the parent document when the iframe receives the HTML response.Keeping these two things in mind, you can begin to construct the response HTML page
The following example does not work in Safari, as it does not log the history of an iframe.
Trang 38Try It Out Iframe Smart Form
The code for this revised smart form is very similar to the code you used previously with the
XMLHttpRequestexample There are, however, a few slight changes Open up your text editor and typethe following:
text-align: right;
}.submit{text-align: right;
}
#hiddenFrame{
var userValue = document.getElementById(“username”).value;
if (userValue == “”){
alert(“Please enter a user name to check!”);
return;
}var url = “iframe_formvalidator.php?username=” + userValue;
frames[“hiddenFrame”].location = url;
}function checkUsername_callBack(data, userValue){
if (data == “available”){
alert(“The username “ + userValue + “ is available!”);
}else{alert(“We’re sorry, but “ + userValue + “ is not available.”);}
}function checkEmail()
Trang 39{var emailValue = document.getElementById(“email”).value;
if (emailValue == “”){
alert(“Please enter an email address to check!”);
return;
}var url = “iframe_formvalidator.php?email=” + emailValue;
frames[“hiddenFrame”].location = url;
}function checkEmail_callBack(data, emailValue){
if (data == “available”){
alert(“The email “ + emailValue + “ is currently not in use!”);}
else{alert(“We’re sorry, but “ + emailValue + “ is in use by another user.”);
}}