Download - Ajax: A new programming model for the Web
INDEX
Contents
1. Rich Internet Applications
2. AJAX Components
3. Example 1: AJAX Flow
4. Example 2: Modifications
5. DOM: Document Object Model
6. Example 3: Modifications Using DOM
7. Example 4: Autocomplete
8. Prototype: a JavaScript library for Ajax
9. Example 5: Prototype
1
INDEX
Two Splitted Worlds
Rich Desktop Applications
• Difficult to distribute and deploy• Rich user experience• Rapid response to the user• Off-line
Classical Web Applications
• Easy to distribute and deploy• Poor user experience• Delayed responses• On-line
Can we get the best of these two worlds?
2
INDEX
Rich Internet Applications
• Rich user experience
• Easy to distribute and deploy
• Easy to actualize
• Rich user experience
• Rapid response to the user
• Can work off-line
• Multiplatform
3
INDEX
RIA PlatformsAdobe Flash
• Was the creator of the RIA concept• More oriented to graphical designers than to developers
Adobe Flex
• Based on flash but oriented to developers• XML (MXML) + Action Script 3.0
Open Laszlo
• XML (LZX) + ECMAScript• Compiles into Flash or AJAX
Microsoft Silverlight
• XML (XAML) + .NET (web version of WPF: WindowsPresentation Foundation)
Java Web Start
• Autodeployable and updatable applications
JavaFX ????
• JavaFX Script• JavaFX Mobile
AJAX
4
INDEX
AJAX
• Based on standards and not owned by any company
• AJAX stands for Asynchronous JavaScript And XML (termcoined by Jesse James Garret in a famous article)
• AJAX is not new but it was not popular until Google usedit into its products
• Based on the XMLHTTP object introduced in IE5.0 (1999)to allow remote scripting of Outlook Web Access
• All browsers have included their own version of theXMLHTTP object
• Technologies in AJAX:
– (X)HTML and CSS for structure and design– JavaScript as a programming language– DOM (Document Object Model) to dynamically modify
the structure– XML as a data transport language between client and
server (but it can use others such as JSON)
5
INDEX
Classic and AJAX Application Model
(from http://www.adaptivepath.com/ideas/essays/archives/000385.php)
6
INDEX
Classic and AJAX Application Flow
(from http://www.adaptivepath.com/ideas/essays/archives/000385.php)
7
INDEX
XMLHTTP Object
• History:
– 1998, Microsoft presents Remote Scripting to allow, bymeans of an applet, make requests from JS without theuser noticing it
– 1999, IE5.0 incorporates, under ActiveX, theXMLHTTP object that replaces the applet
– 5 years later, and driven by Google, used to create richwebweb applications
• Compatibility:
– As an ActiveX XMLHTTP object in IE from 5 up to 7– As a native JS XMLHttpRequest object in Firefox (≥
1.0), Netscape (≥ 7.1), Opera (≥ 8.0), Safari (≥ 1.2),IE 7, Konqueror, Opera Mobile, Nokia Web Browser, ...
• It is the heart of an AJAX application because it allowsto asynchronically make requests to the server withoutchanging the page
8
INDEX
Using the XMLHTTP Object
To make a request to the server from JavaScript using theXMLHTTP Object, one must follow these steps:
1. Obtain the XMLHTTP object
2. Configure and open the connection with the server
3. Define a JavaScript callback function to administer theevolution of the request (because it is asynchronous)
4. Send the request and data to the server
5. The before mentioned function must:
• Administer the state of the request• Get the result from the server• Process the result (i.e. updating the page)
9
INDEX
Obtaining the XMLHTTP object1 funct ion getXHR ( ) {2 r e q = f a l s e ;
3 i f ( window . XMLHttpRequest ) {4 r e q = new XMLHttpRequest ( ) ;
5 } e l s e {6 i f ( A c t i v e X O b j e c t ) {7 m s V e r s i o n s = [ ”MSXML2. XMLHttp5 . 0 ” , ”MSXML2. XMLHttp4 . 0 ” ,
8 ”MSXML2. XMLHttp3 . 0 ” , ”MSXML2. XMLHttp ” ,
9 ” M i c r o s o f t . XMLHttp” ] ;
10 f o r ( var i =0; i<m s V e r s i o n s . l e n g t h ; i ++) {11 t r y {12 r e q = new A c t i v e X O b j e c t ( m s V e r s i o n s [ i ] ) ;
13 return r e q ;
14 } catch ( e ) {}15 }16 }17 }18 return r e q ;
19 }
10
INDEX
XMLHTTP Object MethodsThe methods of the XMLHTTP object are:
open It does not ope the connection to the server butconfigures the request and leaves it prepared to be sent.Its parameters are:
method string with the method used to make the request(”GET”or ”POST”)
url string with the url of the resource. It can be relativeto the current document or absolute. If the method is”GETıt must include the parameters.
asynchronous? boolean that indicates whether the re-quest will be processed asynchronously (true) or not(false).
user optional string to authenticate with the server.password needed if user is defined.
send This is the method that actually connects to the servermaking the request.It has a parameter which is used to pass parameters if therequest method is ”POST”.If no parameters are sent or method is ”GET”one can usethe special value null.
abort Seldom used, aborts the processing of an already sentrequest.
11
INDEX
setRequestHeader defines a request header. It has twostring parameters:
key name of the headervalue its value
getResponseHeader gets the value of a response header asa string.
getAllResponseHeaders all the headers in a multiline string.It can be splitted using .split("\r?\n") and then split-ted again with .split(":")
12
INDEX
XMLHTTP Object PropertiesSome properties of the XMLHTTP Object are used to admi-nister the request:
readyState Read-only property that represents the state ofthe request:
0 Not initialized (XMLHTTP created but not ope-ned)
1 Configured (opened but not sent)2 Sending (sent or being sent but no response has
yet been received)3 Interactive (we have got the header response but
the content is being received)4 Completed (we have access to the full response)
status HTTP response code (available when readyState is 4)200 The request has been processed without problems400 Invalid request sent (e.g. bad request headers or
POST data)403 Access to the resource is not permitted404 URL not found on the server405 Method not accepted (some problem processing
GET or POST)414 URL too long500 Server internal error503 Server temporally unavailable
13
INDEX
statusText read-only string that describes the status
responseText read-only string with the contents of the res-ponse (its value only has sense when readyState is 4 andstatus is 200)
responseXML if the response is valid XML, this property isthe XML native JavaScript object that can be processeswith the DOM API.
onreadystatechange this property allows configuring thecallback function that will be called each time thereadyState property changes its value.This property can be defined before or after invoking openbut before invoking send.
// Option 1
funct ion p r o c e s s R e q u e s t ( ) {. . .
} ;
x h r . o n r e a d y s t a t e c h a n g e = p r o c e s s R e q u e s t ;
// Opt ion 2
x h r . o n r e a d y s t a t e c h a n g e = funct ion ( ) {. . . . .
} ;
14
INDEX
Example 1: AJAX Flow
• This example shows the activation of theonreadystatechange function
• Extracted from the book Pragmatic Ajax (netbeaned inAjax Netbeans repository)
• Question: Why does the alert with the messageexecutes twice?
1 <html>2 <head>3 <s c r i p t type=” t e x t / j a v a s c r i p t ”>
4 v a r x h r ;
5
6 f u n c t i o n modifyPage ( ) { . . . }7 </ s c r i p t>8 </head>9 <body>
10 <button o n c l i c k=” modifyPage ( ) ”>C l i c k Me</ button>11 </body>12 </html>
15
INDEX
Example1: JavaScript Code
1 var x h r ;2 funct ion modifyPage ( ) {3 t r y {4 x h r = new A c t i v e X O b j e c t (” Msxml2 .XMLHTTP” ) ;5 a l e r t (” Msxml2 .XMLHTTP A c t i v e X O b j e c t c r e a t e d ” ) ;6 } catch ( e ) {7 t r y {8 x h r = new A c t i v e X O b j e c t (” M i c r o s o f t .XMLHTTP” ) ;9 a l e r t (” M i c r o s o f t .XMLHTTP A c t i v e X O b j e c t c r e a t e d ” ) ;
10 } catch (E) {11 x h r = f a l s e ;12 }13 }14 i f ( ! x h r && typeof XMLHttpRequest != ’ u n d e f i n e d ’ ) {15 x h r = new XMLHttpRequest ( ) ;16 a l e r t (” XMLHttpRequest Object c r e a t e d ” ) ;17 }18 x h r . open (”GET” , ” . / getMessage ” , ” true ” ) ;19 a l e r t (” Open method c a l l e d ” ) ;20 x h r . s e t R e q u e s t H e a d e r (” User−Agent ” , ”my b r o w s e r ” ) ;21 a l e r t (” Request h e a d e r s e t t e d ” ) ;22 x h r . o n r e a d y s t a t e c h a n g e = funct ion ( ) {23 a l e r t (” S t a t e : ” + x h r . r e a d y S t a t e + ”” ) ;24 i f ( x h r . r e a d y S t a t e != 4) return ;25 i f ( x h r . s t a t u s == 200) {26 a l e r t (” The message i s :\n” + x h r . r e s p o n s e T e x t ) ;27 } e l s e28 a l e r t (” E r r o r p r o c e s s i n g r e s p o n s e . S t a t u s=” + x h r . s t a t u s ) ;29 }30 x h r . send ( n u l l ) ;31 }
16
INDEX
Example1: Java Servlet Code1 package a j a x i a n . book . e x p l a i n e d . s e r v l e t ;
2
3 import j a v a . i o .∗ ;
4 import j a v a x . s e r v l e t .∗ ;
5 import j a v a x . s e r v l e t . h t t p .∗ ;
6
7 p u b l i c c l a s s M e s s a g e S e r v l e t extends H t t p S e r v l e t {8
9 @ O v e r r i d e
10 p u b l i c void doGet ( H t t p S e r v l e t R e q u e s t r e q u e s t ,
11 H t t p S e r v l e t R e s p o n s e r e s p o n s e )
12 throws IOExcept ion , S e r v l e t E x c e p t i o n {13
14 r e s p o n s e . se tContentType ( ” t e x t / p l a i n ” ) ;
15 r e s p o n s e . s e t H e a d e r ( ”Cache−C o n t r o l ” , ”no−cache ” ) ;
16 r e s p o n s e . g e t W r i t e r ( ) . w r i t e ( ” H e l l o from th e s e r v e r ” ) ;
17
18 }19 }
17
INDEX
Accessing and modifying the page
• In the past example we have only shown alerts but we havenot accessed the page content.
• Usually AJAX applications modify the current content ofthe page with the response obtained from the server.
• To do so, we need:
1. parts of the page (tipically a <div>) must be uniquelyidentifiable (using its id attribute’s value).
2. to modify the content we can use the innerHTML pro-perty of the element (simpler than pure DOM nodesmanipulation)
3. the AJAX request must be sent when we are sure the<div>) is loaded.If one wants the request to be done when the page isbeing loaded, one must use the onload method of thebody.
4. the XMLHTTP object must be a global variable of thepage, so it can be accessed from different functions.
18
INDEX
Example 2: AJAX Modification
index.html1 <html>2 <head>3 <s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” x h r . j s ”></ s c r i p t>4 <s c r i p t type=” t e x t / j a v a s c r i p t ”>\b e g i n{ l s t l i s t i n g } [ l a n g u a g e=J a v a S c r i p t , numbers=l e f t , b a s i c s t y l e =\ t i n y ]5 v a r x h r ;67 f u n c t i o n modifyPage ( ) {8 x h r = getXHR ( ) ;9 x h r . open ( ”GET” , ” . / getMessage ” , ” t r u e ” ) ;
10 x h r . s e t R e q u e s t H e a d e r ( ” User−Agent ” , ”my b r o w s e r ” ) ;11 x h r . o n r e a d y s t a t e c h a n g e= f u n c t i o n ( ) {12 i f ( x h r . r e a d y S t a t e != 4) r e t u r n ;13 i f ( x h r . s t a t u s == 200) {14 document . getE lementBy Id ( ” message ” ) . innerHTML = x h r . r e s p o n s e T e x t ;15 } e l s e {16 a l e r t ( ” E r r o r p r o c e s s i n g r e s p o n s e w i t h s t a t u s ” + x h r . s t a t u s ) ;17 }18 }19 x h r . send ( n u l l ) ;20 }21 </ s c r i p t>22 </head>23 <body>24 <div i d=” message ”></ div>25 <button o n c l i c k=” modifyPage ( ) ”>C l i c k Me</ button>26 </body>27 </html>
19
INDEX
DOM: Document Object Model
• DOM is a W3C standard that allows the processing ofXML documents (HTML is not XML but DOM is alsoported to it)
• It defines common interfaces to traverse and manipulate ahierarchical representation of the HTML/XML
• Implemented in different languages: Java, JavaScript,Python, PHP, ...
• In JavaScript we can use the DOM to:
– Manipulate the results obtained from the server (if theyare expressed in XML)
– Manipulate the page by accessing the objectwindow.document (or simply document)
20
INDEX
Example 3: AJAX Modification using DOM
index.html1 <html>2 <head>3 <s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” x h r . j s ”></ s c r i p t>4 <s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” t e x t−u t i l s . j s ”></ s c r i p t>5 <s c r i p t type=” t e x t / j a v a s c r i p t ”>6 v a r x h r ;78 f u n c t i o n modifyPage ( ) {9 x h r = getXHR ( ) ;
10 x h r . open ( ”GET” , ” . / getMessage ” , ” t r u e ” ) ;11 x h r . s e t R e q u e s t H e a d e r ( ” User−Agent ” , ”my b r o w s e r ” ) ;12 x h r . o n r e a d y s t a t e c h a n g e= f u n c t i o n ( ) {13 i f ( x h r . r e a d y S t a t e != 4) r e t u r n ;14 i f ( x h r . s t a t u s == 200) {15 r e p l a c e T e x t ( document . getE lementBy Id ( ” message ” ) , x h r . r e s p o n s e T e x t ) ;16 } e l s e {17 a l e r t ( ” E r r o r p r o c e s s i n g r e s p o n s e w i t h s t a t u s ” + x h r . s t a t u s ) ;18 }19 }20 x h r . send ( n u l l ) ;21 }22 </ s c r i p t>23 </head>24 <body>25 <div i d=” message ”></ div>26 <button o n c l i c k=” modifyPage ( ) ”>C l i c k Me</ button>27 </body>28 </html>
21
INDEX
Example 3: AJAX Modification using DOM
text-utils.js123 funct ion r e p l a c e T e x t ( e l , t e x t ) {4 i f ( e l != n u l l ) {5 c l e a r T e x t ( e l ) ;6 var newNode = document . c reateTextNode ( t e x t ) ;7 e l . a p p e n d C h i l d ( newNode ) ;8 }9 }
1011 funct ion c l e a r T e x t ( e l ) {12 i f ( e l != n u l l ) {13 i f ( e l . c h i l d N o d e s ) {14 f o r ( var i =0; e l . c h i l d N o d e s . l e n g t h ; i ++) {15 var c h i l d N o d e = e l . c h i l d N o d e s [ i ] ;16 e l . r e m o v e C h i l d ( c h i l d N o d e ) ;17 }18 }19 }20 }2122 funct ion getText ( e l ) {23 var t e x t = ” ” ;24 i f ( e l != n u l l ) {25 i f ( e l . c h i l d N o d e s ) {26 f o r ( var i = 0 ; e l . c h i l d N o d e s . l e n g t h ; i ++) {27 var c h i l d N o d e = e l . c h i l d N o d e s [ i ] ;28 i f ( c h i l d N o d e . nodeValue != n u l l ) {29 t e x t = t e x t + c h i l d N o d e . nodeValue ;30 }31 }32 }33 }34 }
22
INDEX
Example: Autocomplete
• An example based (minor modifications) on the J2EEBlueprints Samples from Sun.
• When filling a text entry, generates a pop-up with possiblecompletions for the already entered characters
• Hands-on-project: modify the example to allow the selec-tion of a name by keyboard and not by mouse.
23
INDEX
Example: Autocomplete
index.jsp1 <html>2 <head>3 <s t y l e type=” t e x t / c s s ”>45 . s e l e c t e d {6 background : #7A8AFF ;7 c o l o r : #FFFAFA ;8 }9
10 . u n s e l e c t e d {11 background : #FFFAFA ;12 c o l o r : #000000;13 }14 </ s t y l e>15 <s c r i p t type=” t e x t / j a v a s c r i p t ”>16 var i s I E ;17 var r e q ;18 var names ;19 var t a r g e t ;2021 funct ion getElementX ( e l em en t ){22 var t a r g e t L e f t = 0 ;23 i f ( e l em en t . o f f s e t P a r e n t ) {
24
INDEX
24 whi le ( e l em en t . o f f s e t P a r e n t ) {25 t a r g e t L e f t += el em ent . o f f s e t L e f t ;26 e l em en t = e l em en t . o f f s e t P a r e n t ;27 }28 } e l s e i f ( e l em en t . x ) {29 t a r g e t L e f t += el em ent . x ;30 }31 return t a r g e t L e f t ;32 }3334 funct ion getElementY ( e l em en t ){35 var t a r g e t T o p = 0 ;36 i f ( e l em en t . o f f s e t P a r e n t ) {37 whi le ( e l em en t . o f f s e t P a r e n t ) {38 t a r g e t T o p += e le me nt . o f f s e t T o p ;39 e l em en t = e l em en t . o f f s e t P a r e n t ;40 }41 } e l s e i f ( e l em en t . y ) {42 t a r g e t T o p += e le me nt . y ;43 }44 return t a r g e t T o p ;45 }4647 funct ion i n i t ( ) {48 t a r g e t = document . getE lementBy Id (” complete−f i e l d ” ) ;49 var popup = document . getE lementBy Id (” menu−popup ” ) ;50 popup . s t y l e . top = ( getElementY ( t a r g e t ) + t a r g e t . o f f s e t H e i g h t ) + ” px ” ;51 popup . s t y l e . l e f t = getElementX ( t a r g e t ) + ” px ” ;52 }53
25
INDEX
54 funct ion i n i t R e q u e s t ( u r l ) {55 i f ( window . XMLHttpRequest ) {56 r e q = new XMLHttpRequest ( ) ;57 } e l s e i f ( window . A c t i v e X O b j e c t ) {58 i s I E = true ;59 r e q = new A c t i v e X O b j e c t (” M i c r o s o f t .XMLHTTP” ) ;60 }61 }6263 funct ion doComplet ion ( ) {64 var u r l = ” a u t o c o m p l e t e ? a c t i o n=complete&i d =” + e s c a p e ( t a r g e t . v a l u e ) ;65 i n i t R e q u e s t ( u r l ) ;66 r e q . o n r e a d y s t a t e c h a n g e = p r o c e s s R e q u e s t ;67 r e q . open (”GET” , u r l , true ) ;68 r e q . send ( n u l l ) ;69 }7071 funct ion p r o c e s s R e q u e s t ( ) {72 i f ( r e q . r e a d y S t a t e == 4) {73 i f ( r e q . s t a t u s == 200) {74 p a r s e M e s s a g e s ( ) ;75 } e l s e i f ( r e q . s t a t u s == 204){76 c l e a r T a b l e ( ) ;77 }78 }79 }8081 funct ion p a r s e M e s s a g e s ( ) {82 i f ( ! names ) {83 names = document . getE lementBy Id (” names ” ) ;
26
INDEX
84 }85 c l e a r T a b l e ( ) ;86 var employees = r e q . responseXML . getElementsByTagName (” employees ” ) [ 0 ] ;87 f o r ( l o o p = 0 ; l o o p < employees . c h i l d N o d e s . l e n g t h ; l o o p++) {88 var employee = employees . c h i l d N o d e s [ l o o p ] ;89 var f i r s t N a m e = employee . getElementsByTagName (” f i r s t N a m e ” ) [ 0 ] ;90 var lastName = employee . getElementsByTagName (” lastName ” ) [ 0 ] ;91 var e m p l o y e e I d = employee . getElementsByTagName (” i d ” ) [ 0 ] ;92 appendEmployee ( f i r s t N a m e . c h i l d N o d e s [ 0 ] . nodeValue ,93 lastName . c h i l d N o d e s [ 0 ] . nodeValue ,94 e m p l o y e e I d . c h i l d N o d e s [ 0 ] . nodeValue ) ;95 }96 }9798 funct ion c l e a r T a b l e ( ) {99 i f ( names ) {
100 f o r ( l o o p = names . c h i l d N o d e s . l e n g t h −1; l o o p >= 0 ; loop−−) {101 names . r e m o v e C h i l d ( names . c h i l d N o d e s [ l o o p ] ) ;102 }103 }104 }105106 funct ion appendEmployee ( f i r s t N a m e , lastName , e m p l o y e e I d ) {107 var f i r s t N a m e C e l l ;108 var l a s t N a m e C e l l ;109 i f ( i s I E ) {110 row = names . i n s e r t R o w ( names . rows . l e n g t h ) ;111 nameCel l = row . i n s e r t C e l l ( 0 ) ;112 } e l s e {113 row = document . c r e a t e E l e m e n t (” t r ” ) ;
27
INDEX
114 nameCel l = document . c r e a t e E l e m e n t (” td ” ) ;115 row . a p p e n d C h i l d ( nameCel l ) ;116 names . a p p e n d C h i l d ( row ) ;117 }118 row . s e t A t t r i b u t e (” b o r d e r ” , ” 0 ” ) ;119 nameCel l . s e t A t t r i b u t e (” onmouseout ” , ” t h i s . c lassName =’ u n s e l e c t e d ’ ; ” ) ;120 nameCel l . s e t A t t r i b u t e (” onmouseover ” , ” t h i s . c lassName =’ s e l e c t e d ’ ; ” ) ;121 nameCel l . s e t A t t r i b u t e (” b g c o l o r ” , ”#FFFAFA ” ) ;122 nameCel l . s e t A t t r i b u t e (” b o r d e r ” , ” 0 ” ) ;123 var l i n k E l e m e n t = document . c r e a t e E l e m e n t (” a ” ) ;124 l i n k E l e m e n t . s e t A t t r i b u t e (” s t y l e ” , ” t e x t−d e c o r a t i o n : none ” ) ;125 l i n k E l e m e n t . s e t A t t r i b u t e (” h r e f ” , ” a u t o c o m p l e t e ? a c t i o n=l o o k u p&i d =” + e m p l o y e e I d ) ;126 var nameFontElement = document . c r e a t e E l e m e n t (” f o n t ” ) ;127 nameFontElement . s e t A t t r i b u t e (” s i z e ” , ”+1”);128 nameFontElement . s e t A t t r i b u t e (” c o l o r ” , ” b l a c k ” ) ;129 nameFontElement . a p p e n d C h i l d ( document . c reateTextNode ( f i r s t N a m e + ” ” + lastName ) ) ;130 l i n k E l e m e n t . a p p e n d C h i l d ( nameFontElement ) ;131 nameCel l . a p p e n d C h i l d ( l i n k E l e m e n t ) ;132 }133 </ s c r i p t>134 <t i t l e>Auto−Complet ion u s i n g Asynchronous J a v a S c r i p t and XML (AJAX)</ t i t l e>135 </head>136 <body onload=” i n i t ( ) ”>137138 <h1>Auto−Complet ion u s i n g Asynchronous J a v a S c r i p t and XML (AJAX)</h1>139 <hr />140 <p>141 This example shows how you can do r e a l t ime auto−c o m p l e t i o n u s i n g142 AJAX i n t e r a c t i o n s .143 </p>
28
INDEX
144 <p>145 I n t he form below e n t e r a name . P o s s i b l e names t h a t w i l l be completed146 a r e d i s p l a y e d beneath t he form .147 C l i c k on one o f the s e l e c t i o n s to s e e th e employee d e t a i l s .148 Try t y p i n g " ; Greg" ; , " ; Murray" ; , " ; Jones" ; , o r149 " ; Cindy" ; .150 </p>151152 <form name=” a u t o f i l l f o r m ” act ion=” a u t o c o m p l e t e ” method=” g e t ”>153 <input type=” h i d d e n ” name=” a c t i o n ” value=” lookupbyname ”/>154 <tab le border=”0” ce l lpadd ing=”5” c e l l s p a c i n g=”0”>155 <t r>156 <td><b>Employee Name :</b></ td>157 <td>158 <input type=” t e x t ”159 s i z e=”20”160 i d=” complete−f i e l d ”161 name=” i d ”162 onkeyup=” doComplet ion ( ) ; ”>163 </ td>164 <td a l i g n=” l e f t ”>165 <input i d=” s u b m i t b t n ” type=” Submit ” value=” Lookup Employee ”>166 </ td>167 </ t r>168 </ tab le>169 </ form>170 <div s t y l e=” p o s i t i o n : a b s o l u t e ; top : 1 7 0 px ; l e f t : 1 4 0 px ” i d=”menu−popup ”>171 <tab le i d=”names”172 bgcolor=”#FFFAFA”173 border=”1”
29
INDEX
174 b o r d e r c o l o r=” b l a c k ”175 c e l l s p a c i n g=”0”176 ce l lpadd ing=”0”/>177 </ div>178 </body>179 </html>
30
INDEX
Example: Autocomplete
AutocompleteServlet.jsp1 package com . sun . j 2 e e . b l u e p r i n t s . b p c a t a l o g . a j a x ;23 import j a v a . i o .∗ ;4 import j a v a x . s e r v l e t .∗ ;5 import j a v a x . s e r v l e t . h t t p .∗ ;6 import j a v a . u t i l .∗ ;78 p u b l i c c l a s s A u t o c o m p l e t e S e r v l e t extends H t t p S e r v l e t {9
10 p r i v a t e S e r v l e t C o n t e x t c o n t e x t ;11 p r i v a t e HashMap employees = new HashMap ( ) ;1213 p u b l i c void i n i t ( S e r v l e t C o n f i g c o n f i g ) throws S e r v l e t E x c e p t i o n {14 t h i s . c o n t e x t = c o n f i g . g e t S e r v l e t C o n t e x t ( ) ;15 employees . put ( ”1” , new EmployeeBean ( ”1” , ” Greg ” , ” Murray ” ) ) ;16 employees . put ( ”2” , new EmployeeBean ( ”2” , ” Greg ” , ”Murphy” ) ) ;17 employees . put ( ”3” , new EmployeeBean ( ”3” , ” George ” , ”Murphy” ) ) ;18 employees . put ( ”4” , new EmployeeBean ( ”4” , ” George ” , ” Murray ” ) ) ;19 employees . put ( ”5” , new EmployeeBean ( ”5” , ” P e t e r ” , ” Jones ” ) ) ;20 employees . put ( ”6” , new EmployeeBean ( ”6” , ”Amber” , ” Jones ” ) ) ;21 employees . put ( ”7” , new EmployeeBean ( ”7” , ”Amy” , ” Jones ” ) ) ;22 employees . put ( ”8” , new EmployeeBean ( ”8” , ”Bee” , ” Jones ” ) ) ;23 employees . put ( ”9” , new EmployeeBean ( ”9” , ” Beth ” , ” Johnson ” ) ) ;
31
INDEX
24 employees . put ( ”10” , new EmployeeBean ( ”10” , ” Cindy ” , ” Johnson ” ) ) ;25 employees . put ( ”11” , new EmployeeBean ( ”11” , ” Cindy ” , ”Murphy” ) ) ;26 employees . put ( ”12” , new EmployeeBean ( ”12” , ”Duke” , ” Hazerd ” ) ) ;27 }2829 p u b l i c void doGet ( H t t p S e r v l e t R e q u e s t r e q u e s t , H t t p S e r v l e t R e s p o n s e r e s p o n s e )30 throws IOExcept ion , S e r v l e t E x c e p t i o n {3132 S t r i n g a c t i o n = r e q u e s t . g e t P a r a m e t e r ( ” a c t i o n ” ) ;33 S t r i n g t a r g e t I d = r e q u e s t . g e t P a r a m e t e r ( ” i d ” ) ;34 S t r i n g B u f f e r sb = new S t r i n g B u f f e r ( ) ;35 i f ( t a r g e t I d != n u l l ) {36 t a r g e t I d = t a r g e t I d . t r i m ( ) . toLowerCase ( ) ;37 }38 boolean namesAdded = f a l s e ;39 i f ( ” complete ” . e q u a l s ( a c t i o n ) ) {40 I t e r a t o r i t = employees . k e y S e t ( ) . i t e r a t o r ( ) ;41 whi le ( i t . hasNext ( ) ) {42 S t r i n g i d = ( S t r i n g ) i t . n e x t ( ) ;43 EmployeeBean e = ( EmployeeBean ) employees . g e t ( i d ) ;44 // s imple matching only f o r s t a r t o f f i r s t or l a s t name45 i f ( ( e . g e t F i r s t N a m e ( ) . toLowerCase ( ) . s t a r t s W i t h ( t a r g e t I d ) | |46 e . getLastName ( ) . toLowerCase ( ) . s t a r t s W i t h ( t a r g e t I d ) ) &&47 ! t a r g e t I d . e q u a l s ( ”” ) ) {48 sb . append ( ”<employee>” ) ;49 sb . append ( ”<id>” + e . g e t I d ( ) + ”</id>” ) ;50 sb . append ( ”<f i r s t N a m e>” + e . g e t F i r s t N a m e ( ) + ”</f i r s t N a m e>” ) ;51 sb . append ( ”<lastName>” + e . getLastName ( ) + ”</lastName>” ) ;52 sb . append ( ”</employee>” ) ;53 namesAdded = true ;
32
INDEX
54 }55 }56 i f ( namesAdded ) {57 r e s p o n s e . se tContentType ( ” t e x t / xml ” ) ;58 r e s p o n s e . s e t H e a d e r ( ”Cache−C o n t r o l ” , ”no−cache ” ) ;59 r e s p o n s e . g e t W r i t e r ( ) . w r i t e ( ”<employees>” + sb . t o S t r i n g ( ) + ”</employees>” ) ;60 } e l s e {61 // noth ing to show62 r e s p o n s e . s e t S t a t u s ( H t t p S e r v l e t R e s p o n s e . SC\ NO\ CONTENT ) ;63 }64 }65 i f ( ” lookupbyname ” . e q u a l s ( a c t i o n ) ) {66 I t e r a t o r i t = employees . k e y S e t ( ) . i t e r a t o r ( ) ;67 A r r a y L i s t names = new A r r a y L i s t ( ) ;68 whi le ( i t . hasNext ( ) ) {69 S t r i n g i d = ( S t r i n g ) i t . n e x t ( ) ;70 EmployeeBean e = ( EmployeeBean ) employees . g e t ( i d ) ;71 // s imple matching only f o r s t a r t o f f i r s t or l a s t name72 i f ( e . g e t F i r s t N a m e ( ) . toLowerCase ( ) . s t a r t s W i t h ( t a r g e t I d ) | |73 e . getLastName ( ) . toLowerCase ( ) . s t a r t s W i t h ( t a r g e t I d ) ) {74 names . add ( e ) ;75 }76 }77 i f ( names . s i z e ( ) > 0) {78 r e q u e s t . s e t A t t r i b u t e ( ” employees ” , names ) ;79 }80 c o n t e x t . g e t R e q u e s t D i s p a t c h e r ( ”/ employees . j s p ” ) . f o r w a r d ( r e q u e s t , r e s p o n s e ) ;81 } e l s e i f ( ” l o o k u p ” . e q u a l s ( a c t i o n ) ) {82 // put the t a r g e t employee in the r e q eu s t scope to d i s p l a y83 i f ( ( t a r g e t I d != n u l l ) && employees . c o n t a i n s K e y ( t a r g e t I d . t r i m ( ) ) ) {
33
INDEX
84 r e q u e s t . s e t A t t r i b u t e ( ” employee ” , employees . g e t ( t a r g e t I d ) ) ;85 c o n t e x t . g e t R e q u e s t D i s p a t c h e r ( ”/ employee . j s p ” ) . f o r w a r d ( r e q u e s t , r e s p o n s e ) ;86 } e l s e {87 c o n t e x t . g e t R e q u e s t D i s p a t c h e r ( ”/ e r r o r . j s p ” ) . f o r w a r d ( r e q u e s t , r e s p o n s e ) ;88 }89 }90 }91 }
34
INDEX
Example: Autocomplete
employees.jsp1 <%@ t a g l i b p r e f i x=” c ” u r i=” h t t p : / / j a v a . sun . com/ j s p / j s t l / c o r e ” %>23 <html>4 <head>5 </head>6 <body>7 <h1>Search R e s u l t s</h1>8 <hr />9
10 <c : choose>11 <c : when t e s t=”${ r e q u e s t S c o p e . employees == n u l l }”>12 <p><font s i z e=”+2” c o l o r=” r e d ”>Unable to l o c a t e any employees .</ font></p>13 </ c : when>14 <c : o t h e r w i s e>15 <c : f o r E a c h var=” employee ” b e g i n=”0” i t e m s=”${ r e q u e s t S c o p e . employees}”>16 <p><a hre f=” a u t o c o m p l e t e ? a c t i o n=lo o k u p&i d=${employee . i d}”>17 ${employee . f i r s t N a m e} ${employee . lastName}18 </a>19 </p>20 </ c : f o r E a c h>21 </ c : o t h e r w i s e>22 </ c : choose>23 <br />
35
INDEX
24 <p>25 <a hre f=” i n d e x . j s p ”>Go back to th e a p p l i c a t i o n home</a>.26 </p>27 </body>28 </html>
36
INDEX
Prototype
• Trying to program in JavaScript without any library isalmost suicidal
– There are subtle differences among the implementationsof JS in the different browsers
– Programming in JavaScript is tricky (e.g. it has objectsbut no classes nor inheritance)
– (the language has some flaws but it was a ”hack thatgot shipped”)
• Prototype is a fairly broad library that upgrades”the lan-guage
– makes common tasks easier (mainly Ajax oriented)– provides ways to implement Java-style inheritance– extends HTML DOM elements with new properties and
methods– provides utilities for working with JSON (Java Script
Object Notation)
37
INDEX
Example: The MyTunes Application
index.html1 <html>2 <head>3 <meta http−e q u i v=” Content−Type” content=” t e x t / html ; c h a r s e t=UTF−8”>4 <t i t l e>MyTunes L i b r a r y</ t i t l e>5 <s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” j s / p r o t o t y p e . j s ”></ s c r i p t>6 <s c r i p t type=” t e x t / j a v a s c r i p t ”>7 f u n c t i o n loadTunes ( ) {8 new Ajax . Updater ( ’ tunesBox ’ , ’ l i s t . j s p ’ , {method : ’ get ’} ) ;9 }
10 </ s c r i p t>11 <l i n k r e l=” s t y l e s h e e t ” hre f=” c s s / t u n e s . c s s ” type=” t e x t / c s s ”/>12 </head>13 <body onload=” loadTunes ( ) ; ”>14 <div i d=” p a g e T i t l e ”>MyTunes</ div>15 <div i d=” tunesBox ”>16 <img id=” s p i n n e r ” s r c=” images / w a i t s p i n n e r . g i f ” height=”33” width=”33”/>17 </ div>18 </body>19 </html>
38
INDEX
Example: The MyTunes Application
list.jsp1 <%@ page contentType=” t e x t / html ” pageEncoding=”UTF−8” %>2 <%@ t a g l i b u r i=” h t t p : / / j a v a . sun . com/ j s p / j s t l / c o r e ” p r e f i x=” c ” %>3 <%@ t a g l i b u r i=” h t t p : / / j a v a . sun . com/ j s p / j s t l / s q l ” p r e f i x=” s q l ” %>45 <s q l : q u e r y var=” son gs ” d a t a S o u r c e=” j d b c /MyTunesDS”>6 s e l e c t ∗ from Songs7 </ s q l : q u e r y>8 <tab le border=”1” width=”100\%” ce l lpadd ing=”8”>9 <thead>
10 <t r>11 <td>Name</ td>12 <td>A r t i s t</ td>13 <td>Album</ td>14 <td>Genre</ td>15 <td>Year</ td>16 </ t r>17 </ thead>18 <tbody>19 <c : f o r E a c h var=” song ” i t e m s=”${ s ong s . rows}”>20 <t r>21 <td><a hre f=” e d i t . j s p ? i d=${song . i d}”>${song . t i t l e }</a></ td>22 <td>${song . a r t i s t }</ td>23 <td>${song . album}</ td>24 <td>${song . g e n r e}</ td>25 <td>${song . y e a r }</ td>26 </ t r>27 </ c : f o r E a c h>28 </tbody>29 </ tab le>
39
INDEX
Example: The MyTunes Application
edit.jsp1 <%@page contentType=” t e x t / html ” pageEncoding=”UTF−8”%>23 <!DOCTYPE HTML PUBLIC ”−//W3C//DTD HTML 4 . 0 1 T r a n s i t i o n a l //EN”4 ” h t t p : / /www. w3 . org /TR/ html4 / l o o s e . dtd ”>56 <html>7 <head>8 <t i t l e>E d i t a Song</ t i t l e>9 <s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” j s / p r o t o t y p e . j s ”></ s c r i p t>
10 <s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” j s / e d i t o r . j s ”></ s c r i p t>11 <l i n k r e l=” s t y l e s h e e t ” hre f=” c s s / t u n e s . c s s ”/>12 </head>13 <body onload=” loadSong ( ) ; ”>14 <div i d=” p a g e T i t l e ”>E d i t Song</ div>15 <div i d=” tunesBox ”>16 <span id=” s p i n n e r ”>17 <img s r c=” images / w a i t s p i n n e r . g i f ” height=”33” width=”33”/>18 </span>19 <form i d=” songForm ” onsubmit=” catchSubmit ( ) ; ”>20 <input type=” h i d d e n ” name=” i d ” i d=” i d ”/>21 <div i d=”name”>22 <span id=” nameLbl ”>Name :</span>23 <span id=” t i t l e ” o n c l i c k=” e d i t ( t h i s ) ”>?</span>24 </ div>25 <div i d=” a r t i s t D i v ”>26 <span id=” a r t i s t L b l ”>A r t i s t :</span>27 <span id=” a r t i s t ” o n c l i c k=” e d i t ( t h i s ) ”>?</span>28 </ div>29 <div i d=” albumDiv ”>30 <span id=” albumLbl ”>Album :</span>31 <span id=” album ” o n c l i c k=” e d i t ( t h i s ) ”>?</span>32 </ div>33 <div i d=” g e n r e D i v ”>34 <span id=” g e n r e L b l ”>Genre :</span>35 <span id=” g e n r e ” o n c l i c k=” e d i t ( t h i s ) ”>?</span>36 </ div>37 <div i d=” y e a r D i v ”>
40
INDEX
38 <span id=” y e a r L b l ”>Year :</span>39 <span id=” y e a r ” o n c l i c k=” e d i t ( t h i s ) ”>?</span>40 </ div>41 </ form>42 </ div>43 <div c l a s s=” b a c k L i n k ”>44 <a hre f=” i n d e x . html ”>Back to MyTunes L i b r a r y</a>45 </ div>46 </body>47 </html>
41
INDEX
Example: The MyTunes Application
editor.js (lines 1-39)1 // g l o b a l used to keep t r a c k o f what ’ s c u r r e n t l y b e i n g e d i t e d2 var c u r r e n t E l e m e n t = n u l l ;34 funct ion loadSong (){5 params = window . l o c a t i o n . s e a r c h . p a r s e Q u e r y ( ) ;6 var i d = params [ ” i d ” ] ;78 // c r e a t e h a n d l e r t h a t w i l l be i n v o k e d9 // when r e s p o n s e i s r e c e i v e d from s e r v e r
10 var h a n d l e r = funct ion ( x h r ){11 // use responseJSON p r o p e r t y added by P r o t o t y p e12 var j s o n = x h r . responseJSON ;13 // check f o r e r r o r14 i f ( j s o n . e r r o r ){15 // d i s p l a y th e e r r o r16 }17 var song = j s o n . song ;18 // c l e a r th e s p i n n e r19 // use Prototype ’ s $ ( ) s h o r t c u t n o t a t i o n20 $ (” s p i n n e r ” ) . innerHTML = ” ” ;21 // s e t t he d i s p l a y data22 $ (” i d ” ) . v a l u e = song . i d ;23 $ (” t i t l e ” ) . innerHTML = song . t i t l e ;24 $ (” a r t i s t ” ) . innerHTML = song . a r t i s t ;25 $ (” album ” ) . innerHTML = song . album ;26 $ (” g e n r e ” ) . innerHTML = song . g e n r e ;27 $ (” y e a r ” ) . innerHTML = song . y e a r ;28 } ;2930 // c r e a t e o p t i o n s f o r31 var o p t i o n s = {32 method : ” g e t ” ,33 o n S u c c e s s : h a n d l e r ,34 p a r a m e t e r s : { ” i d ” : i d }35 } ;3637 // send th e r e q u e s t38 new Ajax . Request (” S o n g S e r v l e t ” , o p t i o n s ) ;39 }
42
INDEX
Example: The MyTunes Application
SongServlet.java1 p u b l i c c l a s s S o n g S e r v l e t extends H t t p S e r v l e t {23 protected void p r o c e s s R e q u e s t ( H t t p S e r v l e t R e q u e s t r e q u e s t , H t t p S e r v l e t R e s p o n s e r e s p o n s e )4 throws S e r v l e t E x c e p t i o n , I O E x c e p t i o n {5 r e s p o n s e . se tContentType ( ” a p p l i c a t i o n / j s o n ” ) ;6 P r i n t W r i t e r out = r e s p o n s e . g e t W r i t e r ( ) ;7 t r y {8 S t r i n g message = ”” ;9 JSONObject r e s p = new JSONObject ( ) ;
10 t r y {11 Context i n i t C o n t e x t = new I n i t i a l C o n t e x t ( ) ;12 Context envContext = ( Context ) i n i t C o n t e x t . l o o ku p ( ” j a v a : / comp/ env ” ) ;13 DataSource ds = ( DataSource ) envContext . l o o ku p ( ” j d b c /MyTunesDS” ) ;14 C o n n e c t i o n conn = ds . g e t C o n n e c t i o n ( ) ;15 Statement stmt = conn . c r e a t e S t a t e m e n t ( ) ;16 R e s u l t S e t r s = stmt . e x e c u t e Q u e r y ( ”SELECT ∗ FROM Songs WHERE i d=” +17 r e q u e s t . g e t P a r a m e t e r ( ” i d ” ) ) ;18 i f ( r s . n e x t ( ) ) {19 JSONObject song = new JSONObject ( ) ;20 S t r i n g [ ] a t t r s = {” i d ” , ” t i t l e ” , ” a r t i s t ” , ” album ” , ” g e n r e ” , ” y e a r ”} ;21 f o r ( S t r i n g a t t r : a t t r s ) {22 song . put ( a t t r , r s . g e t S t r i n g ( a t t r ) ) ;23 }
43
INDEX
24 r e s p . put ( ” song ” , song ) ;25 }26 } catch ( JSONException ex ) {27 Logger . g e t L o g g e r ( S o n g S e r v l e t . c l a s s . getName ( ) ) . l o g ( L e v e l . SEVERE , n u l l , ex ) ;28 message= ” Problema amb e l JSON” ;29 } catch ( SQLException ex ) {30 Logger . g e t L o g g e r ( S o n g S e r v l e t . c l a s s . getName ( ) ) . l o g ( L e v e l . SEVERE , n u l l , ex ) ;31 message = ” Problema amb l a BD” ;32 } catch ( NamingExcept ion ex ) {33 Logger . g e t L o g g e r ( S o n g S e r v l e t . c l a s s . getName ( ) ) . l o g ( L e v e l . SEVERE , n u l l , ex ) ;34 message = ” Problema amb JNDI” ;35 }36 r e s p . put ( ” e r r o r ” , message ) ;37 out . w r i t e ( r e s p . t o S t r i n g ( ) ) ;38 } catch ( JSONException ex ) {39 Logger . g e t L o g g e r ( S o n g S e r v l e t . c l a s s . getName ( ) ) . l o g ( L e v e l . SEVERE , n u l l , ex ) ;40 // Desesperated wi th cached excep t i on s ;−)41 } f i n a l l y {42 out . c l o s e ( ) ;43 }44 }45 // . . . .46 } ;
44
INDEX
Example: The MyTunes Application
editor.js (lines 40-103)
40 funct ion e d i t ( elem ){41 var i d = elem . i d ;42 // D i s a b l e o n c l i c k when e d i t i n g43 elem . o n c l i c k = ” ” ;44 var s t r = c r e a t e E d i t o r ( id , elem . innerHTML ) ;45 // Re−e n a b l i n g i t46 elem . o n c l i c k = ” e d i t ( t h i s ) ” ;47 elem . innerHTML = s t r ;48 c u r r e n t E l e m e n t = $ (” s o n g ”+ i d ) ;49 $ (” s o n g ”+ i d ) . f o c u s ( ) ;50 }5152 funct ion c r e a t e E d i t o r ( name , v a l u e ){53 var s t r = ”< i n p u t o n k e y p r e s s =\”catchSubmit ( e v e n t )\”54 onBlur=\”makeText ( t h i s )\”55 t y p e=\” t e x t \”56 name=\””;57 s t r += name ;58 s t r += ”\” v a l u e =\””;59 s t r += v a l u e ;60 s t r += ”\” i d =\”s o n g ” ;61 s t r += name ;62 s t r += ”\”/>”;63 return s t r ;64 }6566 funct ion c r e a t e S p a n ( name , v a l u e ){67 var s t r = ”<span o n C l i c k =\” e d i t ( t h i s )\” i d =\””;68 s t r += name ;69 s t r += ”\”>”;70 s t r += v a l u e ;71 s t r += ”</span >”;72 return s t r ;73 }74
45
INDEX
75 funct ion makeText ( i n p u t ){76 // s a v e r e c o r d77 var formData = $ (” songForm ” ) . s e r i a l i z e ( true ) ;78 saveData ( formData ) ;79 // go back to d i s p l a y80 i n p u t . parentNode . innerHTML = i n p u t . v a l u e ;81 }8283 funct ion saveData ( song ){84 var h a n d l e r = funct ion ( x h r ){85 var j s o n = x h r . responseJSON ;86 i f ( j s o n . e r r o r ){87 // d i s p l a y th e e r r o r88 }89 } ;90 var o p t i o n s = {91 method : ” p o s t ” ,92 o n S u c c e s s : h a n d l e r ,93 p a r a m e t e r s : song94 } ;95 new Ajax . Request (” U p d a t e S e r v l e t ” , o p t i o n s ) ;96 }9798 funct ion catchSubmit ( e v e n t ){99 // KEY RETURN i s a f i e l d added to t he Event c l a s s by P r o t o t y p e
100 i f ( e v e n t . keyCode == Event . KEY RETURN){101 makeText ( c u r r e n t E l e m e n t ) ;102 }103 }
46
INDEX
Example: The MyTunes Application
SongServlet.java1 p u b l i c c l a s s U p d a t e S e r v l e t extends H t t p S e r v l e t {23 protected void p r o c e s s R e q u e s t ( H t t p S e r v l e t R e q u e s t r e q u e s t , H t t p S e r v l e t R e s p o n s e r e s p o n s e )4 throws S e r v l e t E x c e p t i o n , I O E x c e p t i o n {5 r e s p o n s e . se tContentType ( ” a p p l i c a t i o n / j s o n ” ) ;6 P r i n t W r i t e r out = r e s p o n s e . g e t W r i t e r ( ) ;7 S t r i n g c l a u s e = ”” ;8 S t r i n g message = ”” ;9 t r y {
10 Context i n i t C o n t e x t = new I n i t i a l C o n t e x t ( ) ;11 Context envContext = ( Context ) i n i t C o n t e x t . l o o ku p ( ” j a v a : / comp/ env ” ) ;12 DataSource ds = ( DataSource ) envContext . l o ok u p ( ” j d b c /MyTunesDS” ) ;13 C o n n e c t i o n conn = ds . g e t C o n n e c t i o n ( ) ;14 Statement stmt = conn . c r e a t e S t a t e m e n t ( ) ;15 f o r ( Enumerat ion k e y s = r e q u e s t . getParameterNames ( ) ; k e y s . hasMoreElements ( ) ; ) {16 S t r i n g key = ( S t r i n g ) k e y s . nextE lement ( ) ;17 i f ( ! key . e q u a l s ( ” i d ” ) ) {18 S t r i n g v a l u e = r e q u e s t . g e t P a r a m e t e r ( key ) ;19 c l a u s e = c l a u s e + key + ”=’” + v a l u e + ” ’ ” ;20 }21 }22 stmt . e x e c ut e U pd a te ( ”UPDATE Songs SET ” + c l a u s e + ”WHERE i d=” + r e q u e s t . g e t P a r a m e t e r ( ” i d ” ) ) ;23 } catch ( SQLException ex ) {
47
INDEX
24 Logger . g e t L o g g e r ( U p d a t e S e r v l e t . c l a s s . getName ( ) ) . l o g ( L e v e l . SEVERE , n u l l , ex ) ;25 message = ex . t o S t r i n g ( ) ;26 } catch ( NamingExcept ion ex ) {27 Logger . g e t L o g g e r ( U p d a t e S e r v l e t . c l a s s . getName ( ) ) . l o g ( L e v e l . SEVERE , n u l l , ex ) ;28 message = ex . t o S t r i n g ( ) ;29 } f i n a l l y {30 out . w r i t e ( ”{\” e r r o r \” : ” + message + ”}” ) ;31 }3233 }34 // . . .35 } ;
48
INDEX
As to conclude
• This has been a very rushy introductuon to Ajax
• Like it or not, JavaScript is one of the languages of thefutureˆHHHHHHpresent
• Raw JavaScript is not enought: use at least prototype
• (X)HTML + CSS + JS + ¿Prototype? is a MUST
• To explore: GWT (Google Web Toolkit) does Ajax fromJava
49