Archive for the ‘completeui’ Category

* Surfin’ Safari

Posted on October 9th, 2008 by Dave Johnson. Filed under AJAX, CSS, JavaScript, XML, completeui, quirks, safari.


For the past little while I have been busy fixing up Complete UI to work in Safari. The big problem for us in getting Complete UI working in the WebKit powered browser was that there was no client side XSLT JavaScript API until Safari 3.

So there were a few things I had to update to get things all working properly - and this more or less applies to Chrome now as well but I need to check on a few things.

XMLDocument::selectNodes

The first problem I came across was using the XMLDocument::selectNodes method. To get selectNodes working I had to implement my own NamespaceResolver which is usually handled for you by the browser.

I had to change the call to the XMLDocument:evaluate method a bit to look like this:

var oResult = this.evaluate(
  sExpr,
  (oContextNode?oContextNode:this),
  new MyNSResolver(),
  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
  null);

Where the MyNSResolver class essentially implements the lookupNamespaceURI method through a switch statement returning the appropriate URI for the specified namespace prefix. Pretty easy but kinda annoying to figure out!


function MyNSResolver() {};
MyNSResolver.prototype.lookupNamespaceURI = function(prefix) {
  switch (prefix) {
    case "xsl":
      return "http://www.w3.org/1999/XSL/Transform";
      break;
    case "ntb":
      return "http://www.nitobi.com";
      break;
    default:
      return null;
  }
}

XSLT Transformations

Then there was the actual act of performing an XSLT transformation. Doing the transformations was fine but getting the output node or string from the transformations - depending on if the <xsl:output /> was text, html or xml - was rather different than both Firefox and Internet Explorer. Go figure.

For transforming to an XMLDocument here is what I found to be the output of an XML transformation for the various output methods.

Text:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title></title>
  </head>
  <body>
    <pre>innerText</pre>
  </body>
</html>

XML:

<output>innerText</output>

HTML:

<html>
  <body>
    <output>innerText</output>
  </body>
</html>

XSLT Parameters

There is also one difference in how the Safari XSLT processor deals with parameters. Rather than casting true / false to 1 / 0 the Safari XSLT processor does not recognize true or false values and requires the inputs to be 1 / 0. I have started setting all my XSLT params like this:


oXsltProc.addParameter("paramName", val+0, "");

Events and Focus

There were some other small issues that I came across regarding implementing rich keyboard navigation and events in general.

For example, in our Grid component I had to change the HTML element that we used to “focus” the Grid so that we could capture key presses from a <DIV> to an <INPUT>. Apparently you can’t call Element:focus on a <DIV> element from JavaScript but you can on an <INPUT> (even with a tabIndex set but I try to avoid those for accessibility reasons anyhow).

However, that was not my only problem with keyboard navigation. The other problem was that the focusable element (the newly created <INPUT> in this case) was still not getting focus due to a small code snippet like this:


oMyInput.focus();
cancelEvent(evt);

That second line where I cancel the event (wrapped nicely in a cross browser library call) somehow prevents the <INPUT> from getting the focus. Never figured out a workaround aside from a browser check before calling cancelEvent.

CSS

Finally, in some of our components we also generate CSS using XSTL and dynamically insert it into the page. For example, the developer defined column widths in a Grid produce dynamically generated CSS. However, WebKit does not seem to support the bulk creation of stylesheets neither using the document.createStylesheet method of Internet Explorer nor the hacky way of doing in Firefox by creating a <STYLE&gt element and setting the innerText. Instead Safari requires that you use the uber slow DOM API for adding rules to stylesheets :(

Miscellany

You will often see the “xml namespace prefix mapped to wrong URI” error when working with XSLT in Safari.

Be careful that you are using double quotes in your XSLT for attributes etc and only use single quotes in attribute values.

Of course you also have to be very careful about the nodes that you are transforming / selecting as you are also likely to get the “WRONG_DOCUMENT_ERR” fairly frequently.

Oh yah and depending on the application expect a lot of random “Stack overflow” errors!

Tags: , , , , , , , .



* Complete UI Q4

Posted on September 26th, 2008 by Dave Johnson. Filed under AJAX, JavaScript, Nitobi, completeui.


Some big changes are coming in the Q4 release of Complete UI. Big!

Of course there is a slew of JavaScript bug fixes for all the components with Grid receiving the most attention for IE 8, Safari 3, Firefox 3 and Chrome.

There are a bunch of changes to the Java side of Complete UI with more great JSP and JSF code to make it even easier to use Complete UI in your Java project.

Finally, we have also made huge changes to the ASP.NET Grid and Combo code - and are working on the rest of the components as I am writing this! I think that anyone using ASP.NET will be very happy with the new direction of the ASP.NET code :)
We are shooting for an on time Oct 1 release but there is so much we are trying to fit in it might be a bit late - but it will be well worth waiting for!

