Page Lifecycle, DOM and Events

Ajax DOM On The Server

Jaxer is a true Ajax server: the Ajax technologies you know from the browser, namely the HTML DOM, integrated with JavaScript, and equipped with XMLHttpRequests, are all available on the server side. And it's not just "an" HTML DOM, with some integration with JavaScript, and with some surface similarities with the browser. Jaxer incorporates the very same Mozilla engine that powers Firefox3, so it's "bug compatible" with what you find on the browser. It parses and executes the page progressively, building up the DOM as it goes along, and allowing JavaScript to interact with whatever DOM has already been built up at the time the JavaScript executes. Any document.write() calls will write to the DOM immediately following the current location on the page. The JavaScript on that page, and loaded into the page, executes within the context of the window global object. The document is accessible through the document object, and the entire DOM is accessible through the document.documentElement object. And so on...

In fact, it's probably better to concentrate on the few differences between what happens on the server and what happens on the browser, as we do below. Except for these, you can assume that the same DOM and JavaScript APIs and interactions are available in Jaxer as in the browser. Browsers are in fact a bit different from each other, so more specifically the variant that's available in Jaxer is Firefox 3.

Page Lifecycle

To understand the differences between the server and browser sides, it's important to keep in mind the page lifecycle:

  1. The page request from the browser is received by the web server, which fetches the appropriate HTML document (either from the file system or perhaps from another "handler" such as PHP or Ruby or Java).
  2. It then feeds the document to Jaxer, which begins to parse the HTML document. As it does so it builds up the DOM tree.
  3. When it encounters <script> tags it not only adds them to the DOM but may also execute them if they have a runat attribute that indicates they should run on the server.
  4. During the parsing and execution, external content may also be fetched and loaded into the document, via <script src="..."></script> elements and Jaxer.load(...) for JavaScript code, or via <jaxer:include src="..."></jaxer:include> (or <jaxer:include path="..."></jaxer:include>) for HTML content, or via XMLHttpRequests for any content.
  5. After the DOM is fully loaded, the onserverload event is fired. This is the server-side equivalent of the onload event on the browser. It's named differently so your code can react separately to onserverload and onload events.
  6. Jaxer post-processes the DOM to carry out its built-in logic and prepare the DOM for sending to the browser: removing <script> blocks meant only for the server, replacing functions to be proxied with proxies, saving (as needed) functions that should be available on callbacks, etc.
  7. Finally, the DOM is serialized back to HTML, and that HTML is streamed back via the web server to the browser.
The resulting HTML page is sent back to the browser as the response to its request...
  1. The browser begins to parse the HTML, building up the DOM.
  2. When it encounters <script> tags it not only adds them to the DOM but also executes them.
  3. External JavaScript code or any other content may be loaded too.
  4. The onload event fires.
  5. Of course the page is progressively rendered throughout much of this flow, and also the user can interact with it.
Callbacks from the browser to server-side functions are handled via XMLHttpRequests.
  1. When Jaxer receives such a request, it creates a new, empty document (unless configured to use a different static document).
  2. It retrieves the saved functions that needed to be made available during callbacks to this page (the details of exactly how this is done are currently changing somewhat).
  3. If a function called oncallback is found, it is executed. This is usually used to create the enviro0nment needed during a callback, if the saved functions are not enough.
  4. The callback function itself is executed.
  5. Finally, the result of that execution is packaged and returned as the response to the XMLHttpRequest.
Note that while a DOM is available during callback processing, it is not serialized as HTML and returned as the response, as it was during the "regular" (non-callback) page processing flow.

Note that the DOM on Jaxer and the DOM on the browser are not synced in any way. Yes, they are both ultimately created from the same HTML source, but they are often subject to processing by different JavaScript code, and they come to life at different points in the page lifecycle: the DOM on Jaxer exists temporarily wheh the page is processed by Jaxer, and is eliminated after it's been serialized into the HTML sent to the browser; the DOM in the browser is built, on the browser, from that HTML, and is the DOM that's rendered to the user and with which the end-user interacts. This makes evident the few differences between the Jaxer and the browser DOMs:

Different JavaScript:

While Jaxer and the browser may well share some code (e.g. when using runat="both"), usually the JavaScript code designated to run on Jaxer and interacting with the Jaxer DOM is different than the code designated to run on the client. The latter exists e.g. as a <script> tag in the Jaxer DOM but is not executed in Jaxer.

Only the Jaxer DOM is Serialized and Sent to the Browser

Remember that the only things sent to the browser at hte end of page processing is what's actually in the DOM, and what Jaxer has added such as proxies, clientData, and injected scripts. So if e.g. you've added an expando property, that's an in-memory change to the DOM that will not get serialized and hence will not appear on the client side: On the browser you'll find that the div is present, with an id of "myDiv", but without a "userId" property.

For this same reason, setting event handlers programatically rather than in the DOM will not translate to DOM changes and hence will not propagate to the browser. Say we have a button: We could always just add an onclick="..." attribute to the tag, but what if we want to add the event handler programatically? Jaxer provides a Jaxer.setEvent(domElement, eventName, handler) function that "does the right thing" in Jaxer as well as on the browser: Note that it's important that the function used as the event handler be made available in the browser (client). When setEvent is executed on the server, as above, it results in the following change to the myButton element: Since this is a DOM change, it is sent to the browser. If the function passed into setEvent has no name, its body (source) is used as the value of the attribute: results in which is useful for short functions. But it's even easier to just pass in the code to execute as a string: results in

Note that Jaxer retrofits common <form> elements such that programatically setting their values actually changes their DOM attributes. Thus, you can write Though on a browser this would actually only set the value of the "myTextBox" input in memory, in Jaxer the "value" attribute of that element is automatically set to "sample value" in the DOM, and hence is transmitted to the client. This is true for the other form elements too.

Some Things Only Make Sense in the Browser

(Coming soon...)

The Jaxer DOM Itself is Not Rendered

(Coming soon...)