Adobe Air 2 Beta Finally Out!
In an industry that are working with virtual file systems and online document management (www.knowledgetree.com), I have been waiting for this moment for some time now – Adobe Air 2 is finally in beta.
This version of Air opens up several new functionalities – eg. :
- Drag & Drop support of remote files via the filePromiseList clipboard object.
- Socket Server Support – Air apps can now listen on a port and no longer need to initiate a network conversation. This also enables different air apps to now communicate with each other using socket connections.
- New Filesystem API – This includes functionalities like being able to open files with their default registered application, flag files as downloaded so that the operating system can warn against opening them and notification of mounting and dismounting volumes.
- NativeProcess API allows you to execute a third party process and interact with it.
- Microphone Capabilities allows you to access raw data from the microphone, inspect it, alter it, encapsulate it as WAV and store it to the local filesystem.
- HTML5 & CSS3 Support will let you implement the provisional features of next-gen interactive document markup.
For more information on where to get all this goodness: Adobe Labs
Adobe Air MouseLeave Window
It took me a while to figure out how to get an Air application to let me know when the mouse leaves the window. Once I got it.. easy as pie:
window.nativeWindow.stage.addEventListener('mouseLeave',function(e){
alert('The mouse just left the Window');
});
Tada!
Zend Server 5.0 Beta Code Tracing
Zend Server 5.0 Beta is promising an awesome bug-tracking method that will help find and solve problems much easier. Whenever an error is encountered, the new tracing feature will automatically log full error tracing information – even when in production mode.
Just as cool, one can manually run the trace to profile the execution of your code in real time. This will allow you to find bottlenecks, see the function tree for the entire execution of your script and use that information to optimize execution.
Take a look at Zend
jQuery & JavaScript Tips to Improve your Code
Here’s a nice post on TripWire Magazine on improving your JavaScript coding, especially in jQuery.
It deals with these topics:
- Improving your selector skills
- Testing for empty collection containers
- A URL you can use to get the very latest jQuery on page load
- Using callbacks to synchronize Effects
- Using the Event model for DOM and custom object interaction
- Creating custom selectors & how to use them
- Making entire elements clickable – the easy way
- Preloading images – jQuery style
- Disabling / capturing right-click contextual menu
- Grouping queries for simpler code
- Using QUnit for integrated unit testing
To find the article, go to TripWire Magazine
Converting Binary String to ByteArray
While using HTML/JavaScript in air, I have found no way of getting the Air-Ajax functionalities to run in synchronous mode. For this reason we are forced to manage certain upload / download functionality using the XMLHTTPRequest object available via Javascript.
However, one quickly runs into problems trying to write binary strings requested in this fashion, to the local file system. Write operations for binary files need to be passed a flash ByteArray object that contains the data.
Here is how to convert a JavaScript binary string to a ByteArray, ready for use with file IO functionality in Adobe Air:
string2byteArray=function(str){
var ba=new air.ByteArray();
for(var i=0;i<str.length; i++){
ba.writeByte(str.charCodeAt(i));
}
return ba;
}
Hope this helps some.
Drag Server Side File to Local Explorer in Air
Before we complicate things by discussing the actual file download, let’s take a quick look at how the drag & drop functionality works.
Drag & Drop Model
When dragging and dropping items between different windows, whether it be in Windows, Mac or Linux, a standardized process seems to be in place to handle it.
First, it would be a breach in the application security sandbox if an application could access the drop event of something that was drag off itself and onto another window. For this reason, if you drag an element from the Air application window to any other window on the OS, you will only be able to access the onDragStart event and will never have access to the actual drop event.
The method for communicating with the application on the receiving end of the drag drop operation is via the clipboard. As soon as a drag event off the air window is detected, one should populate the clipboard with a set of information you wish to send to the receiving application.
File Copy Clipboard Process
Next we take a look at what the general process is whenever files are copied from one window to another on most platforms. The clipboard must be populated with an array of file location objects (that actually exist on the machine). When dropped, the receiving application will perform a copy or move operation on the array of file locations sitting in wait in the clipboard.
The issue that becomes immediately obvious from this is that when dragging a file or a set of files from an air application to the desktop/explorer, the file might not be available locally as it might represent files or folders residing on the server side. Since we cannot capture the drop event on the receiving application, and since the files don’t reside locally at the moment the drag event starts, there is no information we can put in the clipboard that will cause the receiving application to download the files being dragged.
Clipboard data handler function
The clipboard handler, fortunately allows one to provide a function rather than actual data when setting it. The clipboard will then execute the function and take the result of that function and place it in the clipboard. This is what saves our butts here.
The idea is to create a function that will:
- Asynchronously get each file in the drag list from the server and save it to a local, temporary location.
- Generating a list of these now local files in the temporary folder after all the downloads have been completed.
- Return this file list as a clipboard object and specify the move rather than the copy method.
This function should then be passed as the clipboard data handler function.
There are still some issues surrounding this method (a period during which the application might freeze if you opt for using synchronous file downloading) that could be dealt with by displaying information about the progress of the file download using the same function passed to the clipboard.
Onwards & Upwards!
How To Secure Login Credentials for Ajax
Many JavaScript and other clients that make use of REST or other web services have to use authentication credentials to allow the end user access to those services.
There are several ways to get the credentials to the server. One popular method is using HTTP1.1 Auth, either digest or basic. The problem with this method is that it doesn’t hide your credentials from the world. Anybody listening in on your web traffic is essentially able to get your credentials from the headers.
Another method, probably more readily used by the majority, is to include login credentials in the POST or GET calls being made to web services. And that is just as exposed.
http://mywebserver.com/mywebservice/?user=admin&pass=1234
does not make for very high transport security.
SSL is really the only way to be sure that your credentials remain hidden from the rest of the world.
Server Generated Tokens for Obscuring Login Credentials
I have taken up a different tactic. It runs the following course:
- The client requests a random token from the server to use during it’s session.
- Once it receives the token the client concatenates the token to the end of the password, and then does an MD5 hash on the whole thing.
- When credentials are needed by the server, the client then passes user=’username’&passhash=[md5(password+token)]
- The server compares this with the same process on it’s end. If the two hashes match, then the passwords used in those hashes has to be the same as well.
The beauty of this method is that although it is a 100% reliable method for correctly identifying the correct credentials, it is also impossible to reverse the process and get the password back.
Taking things one step further
The initial step for me was to use [md5(password+token)]. I have now updated it use a variety of information I would like to hide:
[md5(username+password+my_ip+token)] which has some built in cross-site scripting obfuscation built in.
A devious and very zealous hacker can still hijack your session with some effort. And you can make sure it is not worth his/her while by regularly changing the token for the current session.
KnowledgeTree JavaScript API
As a developer on KnowledgeTree I am currently working on set of JavaScript libraries that will expose server functionality via an API. A core component of KnowledgeTree is it’s strict security. The method mentioned above (or a variant of it) is in the process of being implemented for KnowledgeTree jAPI.
*KnowledgeTree is an OpenSource Document Management System for SMB to Enterprise level entities.
Onwards and Upwards!
DOM Events Not Enough
With the move towards Web2.0+ technologies, more and more websites are employing JavaScript to create in-browser applications. User actions are dealt with as DOM events to which you can attach functionality.
In this model it is fairly easy to write small interactive sites. It becomes a pain to code larger Web2.0 type applications in this framework. There are several reasons for this:
- DOM Events are not semantically meaningful in the context of your application. Essentially, one is forced to write a user action response engine rather than an application. A button containing an onClick event tells me nothing about what it means when I click that button.
- An interface event might change it’s behaviour depending on the application state. This is still doable in the normal browser event model, but it becomes more and more tangled as your application become more complex.
- DOM events make it difficult to implement the MVC model. To simplify the code, it is often easier to directly link interface events to the actions they must trigger. This can lead to code where an onClick event contains a function that fetches XML from the server, parses it, and displays it at the correct place on the interface. As your application grows it becomes more and more difficult to follow the code process.
Multiple Languages
Whenever we are dealing with intelligent web-based applications, there are usually quite a few languages involved. The application intelligence is split up between HTML, JavaScript, CSS, Java, Flash, PHP, ASP, SQL and others. This can lead to very tangled code that gets increasingly more difficult to understand as the complexity of your application grows.
It is becoming more and more important to find creative ways of marking your code in order to be able to easily follow the flow.
Web Applications – More Than Just Interactive Websites
Right at the beginning of the Web2.0 revolution, JavaScript and AJAX were used very sparingly and mostly just for interactive enrichment. Those days are over. Users have become accustomed to and are expecting full blown applications running in the browser.
Add to that the general expectation that whatever is in the browser, should be customizable to suit the needs of each and every individual user that pops by for a visit, and you have a recipe for an explosion of source-code.
In this environment, dealing with DOM events become even more of a nightmare.
Semantic Events – A Possible Solution?
In my personal journey toward complex web-based applications, I have found a way to simplify the process and bring scalability back into the picture: Abstracting towards a flexible event delegation model.
How does this work: simple really.
I start off with a JavaScript object I created that manage semantic events. I will discuss this in detail a little later. First let me explain the process of handling a DOM event using my semantic event engine.
Step 1 - Map a DOM event to a semantic event
Instead of calling the intended function straight from my ‘onClick’ event, I map it to a semantic event:
<a href=”Javascript:;” onClick=”sEvents.trigger(‘request_more_contact_info’);”>Contact Us</a>
Step 2 – Create the function that will deal with that event
function handleMoreContactInfoRequest(){
// Call AJAX handler to get the info requested
// Call the UI handler to create a new modal popup box
// Populate the modal box with the AJAX response received
}
Step 3 – Make my handler function listen to the semantic event
sEvents.listen(‘request_more_contact_info’,handleMoreContactInfoRequest);
Application Triggered Events
At first this might seem like a longer way of doing things. I could just as well have called my handler function directly from my onClick event.
For a simple example like the one above, you may be right. When the scope of your application grows, however, it becomes a lot more manageable to use a semantic event dispatcher.
One example of this is how you can modularize your code using application triggered events.
Let us take the previously mentioned event handler and modify it slightly.
function handleMoreContactInfoRequest(){
sEvents.trigger(‘ajax_request_started’);
// Call AJAX handler to get the info requested
sEvents.trigger(‘ajax_request_ended’);
// Call the UI handler to create a new modal popup box
// Populate the modal box with the AJAX response received
sEvents.trigger(‘handleMoreContactInfoRequest_completed’);
}
Now we have expanded the scope of events beyond basic browser DOM events. We now have application level events that can delegate tasks to any listeners bound to the relevant semantic event. If, for instance, I wanted an indicator showing when an ajax request is under way, i could create a function to show and hide the indicator and bind them to the ajax_request_started and ajax_request_ended events respectively.
Multiple Listeners
The event manager I wrote has support for multiple listeners to any given event. This makes augmenting interaction an easy task. I only need to add a listener in order to extend it’s functionality.
Usually when an extension of this nature is needed, it makes for messy code. I might have to do some ui related stuff, ajax stuff and also DOM updates & datastructure modifications every time a certain button gets clicked. Using the straight-forward DOM event method, I would either have to include all those functions in my onClick event, or I would have to include those functions in my event handler.
With event delegation and semantic events, you can organize your application in a structure that is logical to you without losing any functionality.
Code Modularization
One of the major benefits I find with using this method: I can now replace, maintain, upgrade, extend or completely change the way a particular event is dealt with very easily.
When calling a function directly from a DOM event, one is allowed a lot of freedom with regards to what information you pass along. This seems convenient in the beginning, but later on when you want to make changes to your application, this turns into a nightmare.
Having an event delegation model forces you to always pass information to the event manager in the same format. And the event manager will call the event handlers in a standard way. This forces one to stick to a convention when dealing with user-interactions and even application-initiated events.
Ultimately, it is this convention that saves you time in the future. Event handlers now all have the same inputs. And event triggers always look the same. Which means it becomes a lot easier to replace portions of your code or do site upgrades. It also makes documenting your software a lot easier.
HTML is largely a semantic markup. It is human readable for the most part. Adding semantic events that relate not to what the user did in the browser but rather what the user is trying to accomplish, fits in well with the semantic nature of HTML. This means, your web designer doesn’t need to know anything about the underlying work of the web developer to be able to effect changes on the interface. Events are now semantic, readable and easy to call. And they never need to change, no matter what happens in the underlying engine. There’s a huge business implication there.
Hard to Reach Browser Events
Using this event delegation model, it also becomes a lot easier to deal with hard-to-reach browser events. In my event delegation engine, I have most of these browser events automatically included in case my application needs to access them. If, for instance, I need to know when the mousewheel is being scrolled, I just attach a listener to the ‘browser:mousewheel’ event and my application can make use of it.
Want to disable the right click button in the browser?… easy:
sEvents.listen(‘browser:mouse.click.right’,function(){return false;});
Want to capture CTRL-ALT-LEFTCLICK:
sEvents.listen(‘browser:mouse.click.left|key_ctrl,key_alt’,function(){alert(‘you just CTRL-ALT-LEFTCLICKed’);});
aFrame – The Javascript Client-Side Application Framework
By now, some of you might want to have the code to this event manager. It is part of a larger framework intended to make writing enterprise level in-browser applications a lot easier. This framework is called aFrame and it not yet ready for alpha testing.
If you would like to receive word when this framework is ready, you can subscribe to the announcement list below.