Ajax: A new programming model for the Web

33 downloads 33912 Views 594KB Size Report
AJAX stands for Asynchronous JavaScript And XML (term ... JavaScript as a programming language ... It is the heart of an AJAX application because it allows.
Ajax: A new programming model for the Web Juan M. Gimeno, Josep M. Rib´ o May, 2009

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

Adobe Flash

RIA Platforms

• 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: Windows Presentation 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 (term coined by Jesse James Garret in a famous article) • AJAX is not new but it was not popular until Google used it 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 the XMLHTTP 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, by means of an applet, make requests from JS without the user noticing it – 1999, IE5.0 incorporates, under ActiveX, the XMLHTTP object that replaces the applet – 5 years later, and driven by Google, used to create rich webweb 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 allows to asynchronically make requests to the server without changing the page

8

INDEX

Using the XMLHTTP Object To make a request to the server from JavaScript using the XMLHTTP 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 the evolution 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 object 1 f u n c t i o n getXHR ( ) { 2 req = false ; 3 i f ( window . XMLHttpRequest ) { 4 r e q = new XMLHttpRequest ( ) ; 5 } else { 6 i f ( ActiveXObject ) { 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 ( v a r i =0; i var xhr ; f u n c t i o n modifyPage ( ) { . . . } C l i c k Me

15

INDEX

Example1: JavaScript Code 1 var xhr ; 2 function modifyPage ( ) { 3 try { 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 try { 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 xhr = f a l s e ; 12 } 13 } 14 i f ( ! x h r && t y p e o f XMLHttpRequest != ’ u n d e f i n e d ’ ) { 15 x h r = new XMLHttpRequest ( ) ; 16 a l e r t ( ” XMLHttpRequest O b j e c t c r e a t e d ” ) ; 17 } 18 x h r . open ( ”GET” , ” . / g e t M e s s a g e ” , ” t r u e ” ) ; 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 header s e t t e d ” ) ; 22 xhr . onreadystatechange = function () { 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 ) r e t u r n ; 25 i f ( x h r . s t a t u s == 2 0 0 ) { 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 } else 28 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 xhr . send ( n u l l ) ; 31 }

16

INDEX

Example1: Java Servlet Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

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 ; import j a v a . i o . ∗ ; import j a v a x . s e r v l e t . ∗ ; import j a v a x . s e r v l e t . h t t p . ∗ ; 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 { @Override p u b l i c v o i d 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 , HttpServletResponse response ) throws I O E x c e p t i o n , S e r v l e t E x c e p t i o n { response . setContentType ( ” t e x t / p l a i n ” ) ; 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−c a c h e ” ) ; 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 t h e s e r v e r ” ) ;

} } 17

INDEX

Accessing and modifying the page • In the past example we have only shown alerts but we have not accessed the page content. • Usually AJAX applications modify the current content of the page with the response obtained from the server. • To do so, we need: 1. parts of the page (tipically a
) must be uniquely identifiable (using its id attribute’s value). 2. to modify the content we can use the innerHTML property of the element (simpler than pure DOM nodes manipulation) 3. the AJAX request must be sent when we are sure the
) is loaded. If one wants the request to be done when the page is being loaded, one must use the onload method of the body. 4. the XMLHTTP object must be a global variable of the page, so it can be accessed from different functions.

18

INDEX

Example 2: AJAX Modification index.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

< 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 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 , n var xhr ; f u n c t i o n modifyPage ( ) { x h r = getXHR ( ) ; x h r . open ( ”GET” , ” . / g e t M e s s a g e ” , ” t r u e ” ) ; 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 ” ) ; 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 ( ) { i f ( x h r . r e a d y S t a t e != 4 ) r e t u r n ; i f ( x h r . s t a t u s == 2 0 0 ) { document . g e t E l e m e n t B y I d ( ” message ” ) . innerHTML = x h r . r e s p o n s e T e x t ; } else { a l e r t ( ” Error p r o c e s s i n g response with s t a t u s ” + xhr . s t a t u s ) ; } } xhr . send ( n u l l ) ; } C l i c k Me

19

INDEX

DOM: Document Object Model

