Allow the user to enter the email properties in text fields and then send an email without a page round trip. This hack not only sends an email without a page round trip, but also validates the syntax of the entered email addresses and provides useful messages in the event of invalid entries. Figure 4-20 shows what the hack's web page looks like in the Safari browser. Figure 4-20. An email application without round tripsIt looks pretty basic, but a lot happens behind the scenes. A server component awaits a request to receive the data and send it as an email. The web page itself imports three JavaScript libraries: <script type="text/javascript" src="/books/4/254/1/html/2/js/email_lib.js"></script> <script type="text/javascript" src="/books/4/254/1/html/2/js/hacks4_12.js"></script> <script type="text/javascript" src="/books/4/254/1/html/2/js/http_request.js"></script> email_lib.js contains a bit of object-oriented JavaScript that is designed to validate an email address [Hack #23] and provide a useful message in the event of any invalid syntax. http_request.js (see "Use Your Own Library for XMLHttpRequest" [Hack #3]) initializes XMLHttpRequest and uses it to send the email information. hacks4_12.js contains this Ajax application's code, which is reproduced in the next section. Figure 4-21 shows a message that is dynamically generated when the user enters an address with improper syntax in either of the first two text fields. Figure 4-21. Responding to an email typoIn this case, the user left a couple of letters off of the email suffix (the domain) in the second field. Our email-syntax checker in email_lib.js ensures that, among other things, email addresses end with a period followed by two to three characters. (For more validation rules, check out [Hack #23].) If the user's entries are valid, the Java servlet responds with an <outcome>true</outcome> message so that the application can notify the user that the email is on its way, as in Figure 4-22. Figure 4-22. All systems go for emailingHow It WorksFirst we'll look at the code in hacks4_12.js, which uses elements of the other two imported libraries to check the email address syntax and then send the email, all without a page rebuild. Then we'll look at the Java servlet that receives the email data. Here is the page's underlying code: var queryString=""; window.onload=function( ){ var _url="http://www.parkerriver.com/s/em"; var b1 = document.getElementById("b1"); if(b1){ b1.onclick=function( ){ //clear any existing messages clearMsg(document.getElementById("err"),""); clearMsg(document.getElementById("msg"),""); var isValidEmail=validate(document.getElementById("sender"). value, document.getElementById("receiver").value); if(isValidEmail){ try{ showMsg(document.getElementById("msg"), "Sending email..."); setQueryString( ); httpRequest("POST",_url,true, handleResponse,queryString); } catch(errv) { alert("Sorry, but we failed to send the email because "+ "of this error: "+errv.message); } } }; //end function } } //Validate however many email addresses have been //passed in as arguments using the Arguments array. //Break and return false if one of them is invalid function validate(em1) { var bool = false; var eml = null; for(var i = 0; i < arguments.length; i++) { eml = new Email(arguments[i]); eml.validate( ); bool=eml.valid; if(! bool) { showMsg(document.getElementById("err"), eml.message);break;} } return bool; } function showMsg(_id,txt){ if(_id && txt){_id.innerHTML=txt;} } function clearMsg(_id){ if(_id){_id.innerHTML="";} } function handleResponse( ){ try{ if(request.readyState == 4){ if(request.status == 200){ var resp = request.responseXML; if(resp != null){ var outc=resp.getElementsByTagName("outcome")[0]; if(outc.childNodes[0].nodeValue == "true") { showMsg(document.getElementById("msg"), "Your email is on its way!"); } else { showMsg(document.getElementById("msg"), "The email could not be sent at this time."); } } else { showMsg(document.getElementById("msg"), "The email could not be sent at this time."); } } else { //snipped... } }//end outer if } catch (err) { alert("It does not appear that the server "+ "is available for this application. Please"+ " try again very soon. \\nError: "+err.message); } } function setQueryString( ){ queryString=""; var frm = document.forms[0]; var numberElements = frm.elements.length; for(var i = 0; i < numberElements; i++) { if(i < numberElements-1) { queryString += frm.elements[i].name+"="+ encodeURIComponent(frm.elements[i].value)+"&"; } else { queryString += frm.elements[i].name+"="+ encodeURIComponent(frm.elements[i].value); } } } When the browser loads the web page, it sets up the Send Email button's onclick event handler.
When the user clicks this button, the application validates the syntax of the values entered into the email address text fields. If the values represent valid email addresses, setQueryString( ) assembles a querystring of all the email information suitable for sending in a POST request: b1.onclick=function( ){ //clear any existing messages clearMsg(document.getElementById("err"),""); clearMsg(document.getElementById("msg"),""); var isValidEmail=validate(document.getElementById("sender"). value, document.getElementById("receiver").value); if(isValidEmail){ try { showMsg(document.getElementById("msg"),"Sending email..."); setQueryString( ); httpRequest("POST",_url,true,handleResponse,queryString); } catch(errv) { alert("Sorry, but we failed to send the email because "+ "of this error: "+errv.message); } } }; //end function Here is a sample of a querystring from this application encoded for transferal over the Web: //encodeURIComponent( ) function converts '@' to '%40' fromAddr=brucewperry%40gmail.com&toAddr=brucewperry%40gmail.com&subj= hello&emessage=hello%20there! Finally, httpRequest( ) sends the POST request to our server component, which ultimately sends the email. See "Use Your Own Library for XMLHttpRequest" [Hack #3] for an explanation of this method. Server SnippetWhat does our server component look like? Here is a snippet from the Java servlet class that sends the email: package com.parkerriver; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class NewEmailServlet extends HttpServlet{ protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { doPost(httpServletRequest,httpServletResponse); } protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { String fromAddr = httpServletRequest.getParameter("fromAddr"); String toAddr = httpServletRequest.getParameter("toAddr"); String eMsg = httpServletRequest.getParameter("emessage"); String subj = httpServletRequest.getParameter("subj"); boolean outcome = false; if(check(fromAddr) && check(toAddr) && check(eMsg)){ EmailBean bean = new EmailBean( ); bean.setFrom(fromAddr); bean.setTo(toAddr); bean.setSubject(subj); bean.setContent(eMsg); outcome = bean.sendMessage( ); } AjaxUtil.sendXML(httpServletResponse,"<outcome>"+ outcome+"</outcome>"); } private boolean check(String content) { if(content != null && content.length( ) > 0) {return true;} return false; } } This servlet uses an EmailBean object with various setter or "mutater" methods that build an email. EmailBean has a sendMessage( ) method that sends the email and returns true if everything goes okay (in Java terms, if the method call does not result in a thrown exception). The servlet returns this value to the Ajax application as a bit of XML in an outcome element.
|