Donnerstag, Dezember 27, 2007

Useful OpenAjax Event Logger

While working on further adopting the OpenAjax event mechanism I wrote this small JavaScript include file that helps inspecting the current OpenAjax events.

It is implemented by using a single JavaScript include file that can be found at http://www.mathertel.de/AjaxEngine/controls/OpenAjaxEventLog.js (view source).

It is easy to include this file into ANY web page by using a small JavaScript link (a.k.a. bookmarklet) that you can type into the address bar or save as a link in your favorites:

Create any Link in your favorites, or the link bar and name it for example like this:

Here is the url that you can paste into the url field in the property dialog of the link.

javascript:void(document.body.appendChild(document.createElement('script')).src='http://www.mathertel.de/AjaxEngine/controls/OpenAjaxEventLog.js')

There will be one dialog that warns you about the fact that the url is using JavaScript (an unregistered program - what means that ?) and that this may be unwanted. But in this case it is what we need.

You can open any of the sample pages from the http://www.openajax.org/member/wiki/InteropFest_1.0 and try it.

If you click on the link you just created a extra area will be appended at the bottom of the page and all OpenAjax events will be shown in there.

 

If you like to know more about bookmarklets you can google this term and you will find a lot more tricks.

My favorite is:

javascript:'<xmp>'+document.documentElement.outerHTML+'</xmp>'

Mittwoch, Dezember 19, 2007

Passing values around with OpenAjax events

When publishing and receiving OpenAjax events there is the built-in mechanism of passing a payload a.k.a publisherData around together with the event. When implementing applications based on OpenAjax events there are some more things you should care about when using the publisherData feature. In the specifications you can also find some guidelines.

1. Don’t change the publisherData when handling an event.

That’s already said in the specification. Another and not so explicit mentioned argument for not doing so is the fact that there may be multiple subscribers to the same event. Because the sequence of the elements that receive the event is not determined you do not know whether a control gets the original or the modified publisherData. Anyway these situations are hard to debug – another reason to avoid them.

2. Don’t use objects – use strings instead

Right now the OpenAjax hub implementation is client side only but you can expect that events can also be spread other windows on inner iframes. In both cases direct object references are a problem because they cannot pass completely. If you need more than simple values consider using a proprietary format like "29.0016;18.5337", a JSON or an XML string.

And don’t assume when passing a numeric value that the subscribers get them as a JavaScript Number object.

It seems that strings are fine. :-)

3. Don’t use language specific formats

Users like to enter values into fields by using their culture or national language specific notations. Most keyboards here in Germany have a comma in the numeric keypad and a many people would not agree in typing dots when filling out fields for example with prices.

If you pass a "1.777,88" around you must assume that all subscribers can understand this specific notation. You can’t assume that if you like to live in meshup scenarios where the connected components come from different world wide vendors or sites. You even can’t assume that when writing a web application for the German speaking market: the Swiss people like the format: "1'777.88".

A good idea is to pass the values as defined by JSON and make them directly useable by scripting.

4. Don’t pass date values