• DOM is a W3C standard that allows the processing of XML documents (HTML is not XML but DOM is also ported to it) • It defines common interfaces to traverse and manipulate a hierarchical 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 they are expressed in XML) – Manipulate the page by accessing the object window.document (or simply document)

20

INDEX

Example 3: AJAX Modification using DOM index.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

< 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 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 type=” t e x t / j a v a s c r i p t ”> var xhr ; f u n c t i o n modifyPage ( ) { x h r = getXHR ( ) ; x h r . open ( ”GET” , ” . / g e t M e s s a g e ” , ” t r u e ” ) ; 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 ” ) ; 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 ( ) { i f ( x h r . r e a d y S t a t e != 4 ) r e t u r n ; i f ( x h r . s t a t u s == 2 0 0 ) { r e p l a c e T e x t ( document . g e t E l e m e n t B y I d ( ” message ” ) , x h r . r e s p o n s e T e x t ) ; } else { a l e r t ( ” Error p r o c e s s i n g response with s t a t u s ” + xhr . s t a t u s ) ; } } xhr . send ( n u l l ) ; } C l i c k Me

21

INDEX

Example 3: AJAX Modification using DOM text-utils.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

function replaceText ( el , text ) { i f ( e l != n u l l ) { clearText ( el ); v a r newNode = document . c r e a t e T e x t N o d e ( t e x t ) ; e l . a p p e n d C h i l d ( newNode ) ; } } function clearText ( e l ) { i f ( e l != n u l l ) { i f ( el . childNodes ) { f o r ( v ar i =0; e l . c h i l d N o d e s . l e n g t h ; i ++) { v ar c h i l d N o d e = e l . c h i l d N o d e s [ i ] ; e l . removeChild ( childNode ) ; } } } } function getText ( e l ) { var t e x t = ” ” ; i f ( e l != n u l l ) { i f ( el . childNodes ) { f o r ( v ar i = 0 ; e l . c h i l d N o d e s . l e n g t h ; i ++) { v ar c h i l d N o d e = e l . c h i l d N o d e s [ i ] ; i f ( c h i l d N o d e . n o d e V a l u e != n u l l ) { t e x t = t e x t + childNode . nodeValue ; } } } } }

22

INDEX

Example: Autocomplete

• An example based (minor modifications) on the J2EE Blueprints Samples from Sun. • When filling a text entry, generates a pop-up with possible completions for the already entered characters • Hands-on-project: modify the example to allow the selection of a name by keyboard and not by mouse.

23

INDEX

Example: Autocomplete

index.jsp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

