End-to-end AJAX
Originally Presented to MultiValue Software Developers at
SAPUG June 15, 2006
Modifying in August 2006
Dawn M. Wolthuis
Tincat Group, Inc.
dwolt@tincat-group.com
Mid-level Overview
- This presentation gives little context or rationale for AJAX, not high level
- And provides only a small amount of code, not low level
- But you should be able to jump in afterwards
- With some details on areas to research later
- And resources to help you get moving
- By the way, F11 will help for viewing this presentation
- The autohide extension helps FireFox get the largest window
- Otherwise there is some obnoxious scrolling to view everything
For the record...
- I'm currently responsible for no production systems
- I've been in mgmt for ~17 years, project mgmt for > 20
- and at the height of my programming years
- I was a COBOL CICS developer
- and I can code a little Java too
- I have done more JavaScript coding than DataBASIC (note to web readers, DataBASIC is the primary language for MultiValue, aka PICK, programmers, the original audience for this talk)
if (do != "can") {
teach();
}
In this session
- Description of AJAX
- Architecture
- Stepping-thru AJAX
- AJAX Samples
- Look at Each AJAX Browser Input
- XHTML
- CSS
- User Events
- JavaScript
- Server-side
- Developer Tools & Resources
- Wrap-up
Architecture
Architecture
JRE or .NET for Application Run-time Container? Neither.
Stepping Thru
Stepping Thru
Apologies that the sample code for this example is no longer available
Stepping Thru
Sample xhtml Source Code
Stepping Thru
Sample Event is "onblur"
Stepping Thru
Custom JavaScript
Stepping Thru
Note about listening
Although I wrote that JavaScript "listens" it is the browser that is listening and passing the information to the JavaScript as you have specified.
User sees the screen
Stepping Thru
Uses prototype.js AJAX "framework"
Stepping Thru
Results without New Page
Not your Grandma's Web Page
- Server sends values for JavaScript, not a new page.
- Communication to server from JS, not html form submits.
- Background asynchronous requests to server, user not waiting.
- Single page web applications, not multi-page web sites.
- Responsibility for the HCI in the client software, not the server.
- Server-side app logic packaged in services, not page responses.
- Browser is run-time container for the application, not .NET or JRE.
Let's Go Clockwise Around
XHTML: XML version of HTML
XHTML 1.0
- Namespaces for Transitional or Strict
- or frameset DTDs (Data Type Definitions)
- Small syntax changes from HTML, such as
- requiring lowercase markup tags
- providing end tags
- quoting all attribute values
- Specification w3.org
- Tutorial w3schools.com
Partitions XHTML Tags into Modules
Module (Incomplete List) |
Tags (Also incomplete) |
Block structural |
div, p |
Block phrasal |
address, blockquote, pre, h1-h6 |
Inline structural |
br, span |
Inline phrasal |
abbr, acronym, cite, code, dfn, em, kbd, q, samp, strong, var |
Linking |
a, base, link |
Lists |
dir, dl, dt, dd, ol, ul, li |
Simple forms |
form, input, select, option, textarea |
Extended forms |
button, fieldset, label, legend, optgroup, option, select, textarea |
Simple tables |
table, td, th, tr |
Extended tables |
caption, col, colgroup, tbody, tfoot, thead |
Images |
img |
Image maps |
area, map |
Metadata |
meta, title |
Structure |
html, head, body |
Extensive Use of Two Attributes
XHTML Tidbits
- Specify meaning and component parts such as navigation or footer.
- style might be specified with CSS
- content might be injected by JavaScript
- Use tables only for data table-like content, not for layout.
- Include id attribute on elements to be referenced in JavaScript.
- Include a <title> along with head and body
- Declare a DOCTYPE
- Follow DOCTYPE with root element including namespace declaration
- Do not include an <xml> tag as standard with xml.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1" />
<!-- Change the title for each page -->
<title>Tincat Group, Inc.—Contact Us</title>
Should Get Rid of Gen'ing Server-side HTML
PHP excerpt from the example. Note that I did not obey this, but at least feel guilty
$cl = 'tr class="cle"';
$rows = $result->results;
if(is_Array($rows)) {
$mz = sizeof($rows);
} else {
$rows[0] = $rows;
$mz = 1;
}
for($rx = 0; $rx < $mz; $rx++) {
if($cl == 'tr class="clo"')
$cl = 'tr class="cle"';
else
$cl = 'tr class="clo"';
$ret .= '<'.$cl.'>';
$row = $rows[$rx];
if(strstr($row, AM)) {
$row = explode(AM, $row);
$mx = sizeof($row);
} else {
$row[0] = $row;
$mx = 1;
}
The DOM
"The Document Object Model is a platform- and language-neutral interface that will allow
programs and scripts to dynamically access and update the content,
structure and style of documents, both HTML and XML"
From w3schools.com/dom
Each Page has a DOM
DOM Inspector
Cascading Style Sheets?
CSS
CSS Cross-Browser
- A LOT of hacks for various browsers
- Lowery's CSS Hacks & Filters, 2005, Wiley
- Box model, IE and FF/W3C differ
- I have a lot of frustration with IE
- Until it finally works
- At which point I find the css broken for FireFox
- And then there's Opera, Safari, and others
- browsershots.org/submit
- browsers.evolt.org
Each of the pages in this graphic is done with the exact same html, different css
CSS Current Status
- Every jot and tiddle might be important in a non-obvious way
- Some statements are only interpreted by one browser or another
- Extensive use of hacks and work-arounds
- Iterative testing of css can be quick and easy
- But debugging and correcting problems can be painful
- Worth using for the separation of concerns
- Might want to clone and modify
User Events
Events are User Events
- window
- mouse
- onclick, ondblclick, onmousedown, onmouseup, onmouseover, onmousemove, onmouseout
- keyboard
- onkeypress, onkeydown, onkeyup
- form
- onblur, onchange, onfocus, onsubmit, onreset, onselect
Event Issues
- Cross-browser differences
- Where to put event handlers
- In xhtml with onblur=doThis();
- Or in JavaScript, where they need to play nice with any other event handlers that might be added in other scripts
- Validations
- Choosing an approach
- Combined with dropdowns and other GUI widgets
- "Code file" could be pre-loaded, taking memory
- What happens on the server, what on the client
- How are users informed of issues
- Updates
- Should use still click Submit button before every database update?
- If not, how do they know when the changes they made will stick?
- Multiple events triggering the same logic
Validations HCI
From http://justaddwater.dk/2006/02/08/ajax-businesscase/
Human—Event—Service
- Polling server, avoid if you can
- Server provides services
- Autonomous (preferably)
- Stateless (preferably)
- With a public interface
- But these services are rarely autonomous or stateless.
- If order of services matters, design properly on the client.
- Will session management move to the client?
- Databased services are not autonomous
- Locking mechanisms
- Connection pooling
- CRUD services for entities, transactions
It's time for JavaScript?
ECMAScript
- Also known as JavaScript or JScript (IE)
- Is the only language that all browsers must support
- You can resist it, as I did for quite some time
- Or use tools to generate it from other languages
- But it has a more secure standing than most languages
- With nothing on the horizon replacing it for browser-based UI's
- Requires no plug-in
- But may be turned off
- Must either degrade or fail gracefully
- JavaScript is not strictly OO; it is more of a functional language.
- Best to combine logic with a zen approach.
Executing JavaScript
- JS is interpreted by the browser
- The source code is in the clear unless you work to secure or encrypt it.
- When a page is loaded
- JS not in a function is run statically.
- JS inline between <script> tags or pointed to will run.
- myFunction1, myFunction2 will run if in <body onload="myFunction1(), myFunction2()";>
- Similarly, JS functions will run if associated with any event
- Or you can put JS inline in your html page and it will run that when it gets there.
- Somewhat ill-advised is to send text to a JS eval() function; if JS, it will run.
DOM Methods
getElementById('thisid') or $('thisid') if using prototype.js
JavaScript Objects
- Native Objects
- For primitive values (passed by value)
- Boolean
- Number
- String
- (Primitive values can also be Null or Undefined)
- of type Object
- Array
- Date
- Function
- Math
- RegEx
- Host Objects
JavaScript Object
- Is a set of tag-value properties, where the value can be
- a primitive value or
- another object, including a function.
- e.g. lastName = "Smith"
- phone = new Function { ... }
JavaScript Object Notation (JSON)
{"Customer": [{
"lastName": "Doe",
"firstName": "Jane",
"hobbies": ["knitting", "tennis"]
}
]};
for
var Customer = {
lastName: "Doe",
firstName: "Jane",
hobbies: ["knitting", "tennis"]
}
or
var Customer = new Object();
Customer["lastName"] = "Doe";
Customer["firstName"] = "Jane";
Customer["hobbies"] = ["knitting", "tennis"];
or
var Customer = {};
Customer.lastName = "Doe";
Customer.firstName = "Jane";
Customer.hobbies = ["knitting", "tennis"];
Associative Array
- Def: See definition of a JavaScript object
- Every Pick file is an associative array @ID:@RECORD
- Every MV dictionary provides us with an associative array of dictionary name, value for each record
- Note that with an MV dictionary, some items are virtual fields,
which would relate to functions in JavaScript
- Other items are data, just as in JavaScript
- Objects and Types are not handled the same between Pick and JavaScript,
but somewhat similar in that both have forms of duck typing
Arrays, don't use them for Associative Arrays
- Arrays, like colors[] where colors[3] = "blue" are a type of object.
- All objects are associative arrays, so they have properties in the form of tag:value.
- So you can declare something to be an Array and then use it as an associative array.
- This is sometimes done to make it easy to iterate using for...in
- BUT DON'T DO THAT!
- Anything that extends Array via Array.prototype will break for...in loops.
- New iterators are available as of JS 1.5.
XMLHttpRequest (XHR)
- Must send AJAX request to the same server the HTML came from.
- FireFox requires it
- Could use server as proxy for service on another host
- Use it Asynch, not synchronous XHR
- But don't do asynch when synch is required
- IE 7 will have XMLHttpRequest (instead of ActiveXObject)
From prototype.js
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')},
function() {return new XMLHttpRequest()}
) || false;
...
Back Button & UNDO
- What happens when you click the back button?
- Distinquish between Back and UNDO?
- Undo based on order of client events NOT order executed on server.
- By the way, would UNDO be easier to implement with some DBMS's?
- The # portion of the URL is the only thing that can be changed without prompting a reload.
- See Really Simple History and other approaches.
- For addressing the Back Button and Bookmarking.
- Also handles client sessions without cookies.
- You are on your own for UNDO as best I can tell.
Passing Data
- Passing data to server
- Pass parms as text ?tag=value using GET instead of POST if you can
- urlencode for parms passed in URL
- text string returned from server
- If multiple values, then parse it
- Could then use Ian Renfrew's U2 JS functions to change
string to a Dynamic Array
- XML returned from server
- Optionally using XSLT to transform it
- JSON returned from server
JavaScript Tidbits
- innerHTML deprecated; bummer
- Must borrow or write functions to replace it.
- You might need or see this
- url=url+"?unique="+ new Date().getTime();
- since IE will cache the request and response and not reexecute
- SQL Injection
- We are not immune
- SELECT PERSON WITH @ID = $person_id
- Then someone could enter "'12345' OR @ID"
- Yahoo Mail AJAX worm because JS in html executes
- Read up on how to work with JS object prototypes
- Not to be confused with prototype.js
- Inheritance and polymorphism not the same as Java and other OOPs
- Read up on closures, both to avoid them (memory leaks) and exploit them.
Framework Libraries
- An AJAX framework is a JS library or server-side tool that generates the JS that wraps XMLHttpRequest
- They tend to align with server-side languages, but can be server-side independent.
- I chose prototype.js
- And have dabbled with openrico that wraps prototype.
- Instead of reviewing others here, check lists
The Server & Services
Input to the Browser from AJAX Server-side
onreadystatechange
- Fires at each state change
- Check status for 200, statusText for OK
- Perform your JS code if onreadystatechange == 4
- 0 uninitialized
- 1 loading
- 2 loaded
- 3 interactive
- 4 complete
- responseText (or responseXML)
- Response, such as that sent via php echo
Back-end
- URL?this=that
- Your choice of how you want to get a URL connected to code interacting with database
End-to-end AJAX
- Is simply AJAX
- used in a databased application
- with a data model on the back that is similar to the front.
- No Object-relational mapping required.
- No need to squeeze data through a SQL 1NF model.
- No 2VL to 3VL mismatch.
- A single view of data can be more similar to an xhtml view.
- A code file of validation lists can be pulled into a JS associative array
- (More on data models this evening)
Developer Tools
FireFox Add-ins
FireFox Developer Tools
Questions?
Wrap-up
- Applications built with AJAX
- Compared to CUIs?
- Compared to other GUIs?
- Bang for the Buck at this point
- End-to-end AJAX