Passing date values is somewhat problematic because there is no JavaScript constant definition (a.k.a. JSON) for that datatype. :-(

I recommend using the XML notation that is based on ISO 8601 date and time formats: "2007-12-24T18:00:02", but I must admit that that's my personal preference based on the fact that I prefer XML and SOAP.

Mittwoch, Dezember 12, 2007

Using OpenAjax events for building data-centric and forms based AJAX applications

Most of the business web applications on the Internet are HTML forms based applications where html elements are bound to data is the core functionality. I am talking about registration forms, dialogs and pages to display and modify records of a server side relational database system like in ERP or CRM systems.

Usually there is not a lot of drag & drop activity or popping visual effects here but the most active elements deal with data that comes from databases or other data sources. We need to display, edit and control records from a company's database and implement transactions on these entities.

Here is an approach to use the OpenAjax event mechanism to implement this kind of web applications. The beauty of it and the reason why I implemented this for the AjaxEngine open source project is that using events and namespaces is a far more open approach then the mechanism that I introduced some time ago and has a neat extensibility model.

Typical data-centric web pages

Using OpenAjax events for building data-centric and forms based AJAX applications

From a high level viewpoint onto pages that implement data-centric applications you see that the elements on the page can be categorized into the following cases:

  • Fields and other elements where values are shown and edited by the users (Input fields, checkboxes, ...)
  • Buttons that help editing these values (calendar popup, drop-down lists, ...)
  • Foreign key Lookup mechanisms (checking against a list of countries, ...)
  • Buttons that offer a way of navigation through huge data sources (|< first, next >>, ...)
  • Buttons that commit a current state to the backend system ([Update])
  • Buttons that trigger special transactions or back-end calculations

Forms in this kind of scenario are just a collection of html elements that together can be used to display or edit a single record of a given schema.

Where to use OpenAjax events

Events can help in these situations where a direct connection between components is not desired or otherwise problematic:

1. events on the field-level

On the field-level (inside the form) data is passed around when the value of a field or another data control is changed. This happens either by a user interaction with a field or another data control or as part of a situation on the record level for example when a new record is displayed.

If a field exists it can subscribe to the appropriate event and can display the value passed around. On the other side it can also publish a new event if the user changes the value.

It doesn’t matter if a real field is used or a slider, a calendar popup or a 3d spin control. Even multiple controls that subscribe to the same event can coexist side by side without knowing from each other.

Conclusion 1: Using OpenAjax events gives us the advantage of having a simple plugin mechanism that is extendable.

2. events from the menubar

Clicking a button already publishes the HTML built-in onclick event. However this event is only passed to those elements that are clicked directly or are part of the control hierarchy of the html object model. The menubar catches these events and transfers them into OpenAjax events that are passed to all elements that are interested because they have subscribed them. These events in contrary to the html DOM events are carrying a semantic by using the full eventname and eventually by carrying some data with them.

Conclusion 2: Using OpenAjax events can add semantic statements to events.

Conclusion 3: OpenAjax events are independent from the html DOM layout and therefore can help separating the UI model from the event model.

These 2 scenarios fit well into the OpenAjax event standard.

Antipatterns to OpenAjax events

1. events between tight coupled components

The datasource controller and the form element are 2 components that share some information flow. However every situation in this scenario is started by the datasource controller. The case where a user wants to “update” the datasource controller has to request the current form data from the form. Using is not practical because the form element that would receive the event will not be able to “attach” the current form data. A direct connection is more adequate approach by sharing a common interface like the 3 methods.

Conclusion 4: Using OpenAjax events to retrieve information is not a practical solution. Tight coupled components are still an option.

Note: Maybe some other control is interested in the fact that new data is available in the form which is done through a write() call. This can be the reason for publishing an event by the datasource controller that expresses that.

2. events between passed between client and server

The datasource controller also has to exchange data with the server. This is a direct end to end communication that happens every time a record is fetched from the server or a record should be updated. OpenAjax events can’t cross this boundary (yet) and again there is return data that is not available immediately when using asynchronous calls (I hope you do for reasons of robustness).

Conclusion 5: Remote Procedure Calls situations should be implemented by using a high level AJAX protocol.

Using attributes on controls to define the event names

One design convention that is used within the DataControls is that the eventnames that are used by controls can be split into 2 parts: the namespace and the local name.

The event “de.mathertel.datasource.search” that is used by the search button in the menubar has the namespace “de.mathertel.datasource” and the local name “search”. The eventname can be specified on the button itself ion 2 ways.

  1. When the eventname attribute contains a dot character it is assumed that the value already contains a full qualified event name.
  2. When the eventname attribute contains no dot character the parent elements are scanned for a “eventnamespace” attribute ant the effective event name is built by combining them.

Here is the sample of the html code:

<div id="datamenubar" class="VEMenuBar" eventnamespace="de.mathertel.datasource">
  <span hover="true" class="VEMenu" tabindex="1" eventname="search">Search</span>
  ...
</div>

This convention helps writing short html attributes and allows an easy changing of the namespace that is used for a collection of controls.

Currently the menubar control and the ajax form control both use this mechanism for building the full qualified even names from the eventname / eventnamespace attributes.

That’s the blue print of the current changes that took place in the AjaxEngine project. The even simplified the way Ajax Forms can be implemented and helps minimizing the code that we usually need to connect all the elements in a typical data-centric web application.

Have a look at the sample: http://www.mathertel.de/AJAXEngine/S06_AJAXForms/SimpleReader.aspx. If you scroll down the page you can also see a region with a protocol of the raised events.