< s t y l e type=” t e x t / c s s ”> . selected { b a c k g r o u n d : #7A8AFF ; c o l o r : #FFFAFA ; }

var var var var

. unselected { b a c k g r o u n d : #FFFAFA ; c o l o r : #000000; } < s c r i p t type=” t e x t / j a v a s c r i p t ”> isIE ; req ; names ; target ;

f u n c t i o n g e t E l e m e n t X ( e l e m e n t ){ var t a r g e t L e f t = 0 ; i f ( element . o f f s e t P a r e n t ) {

24

INDEX 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

while ( element . o f f s e t P a r e n t ) { t a r g e t L e f t += e l e m e n t . o f f s e t L e f t ; element = element . o f f s e t P a r e n t ; } } else i f ( element . x ) { t a r g e t L e f t += e l e m e n t . x ; } return t a r g e t L e f t ;

} f u n c t i o n g e t E l e m e n t Y ( e l e m e n t ){ var targetTop = 0 ; i f ( element . o f f s e t P a r e n t ) { while ( element . o f f s e t P a r e n t ) { t a r g e t T o p += e l e m e n t . o f f s e t T o p ; element = element . o f f s e t P a r e n t ; } } else i f ( element . y ) { t a r g e t T o p += e l e m e n t . y ; } return targetTop ; } function i n i t () { t a r g e t = document . g e t E l e m e n t B y I d ( ” c o m p l e t e − f i e l d ” ) ; v a r popup = document . g e t E l e m e n t B y I d ( ” menu−popup ” ) ; popup . s t y l e . t o p = ( g e t E l e m e n t Y ( 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 ” ; popup . s t y l e . l e f t = g e t E l e m e n t X ( t a r g e t ) + ” px ” ; }

25

INDEX 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

function i n i t R e q u e s t ( u r l ) { i f ( window . XMLHttpRequest ) { r e q = new XMLHttpRequest ( ) ; } e l s e i f ( window . A c t i v e X O b j e c t ) { i s I E = true ; 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” ) ; } } function doCompletion () { v a r u r l = ” a u t o c o m p l e t e ? a c t i o n=c o m p l e t e&i d =” + e s c a p e ( t a r g e t . v a l u e ) ; initRequest ( url ); req . onreadystatechange = processRequest ; r e q . open ( ”GET” , u r l , t r u e ) ; req . send ( n u l l ) ; } function processRequest () { i f ( r e q . r e a d y S t a t e == 4 ) { i f ( r e q . s t a t u s == 2 0 0 ) { parseMessages ( ) ; } e l s e i f ( r e q . s t a t u s == 204) { clearTable (); } } } function parseMessages () { i f ( ! names ) { names = document . g e t E l e m e n t B y I d ( ” names ” ) ;

26

INDEX 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113

} clearTable (); v a r e m p l o y e e s = r e q . responseXML . getElementsByTagName ( ” e m p l o y e e s ” ) [ 0 ] ; f o r ( l o o p = 0 ; l o o p < e m p l o y e e s . c h i l d N o d e s . l e n g t h ; l o o p++) { var employee = employees . c h i l d N o d e s [ loop ] ; v a r f i r s t N a m e = e m p l o y e e . getElementsByTagName ( ” f i r s t N a m e ” ) [ 0 ] ; v a r l a s t N a m e = e m p l o y e e . getElementsByTagName ( ” l a s t N a m e ” ) [ 0 ] ; v a r e m p l o y e e I d = e m p l o y e e . getElementsByTagName ( ” i d ” ) [ 0 ] ; appendEmployee ( f i r s t N a m e . c h i l d N o d e s [ 0 ] . nodeValue , l a s t N a m e . c h i l d N o d e s [ 0 ] . nodeValue , employeeId . childNodes [ 0 ] . nodeValue ) ; } } function clearTable () { i f ( names ) { 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 ; l o o p −−) { 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 ] ) ; } } } f u n c t i o n appendEmployee ( f i r s t N a m e , lastName , e m p l o y e e I d ) { var f i r s t N a m e C e l l ; var l a s t N a m e C e l l ; if ( isIE ) { row = names . i n s e r t R o w ( names . rows . l e n g t h ) ; n a m e C e l l = row . i n s e r t C e l l ( 0 ) ; } else { row = document . c r e a t e E l e m e n t ( ” t r ” ) ;

27

INDEX 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 } 133 134 135 136 137 138 139 140 141 142 143

n a m e C e l l = document . c r e a t e E l e m e n t ( ” t d ” ) ; row . a p p e n d C h i l d ( n a m e C e l l ) ; names . a p p e n d C h i l d ( row ) ;

} row . s e t A t t r i b u t e ( ” b o r d e r ” , ” 0 ” ) ; n a m e C e l l . s e t A t t r i b u t e ( ” onmouseout ” , ” t h i s . c l a s s N a m e =’ u n s e l e c t e d ’ ; ” ) ; n a m e C e l l . s e t A t t r i b u t e ( ” onmouseover ” , ” t h i s . c l a s s N a m e =’ s e l e c t e d ’ ; ” ) ; n a m e C e l l . s e t A t t r i b u t e ( ” b g c o l o r ” , ”#FFFAFA ” ) ; nameCell . s e t A t t r i b u t e (” border ” , ” 0 ” ) ; v a r 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 ” ) ; 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 ” ) ; 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 ) ; v a r nameFontElement = document . c r e a t e E l e m e n t ( ” f o n t ” ) ; nameFontElement . s e t A t t r i b u t e ( ” s i z e ” , ”+1”); nameFontElement . s e t A t t r i b u t e ( ” c o l o r ” , ” b l a c k ” ) ; nameFontElement . a p p e n d C h i l d ( document . c r e a t e T e x t N o d e ( f i r s t N a m e + ” ” + l a s t N a m e ) ) ; l i n k E l e m e n t . a p p e n d C h i l d ( nameFontElement ) ; nameCell . appendChild ( linkElement ) ; < t i t l e>Auto−C o m p l e t i o n u s i n g A s y n c h r o n o u s J a v a S c r i p t and XML (AJAX)

Auto−C o m p l e t i o n u s i n g A s y n c h r o n o u s J a v a S c r i p t and XML (AJAX)


T h i s e x a m p l e shows how you can do r e a l t i m e auto−c o m p l e t i o n u s i n g AJAX i n t e r a c t i o n s .



28

INDEX 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

I n t h e form b e l o w 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 c o m p l e t e d a r e d i s p l a y e d b e n e a t h t h e form . C l i c k on one o f t h e s e l e c t i o n s t o s e e t h e e m p l o y e e d e t a i l s . Try t y p i n g &q u o t ; Greg&q u o t ; , &q u o t ; Murray&q u o t ; , &q u o t ; J o n e s&q u o t ; , o r &q u o t ; C i n d y&q u o t ; .



< t r> Employee Name :

30

INDEX

Example: Autocomplete

AutocompleteServlet.jsp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

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 ; import import import import

java . io .∗; javax . s e r v l e t .∗; javax . s e r v l e t . http .∗; java . u t i l .∗;

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 { private ServletContext context ; p r i v a t e HashMap e m p l o y e e s = new HashMap ( ) ; p u b l i c v o i d 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 { this . context = config . getServletContext ( ) ; e m p l o y e e s . p u t ( ”1” , new EmployeeBean ( ”1” , ” Greg ” , ” Murray ” ) ) ; e m p l o y e e s . p u t ( ”2” , new EmployeeBean ( ”2” , ” Greg ” , ” Murphy ” ) ) ; e m p l o y e e s . p u t ( ”3” , new EmployeeBean ( ”3” , ” Ge or ge ” , ” Murphy ” ) ) ; e m p l o y e e s . p u t ( ”4” , new EmployeeBean ( ”4” , ” Ge or ge ” , ” Murray ” ) ) ; e m p l o y e e s . p u t ( ”5” , new EmployeeBean ( ”5” , ” P e t e r ” , ” J o n e s ” ) ) ; e m p l o y e e s . p u t ( ”6” , new EmployeeBean ( ”6” , ”Amber” , ” J o n e s ” ) ) ; e m p l o y e e s . p u t ( ”7” , new EmployeeBean ( ”7” , ”Amy” , ” J o n e s ” ) ) ; e m p l o y e e s . p u t ( ”8” , new EmployeeBean ( ”8” , ” Bee ” , ” J o n e s ” ) ) ; e m p l o y e e s . p u t ( ”9” , new EmployeeBean ( ”9” , ” Beth ” , ” Johnson ” ) ) ;

31

INDEX 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

e m p l o y e e s . p u t ( ” 10 ” , new EmployeeBean ( ” 10 ” , ” C i n d y ” , ” Johnson ” ) ) ; e m p l o y e e s . p u t ( ” 11 ” , new EmployeeBean ( ” 11 ” , ” C i n d y ” , ” Murphy ” ) ) ; e m p l o y e e s . p u t ( ” 12 ” , new EmployeeBean ( ” 12 ” , ”Duke” , ” Hazerd ” ) ) ;

} p u b l i c v o i d 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 ) throws I O E x c e p t i o n , S e r v l e t E x c e p t i o n { String action = request . getParameter ( ” action ” ) ; String t a r g e t I d = request . getParameter (” id ” ) ; 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 ( ) ; i f ( t a r g e t I d != n u l l ) { t a r g e t I d = t a r g e t I d . trim ( ) . toLowerCase ( ) ; } boolean namesAdded = f a l s e ; i f ( ” complete ” . equals ( action )) { I t e r a t o r i t = employees . keySet ( ) . i t e r a t o r ( ) ; while ( i t . hasNext ( ) ) { String id = ( String ) i t . next ( ) ; EmployeeBean e = ( EmployeeBean ) e m p l o y e e s . g e t ( i d ) ; // s i m p l e matching o n l y f o r s t a r t o f f i r s t or l a s t name i f ( ( e . getFirstName ( ) . toLowerCase ( ) . s t a r t s W i t h ( t a r g e t I d ) | | e . getLastName ( ) . t o L o w e r C a s e ( ) . s t a r t s W i t h ( t a r g e t I d ) ) && ! t a r g e t I d . e q u a l s ( ”” ) ) { sb . append ( ”” ) ; sb . append ( ”” + e . g e t I d ( ) + ”” ) ; sb . append ( ”” + e . g e t F i r s t N a m e ( ) + ”” ) ; sb . append ( ”” + e . getLastName ( ) + ”” ) ; sb . append ( ”” ) ; namesAdded = t r u e ;

32

INDEX 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

} } i f ( namesAdded ) { r e s p o n s e . s e t C o n t e n t T y p e ( ” t e x t / xml ” ) ; 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−c a c h e ” ) ; r e s p o n s e . g e t W r i t e r ( ) . w r i t e ( ”” + sb . t o S t r i n g ( ) + ”” ) ; } else { // n o t h i n g t o show 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 ) ; } } i f ( ” lookupbyname ” . e q u a l s ( a c t i o n ) ) { I t e r a t o r i t = employees . keySet ( ) . i t e r a t o r ( ) ; A r r a y L i s t names = new A r r a y L i s t ( ) ; while ( i t . hasNext ( ) ) { String id = ( String ) i t . next ( ) ; EmployeeBean e = ( EmployeeBean ) e m p l o y e e s . g e t ( i d ) ; // s i m p l e matching o n l y f o r s t a r t o f f i r s t or l a s t name i f ( e . getFirstName ( ) . toLowerCase ( ) . s t a r t s W i t h ( t a r g e t I d ) | | e . getLastName ( ) . t o L o w e r C a s e ( ) . s t a r t s W i t h ( t a r g e t I d ) ) { names . add ( e ) ; } } i f ( names . s i z e ( ) > 0 ) { r e q u e s t . s e t A t t r i b u t e ( ” e m p l o y e e s ” , names ) ; } 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 m p l o y e e s . 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 ) ; } else i f (” lookup ” . equals ( action )) { // p u t t h e t a r g e t employee i n t h e r e q e u s t s c o p e t o d i s p l a y i f ( ( t a r g e t I d != n u l l ) && e m p l o y e e s . 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 85 86 87 88 89 90 91 }

r e q u e s t . s e t A t t r i b u t e ( ” employee ” , employees . get ( t a r g e t I d ) ) ; 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 m p l o y e e . 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 ) ; } else { 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 ) ; }

} }