Tags: , , , , , , , .



* Complete UI Q2 Released!

Posted on May 1st, 2008 by Dave Johnson. Filed under AJAX, JSF, Nitobi, completeui, safari, treegrid.


We managed to finally pull things together and get the release out despite some attempts by .NET build tools to sabotage the entire release!

With this release we now support Safari 3, have added a bunch of new themes to help you make your apps look hot, some new Dreamweaver extensions that mean there is no JavaScript to write to make master-detail grid or combo applications, and most importantly Mike did an awesome job on getting the new TreeGrid component done!

There are some exciting things in the works as well for next week - including screencasts and even some JavaServer Faces love!

.



* Complete UI Q2 Progress

Posted on April 28th, 2008 by Dave Johnson. Filed under AJAX, Nitobi, Uncategorized, completeui, dreamweaver, safari.


We are almost a month behind now on the Q2 release of Complete UI but Mike and I are in the final throws of polishing. We are shooting for releasing today and if that fails tomorrow at the latest. As people will know from the beta we are releasing support for Safari 3, new Dreamweaver Extensions, new themes and, most importantly, a new component called TreeGrid for displaying hierarchical data. I have a can of Red Bull in hand and one last Safari Combo bug to fix before the building will commence!

.



* CompleteUI Q2 Release Update

Posted on March 31st, 2008 by Dave Johnson. Filed under AJAX, Nitobi, completeui.


We are still gathering feedback from our later than expected Q2 Beta release and so are trying to get things working for an April 18 release.

As Sean mentioned on my other post about Q2 Beta there are a few holes in the beta (like .NET libraries :) ) that will certainly be patched up for the release.

Stay tuned as this release should be a great one!

.



* TreeGrid and Safari Almost There

Posted on March 11th, 2008 by Dave Johnson. Filed under AJAX, Nitobi, completeui, safari, treegrid.


Just a few more days until the Q2 Beta!

.



* Nitobi Complete UI Q1 2008

Posted on February 24th, 2008 by Dave Johnson. Filed under AJAX, Nitobi, Performance, completeui.


I made this video the other day highlighting new features in the latest release of the Nitobi Complete UI Ajax framework.

Main points being:

  • Improved Grid performance and file size
  • Drag and fill selection enhancements
  • Better CSS styling and skinning
  • New Support Center
  • Dreamweaver support

Check it out and download the latest code!

.



* Salesforce.com AIR Application

Posted on July 18th, 2007 by Dave Johnson. Filed under AJAX, Nitobi, Web2.0, air, completeui, onairbustour, salesforce.


Since Andre was invited to go on the Adobe AIR bus tour we decided to build a cool sample application that would exhibit some of the cool features of AIR and our components. Since we like to focus on the “business case” for our Ajax components and our custom development, we built an AIR application that integrated with the Salesforce.com API. Being the RIA nutters that we are and knowing that most people would be building Flex based applications - which we are currently building a few of for various customers - we decided to build an HTML / Ajax based application instead.

The cool AIR features that we wanted to show off were things like

      1. custom chrome to make things look hawt
      2. drag and drop from the desktop for vcard integration
      3. file system integration for taking things offline

Since we had a pretty tight timeline we went fairly simple and built the application in about three person weeks. The idea was centered around a mobile sales person being able to have access to their Salesforce Account and Contact data while online or offline. Of course, being an Ajax application it should also prove to be a much nicer interface than the current Web 1.0 based Salesforce user interface - man would I like to be able to redesign the Salesforce UI!

Custom Chrome