34

INDEX

Example: Autocomplete

employees.jsp 1 2 3 4 5 6 7

S e a r c h R e s u l t s

8
9 10 11 12

U n a b l e t o l o c a t e any e m p l o y e e s .

13 14 15 16

17 $ { e m p l o y e e . f i r s t N a m e } $ { e m p l o y e e . l a st N a m e } 18 19

20 21 22 23


35

INDEX 24

25 Go back t o t h e a p p l i c a t i o n home . 26

27 28

36

INDEX

Prototype

• Trying to program in JavaScript without any library is almost suicidal – There are subtle differences among the implementations of JS in the different browsers – Programming in JavaScript is tricky (e.g. it has objects but no classes nor inheritance) – (the language has some flaws but it was a ”hack that got shipped”) • Prototype is a fairly broad library that u ¨pgrades”the language – 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.html 1 2 3 4 < t i t l e>MyTunes L i b r a r y 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 ”> 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 A j a x . U p d a t e r ( ’ tunesBox ’ , ’ l i s t . j s p ’ , { method : ’ get ’ } ) ; 9 } 10 11 < l i n k r e l=” s t y l e s h e e t ” h r e f=” c s s / t u n e s . c s s ” type=” t e x t / c s s ”/> 12 13 14 MyTunes 15 16 17 18 19

38

INDEX

Example: The MyTunes Application

list.jsp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

< s q l : q u e r y v ar=” s o n g s ” d a t a S o u r c e=” j d b c /MyTunesDS”> s e l e c t ∗ from Songs < t r> Name A r t i s t Album Genre Year < t r> $ { song . t i t l e } $ { song . a r t i s t } $ { song . album } $ { song . g e n r e } $ { song . y e a r }

39

INDEX

Example: The MyTunes Application

edit.jsp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

< !DOCTYPE HTML PUBLIC ”−//W3C//DTD HTML 4 . 0 1 T r a n s i t i o n a l //EN” ” h t t p : / /www. w3 . o r g /TR/ html4 / l o o s e . d t d ”> < t i t l e> E d i t a Song < 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 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 ”> < l i n k r e l=” s t y l e s h e e t ” h r e f=” c s s / t u n e s . c s s ”/> E d i t Song Name : ? A r t i s t : ? Album : ? Genre : ?

40

INDEX 38 Year : 39 ? 40 41 42 43 44 Back t o MyTunes L i b r a r y 45 46 47

41

INDEX

Example: The MyTunes Application editor.js (lines 1-39) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

// g l o b a l u s e d t o k e e p 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 d var c u r r e n t E l e m e n t = n u l l ; function loadSong (){ 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 ( ) ; v a r i d = params [ ” i d ” ] ; // 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 d // 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 v a r h a n d l e r = f u n c t i o n ( x h r ){ // u s e responseJSON p r o p e r t y added by P r o t o t y p e v ar j s o n = x h r . responseJSON ; // c h e c k f o r e r r o r i f ( j s o n . e r r o r ){ // d i s p l a y t h e e r r o r } v ar song = j s o n . song ; // c l e a r t h e s p i n n e r // u s e P r o t o t y p e ’ s $ ( ) s h o r t c u t n o t a t i o n $ ( ” s p i n n e r ” ) . innerHTML = ” ” ; // s e t t h e d i s p l a y d a t a $ ( ” i d ” ) . v a l u e = song . i d ; $ ( ” t i t l e ” ) . innerHTML = song . t i t l e ; $ ( ” a r t i s t ” ) . innerHTML = song . a r t i s t ; $ ( ” album ” ) . innerHTML = song . album ; $ ( ” g e n r e ” ) . innerHTML = song . g e n r e ; $ ( ” y e a r ” ) . innerHTML = song . y e a r ; }; // c r e a t e o p t i o n s f o r var o p t i o n s = { method : ” g e t ” , onSuccess : handler , parameters : { ” id ” : id } }; // s e n d t h e r e q u e s t new A j a x . R e q u e s t ( ” S o n g S e r v l e t ” , o p t i o n s ) ;

}