The most important part of the application was to make it look hawt. This involved a bit of design assistance from Alexei and the creation of some JavaScript and text based activity indicators since animated gifs don’t work in the current AIR beta :( What we did use a lot though was the CSS3 border-image style. It doesn’t seem to work quite right but if you just go with it you can make something that looks half decent.

So on the outer window we applied a style like this:
[code]
-webkit-border-image:url(../images/app-border.png) 18 18 18 18 stretch stretch; border: 18px;
[/code]

Where the app-border.png looks like this:

As well as looking great the chrome needs to be functional. It needs to have minimize, maximize, restore and close buttons. It needs to be resizable and draggable. Maximize, minimize, restore and close are easy - for example:

[code]
window.htmlControl.stage.window.restore();
[/code]

All of those methods (restore, close, minimize, maximize) are created on the nitobi.air.Window JavaScript class. To enable draggability we attach an HTML event handler to the our main window DIV element like this:

[code]
nitobi.html.attachEvent($(”main_window”), “mousedown”, handleMove, this);
[/code]

The handleMove method is shown below where we just do a quick check first to see if the element that the user is trying to drag has the chrome class on it - this lets us make the window draggable from various points like the header and around the edges. Once they get the chrome we just call startMove() like this:

[code]
nitobi.air.Window.prototype.handleMove = function(evt)
{
if (nitobi.html.Css.hasClass(evt.srcElement, “chrome”))
window.nativeWindow.startMove();
}
[/code]

Desktop Integration

The other cool thing about using AIR is that rather than having some ridiculous multi file upload utility written in Java or Flash, with AIR we can just take files from the desktop and drag them onto the application. What this means is that we can take things like VCards or CSV files full of contact information and have them automagically entered into Salesforce. If offline they get saved as updategrams and get uploaded once the computer is back online. The events for the drag and drop are Flex events on the AIR htmlControl but they connect to JavaScript methods as handlers.

[code]
window.htmlControl.addEventListener(
runtime.flash.events.NativeDragEvent.NATIVE_DRAG_ENTER,
nitobi.lang.close(this, doEnter));
window.htmlControl.addEventListener(
runtime.flash.events.NativeDragEvent.NATIVE_DRAG_DROP,
nitobi.lang.close(this, doDrop));
[/code]

When the drag operation enters the AIR window we call the acceptDragDrop method with the htmlControl as the only argument. This will enable dropping onto our HTML application.

[code]
nitobi.air.Window.prototype.doEnter = function( e )
{
if(e.transferable.hasFormat(air.TransferableFormats.FILE_LIST_FORMAT ) ) {
runtime.flash.desktop.DragManager.acceptDragDrop(window.htmlControl);
onDragEnter.notify();
}
}
[/code]

Now that we have enabled dropping on our HTML app we can actually process the information when it is dropped by accessing the transferred data like this:

[code]
nitobi.air.Window.prototype.doDrop = function( e )
{
var files = e.transferable.dataForFormat(
air.TransferableFormats.FILE_LIST_FORMAT,
air.TransferableTransferMode.CLONE_PREFERRED );
for( var f = 0; f < files.length; f++ ) {
onDragDrop.notify(files[f]);
}
}
[/code]

In this case we specify that the drop should be a list of files and we are able to iterate over that list to add each of the VCards to Salesforce.

Offline Operation

Finally, we did some filesystem integration for working offline and that was pretty cool. Rather than using the SQL-Lite database that comes with AIR, we wanted a solution that would be more conducive to a web way of working - ie something that will essentially queue HTTP POSTs and subsequently POST them when a network connection is present. Because frankly, unless you have A LOT of data on the client and interfacing to a SQL-Lite database is generally going to be overkill and make a lot more work for the developer since they will have to write not one backend in their server language of choice but also a client side backend in JavaScript. Anyhow, in the Nitobi CompleteUI framework, all changes on the client are stored as XML “updategrams”. So it was a pretty easy task to put a layer between the client side JavaScript DataTable and the XMLHttpRequest that sends data to the server when it is “saved”. Instead of the data being sent to the server with an XHR, if the client is offline the updategram is just persisted to disk. Even when online, the data is continually saved to the disk for offline use at any time. All this took very little extra coding since we just serialized the server messages rather than actually transforming them into SQL statements that would store the data in SQL-Lite.

For all of this to work we needed to be notified when the computer is connected to the network. This is done in the nitobi.air.Window class by using the AIR service monitor. This has the additional requirement of having the servicemonitor.swf library in the web page by using a script tag with the src as servicemonitor.swf. To create the service monitor we do something like this:

[code]
var req = new air.URLRequest(’http://www.adobe.com’);
this.monitor = new window.runtime.air.net.URLMonitor(req);
this.monitor.addEventListener(
air.StatusEvent.STATUS, handleStatusChange
);
this.monitor.start();
[/code]

Where the handleStatusChange method will notify any objects that are connected to the the onOnline and onOffline events of the nitobi.air.Window class.

[code]
nitobi.air.Window.prototype.handleStatusChange = function(evt) {
// Fire the event for online / offline notification
if (evt.code == “Service.unavailable”)
onOffline.notify();
else
onOnline.notify();
}
[/code]

For writing the data to disk we use the AIR filesystem integration and wrap it all in two IO methods for reading and writing. The air.File.applicationStorageDirectory is (on Windows) in c:\documents and settings\username\application data\Application-Name folder.

[code]
nitobi.data.IO.readXml = function(filename) {
var file = air.File.applicationStorageDirectory.resolve(filename);
var stream = new air.FileStream();
stream.open(file, air.FileMode.READ);
var str = stream.readMultiByte(file.size, air.File.systemCharset);
stream.close();
return nitobi.xml.createXmlDoc(str);
}

nitobi.data.IO.writeXml = function(xmlDoc, filename) {
if (typeof xmlDoc != ’string’) xmlDoc = nitobi.xml.serialize(xmlDoc);
var file = air.File.applicationStorageDirectory.resolve(filename);
var stream = new air.FileStream();
stream.open(file, air.FileMode.WRITE);
var str = stream.writeMultiByte(xmlDoc, air.File.systemCharset);
stream.close();
}
[/code]

I think that those were definitely the coolest parts of the application and made for a a pretty sweet little app for managing Salesforce Contacts and Accounts. There is still a little more work that I would like to do in the coming weeks like allowing adding and saving of both Contacts and Accounts without VCards as well as some other searching features. Alas, this will have to do for now :) Also, when Adobe gets XSLT support in there it will be even more awesome!

You can check out the half baked source code here and get the AIR application for installation here. I am working on a version of the AIR app that will allow the user to enter their Salesforce.com credentials and actually see their data - and there will be a HUGE disclaimer that you use at your own risk :D
Update: I just found out that the Mac version of AIR does not have XPathResult (!!!) so selectNodes doesn’t work … sorry Mac users but it should be fixed soon.

.



* Grid With AIR and Safari 3

Posted on June 14th, 2007 by Dave Johnson. Filed under AJAX, Components, Nitobi, Web, XSLT, air, apollo, completeui, safari.


With the release of Safari 3 Beta and the recent renaming and Beta release of AIR (formerly Apollo) from Adobe, we have started to work on getting our components running in both of them.

We have run across a few problems - the biggest of which is the lack of any decent debugging tools for either one. I am sure that this will soon change. Currently the best thing around for debugging is Scout.

Grid is being a bit of a challenge given that there is no XSLT support in AIR - though there is in Safari 3. Jake and I got it almost working with a day or so of work / screaming at our computers. Here is a screenshot of what we got so far:

We are pretty happy with the progress and the fact that no one has been hurt - yet ;)
There a few known problems in AIR currently such as CSS opacity not working, table width=0px with colgroups does not work and a few other small things like that. We are certainly happy that Safari 3 and AIR both support addRule and insertRule for working with CSS while a little disappointed in no XSLT support in AIR yet good support in Safari 3.

.



* Complete UI Q2 Released!

Posted on June 3rd, 2007 by Dave Johnson. Filed under AJAX, Nitobi, Uncategorized, completeui.


We were able to get out the Q2 release of Complete UI without too much trouble!

With the help of a keg of beer last night Jake, Mike, Alexei and I were able to pull everything together at the last moment (of course there are a few small things we are still fixin up) and get it out there. Grid is looking awesome with much improved performance and we have also released Spotlight and Calendar - as I have mentioned previously.

Its up online so check it out and let me know what you think :)
Time to catch up on my blog reading / writing and have a looooooong sleep.

.