42

INDEX

Example: The MyTunes Application

SongServlet.java 1 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 { 2 3 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 request , 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 response . setContentType ( ” a p p l i c a t i o n / json ” ) ; 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 try { 8 S t r i n g message = ”” ; 9 JSONObject r e s p = new JSONObject ( ) ; 10 try { 11 C o n t e x t 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 C o n t e x t e n v C o n t e x t = ( C o n t e x t ) i n i t C o n t e x t . l o o k u p ( ” j a v a : / comp/ env ” ) ; 13 D a t a S o u r c e ds = ( D a t a S o u r c e ) e n v C o n t e x t . l o o k u 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 S t a t e m e n t 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 request . getParameter ( ” id ” ) ) ; 18 i f ( rs . next ()) { 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 for ( String attr : a t t r s ) { 22 song . p u t ( a t t r , r s . g e t S t r i n g ( a t t r ) ) ; 23 }

43

INDEX 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 } ;

r e s p . p u t ( ” song ” , song ) ;

} } catch ( JSONException ex ) { L o g g e r . 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 , message= ” Problema amb e l JSON” ; } catch ( SQLException ex ) { L o g g e r . 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 , message = ” Problema amb l a BD” ; } catch ( N a m i n g E x c e p t i o n ex ) { L o g g e r . 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 , message = ” Problema amb JNDI” ; } r e s p . p u t ( ” e r r o r ” , message ) ; out . w r i t e ( r e s p . t o S t r i n g ( ) ) ; } catch ( JSONException ex ) { L o g g e r . 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 // D e s e s p e r a t e d w i t h cached e x c e p t i o n s ; − ) } finally { out . c l o s e ( ) ; }

n u l l , ex ) ;

n u l l , ex ) ;

n u l l , ex ) ;

, ex ) ;

} // . . . .

44

INDEX

Example: The MyTunes Application

editor.js (lines 40-103) 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

f u n c t i o n e d i t ( elem ) { v a r i d = elem . i d ; // D i s a b l e o n c l i c k when e d i t i n g elem . o n c l i c k = ” ” ; v a r s t r = c r e a t e E d i t o r ( i d , elem . innerHTML ) ; // Re−e n a b l i n g i t elem . o n c l i c k = ” e d i t ( t h i s ) ” ; elem . innerHTML = s t r ; c u r r e n t E l e m e n t = $ ( ” s o n g ”+ i d ) ; $ ( ” s o n g ”+ i d ) . f o c u s ( ) ; } f u n c t i o n c r e a t e E d i t o r ( name , v a l u e ) { v a r s t r = ”< i n p u t o n k e y p r e s s =\”c a t c h S u b m i t ( e v e n t ) \ ” o n B l u r=\”makeText ( t h i s ) \ ” t y p e =\” t e x t \ ” name= \ ””; s t r += name ; s t r += ” \ ” v a l u e = \ ””; s t r += v a l u e ; s t r += ” \ ” i d =\” s o n g ” ; s t r += name ; s t r += ” \ ”/ > ”; return s t r ; } f u n c t i o n c r e a t e S p a n ( name , v a l u e ) { v a r s t r = ”< s pa n o n C l i c k =\” e d i t ( t h i s ) \ ” i d = \ ””; s t r += name ; s t r += ” \ ” > ”; s t r += v a l u e ; s t r += ”
”; return s t r ; }

45

INDEX 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103

f u n c t i o n makeText ( i n p u t ) { // s a v e r e c o r d v a r formData = $ ( ” songForm ” ) . s e r i a l i z e ( t r u e ) ; s a v e D a t a ( formData ) ; // go back t o d i s p l a y i n p u t . p a r e n t N o d e . innerHTML = i n p u t . v a l u e ; } f u n c t i o n s a v e D a t a ( song ) { v a r h a n d l e r = f u n c t i o n ( x h r ){ v ar j s o n = x h r . responseJSON ; i f ( j s o n . e r r o r ){ // d i s p l a y t h e e r r o r } }; var o p t i o n s = { method : ” p o s t ” , onSuccess : handler , p a r a m e t e r s : song }; new A j a x . R e q u e s t ( ” U p d a t e S e r v l e t ” , o p t i o n s ) ; } f u n c t i o n c a t c h S u b m i t ( e v e n t ){ // KEY RETURN i s a f i e l d added t o t h e E v e n t c l a s s by P r o t o t y p e i f ( e v e n t . keyCode == E v e n t . KEY RETURN) { makeText ( c u r r e n t E l e m e n t ) ; } }

46

INDEX

Example: The MyTunes Application

SongServlet.java 1 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 { 2 3 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 request , 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 response . setContentType ( ” a p p l i c a t i o n / json ” ) ; 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 try { 10 C o n t e x t 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 C o n t e x t e n v C o n t e x t = ( C o n t e x t ) i n i t C o n t e x t . l o o k u p ( ” j a v a : / comp/ env ” ) ; 12 D a t a S o u r c e ds = ( D a t a S o u r c e ) e n v C o n t e x t . l o o k 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 S t a t e m e n t stmt = conn . c r e a t e S t a t e m e n t ( ) ; 15 f o r ( E n u m e r a t i o n k e y s = r e q u e s t . getParameterNames ( ) ; k e y s . h a s M o r e E l e m e n t s ( ) ; ) { 16 S t r i n g key = ( S t r i n g ) keys . nextElement ( ) ; 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 . getParameter ( key ) ; 19 c l a u s e = c l a u s e + k e y + ”=’” + v a l u e + ” ’ ” ; 20 } 21 } 22 stmt . e x e c u t e U p d a t e ( ”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 25 26 27 28 29 30 31 32 33 34 35 } ;

L o g g e r . 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 ) ; message = ex . t o S t r i n g ( ) ; } catch ( N a m i n g E x c e p t i o n ex ) { L o g g e r . 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 ) ; message = ex . t o S t r i n g ( ) ; } finally { o u t . w r i t e ( ” {\” e r r o r \ ” : ” + message + ” } ” ) ; }

} // . . .

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 the futureˆ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 from Java

49