Monday, March 12, 2012

FITC Amsterdam 2012: Open web technologies as an alternative to plugins

This is a short recap of a presentation made during FITC Amsterdam 2012. Kudos for the presentation content goes to the presenter. Please use the resource links at the end of this post to get more information from the source.

Michal Budzynski, a web game developer from Poland, shared some of his HTML5 come backs to typical doubts about HTML5 related technologies coming from Flash developers. Since Michal is not a Flash developer himself he had to ask some of his Flash developer friends about why they still preferred Flash over HTML5. These are some of their most usual reasons for favoring Flash coupled with plausible HTML5 alternatives suggested by Michal.

Flash developer: With Flash you can access the users camera.
Michal: HTML5 has the getUserMedia API.

Flash Developer: Flash can go full screen
Michal: With HTML5 you can call requestFullScreen on any page element

Flash developer: Flash can create desktop apps
Michal: You can also do that using XUL

Flash developer: There are Flash debugging tools
Michal: There are similar tools in browsers, firebug in Firefox, developer tools in Chrome, Venkman javascript debugger in FireFox (https://developer.mozilla.org/en/Venkman).

Flash developer: You can create P2P with Flash
Michal: You can use Web Sockets, Easy Web Sockets http://easywebsocket.org/ or upcoming WebRTC http://www.webrtc.org

Flash developer: For Flash there are services like Mochimedia and Kongregate for integrating with social media etc.
Michal: Similar services are starting to surface also on the HTML side, like bluevia.

Flash developer: Flash has DRM
Michal: Google are working on specs to secure web content. The open web community takes pride in staying open.

Flash developer: Flash has decent development tools
Michal: There are good alternatives for HTML5; cloud9ide.com, bly.sk, gordon/shumway and bikeshed.

All in all another one of those Flash vs HTML5 presentations. On several of the points mentioned above Flash is still ahead, HTML5 is catching up but there is still some time until new specifications turn into stable technologies with decent browser support. What I mostly take with me from this presentation is a few of the useful resources mentioned for HTML5 development, like the cloud9 IDE and the Venkman JavaScript debugger.

Resources:

FITC Amsterdam 2012: Getting acquainted with jQuery

I believe I promised to post some recaps of the presentations I attended during my visit to FITC Amsterdam the other week. This is the first one, stay tuned for more.

This is a short recap of a presentation made during FITC Amsterdam 2012. Kudos for the presentation content goes to the presenter. Please use the resource links at the end of this post to get more information from the source.

Matt Fisher made a simple but useful introduction to jQuery. For anyone who hasn't used jQuery in a project before, like myself, this was a nice presentation for getting acquainted with the framework. This is what I got out of it.

jQuery is a JavaScript framework for boosting productivity for any JavaScript developer. It was first created by John Resig in 2004 and has been developed and improved since then. Current version is 1.7.1 and its main advantage over the widely used and stable version 1.6 is all about performance improvements.

jQuery is light-weight, widely used and accepted and should, according to Matt, be an integral component in the toolbox of any serious web developer.

The jQuery framework consists of the following parts:

  • jQuery core – The core APIs provided by of the jQuery framework
  • jQuery UI – provides useful user interface components like tree navigators and grids
  • jQuery mobile – a relatively new addition to the jQuery family for supporting development for mobile
  • Qunit – A unit test framework to use for java script development
  • Sizzle – The selector engine for locating elements in the dom tree of an html page
...and its functionality can be divided into the following main areas of use:
  • Modify CSS
  • Alter HTML
  • Respond to user interaction
  • Animate elements
  • Retrieve information from external resources

Short examples on each of the aforementioned functionalities are available from Matt Fisher's blog.

Matt also made a strong point about the licensing of jQuery and many other open source libraries out there. jQuery adheres to the MIT Licence and all you basically have to do to freely start using the framework is to keep that copyright notice at the top of the source files. If you remove the copyright notice or start copying and pasting parts of the framework and passing it off as your own you are violating the license and by doing that you are basically breaking the law. Perhaps that goes without saying but it was clear from the reaction of the audience that many of the present developers had been doing just that.

I asked Matt about the development environment that he would suggest for starting to work with jQuery or javascript and HTML development in general. As he had grown accustomed to using eclipse based development environments he recommended Aptana Studio. That description also applies to myself so I'll be checking it out.

Resources:

Thursday, March 1, 2012

FITC Amsterdam 2012: All about HTML5

There has been a while since my last blog post here. A lot of things have been going on in my life since then, I got a little kid, moved back to Sweden after several years abroad and I moved into a new apartment in Malmo. Finally things have settled a bit and I have been able to find some time to produce more content for the blog between remote working, diaper changing and home styling.

It's been about a year since I first started this blog with a visit report from FITC Amsterdam 2011. I was there again this year and this is what I got out of it.

Last years conference was mostly about the Flash vs HTML5 debacle. At that point HTML5 was still very new, browser support was bad, performance even worse and for application development Flex and Flash still seemed like the better choice.

A lot of things has happened over the past year and HTML5 has gained significant grounds in terms of technology advancements and general acceptance during that period. At the same time the uncertainties surrounding the Flash platform over the past few months have made decision makers more reluctant to choose Flex for their next project and are opting for HTML5 solutions.

This was also reflected in the program of this years conference. The vast majority of the technology related presentations were all focusing on HTML5. Even the keynote presentation by Adobe was all about what they are doing in the HTML5 field and you could see an evident change of focus and strategy from this big player in both fields.

So does this all mean that Flash is dead? Not necessarily. The message from Adobe is that the future of the Flash platform will be focussed on advanced gaming and premium video. The idea behind it being to not try to do everything and support every use case, but focus on one or a few main areas, and do them really well.

So for me as a developer using Flex, what is the way forward? Well I guess whenever you are presented with a new project it is still a question of choosing the right technology for the job. For a decently sized enterprise application project I would probably still go with Flex. Even if most of the things that you can do in Flex can now be accomplished with HTML5 related technologies HTML5 still has a long way to go in terms of development experience, tooling and browser support.

I would also keep an eye on what the community can do for the future of Flex now that it has been donated to the Apache foundation as an open source project. Maybe at some point we could even have a decent Flex to HTML5 compiler with a few tweaks in the language specification. The conference made me start thinking and I'll try to gather my thoughts on the future of Flex in a later blog post.

I had a great time at this years FITC Amsterdam, as did I last year. Interesting and relevant presentations, inspiring atmosphere and some very cool people. Add some free beers to the mix and you have a great event right there. I will definitely try to return again next year.

Stay tuned: Over the coming days I'll be publishing short recaps of the various presentations I attended during the conference, it will be almost as if you had been there yourself;

Friday, June 17, 2011

Flex: dragDropEvent is not dispatched if feedback is set to none

A few days ago I posted about how setting the useRollOver style to false on a List control also prevents the itemRollOver event from firing on that same control:

Flex: Changing useRollOver style affects itemRollOver event

In other words, what I thought would only affect the visual appearance of a component turned out to also have an impact on the components logic. I realized that some time ago I ran in to that same scenario in the context of drag & drop. I thought I'd share that here as well.

So, basically, I was implementing some drag and drop functionality for our application. When the user started a drag action I changed some parameters in the application to reflect that a dragging was currently under way. When the user stopped his dragging I was relying on the dragDropEvent to restore the application to its original state or update it depending on the drop location.

The above was implemented and was working fine. Next step was to show different cursor icons depending on which areas of the screen the user was currently dragging over, the green plus for allowed drop locations and the red cross for prohibited locations. This was easily accomplished by using the DragManager.showFeedback function passing it DragManager.COPY or DragManager.NONE respectively. Unfortunately it showed that this change also caused the implemented logic to fail. The dragDropEvent handler was just not invoked if the feedback was set to none.

Looking back at it now, I suppose it kind of makes sense and my implementation became a bit more clear after reorganizing it to account for the encountered issue. Still, it took me a while to figure it out and I also couldn't find any mentioning of this 'feature' in the documentation. It just doesn't feel right when changing the visual feedback of your application also affects the functionality. MVC, anyone?

Tuesday, June 14, 2011

Flex: Changing useRollOver style affects itemRollOver event

The other day I ran into a bug in our application that was a bit unintuitive to track down. Suddenly the context menus used on a Tree component in our application started to behave weird. Anytime the context menu was opened the menu items in it referred to the first item in the Tree rather than to the item below the mouse cursor. To give some context, this is how the context menu logic for the Tree component is setup:

We have a variable called 'lastRollOverIndex' that is updated whenever the user hovers an item in the Tree. This variable is updated with the Tree index of the last rolled over item using the itemRollOver event of the Tree control. Whenever the user then right clicks the Tree control the lastRollOverIndex is used to get the item currently under the mouse cursor and the statuses and captions of the context menu items are updated accordingly before the context menu is shown to the user.

And now, seemingly out of the blue, the above functionality failed to work. So I started going through the recent change sets in our repository to try to find out what could be the cause of this problem. Interestingly, the search showed that no changes had been made to any files containing the logic for the above, the only change between a working and a non-working version of the application was some updates to the stylesheet.

But, could that really be? Updating some styles to changes the visual appearance of the application would also cause the logic of the same to fail? Well, answer is yes.

So one of the changes in the stylesheets was setting useRollOver to false for all List components to turn of the highlighting of items while hovering the list. Since a Tree is an extension of a List the change also applies to Tree components. So far, so good. But now we come to the unexpected part. Turns out, setting the useRollOver style also prevents the itemRollOver event from being dispatched which in turn killed the logic for our context menus. At least to me, this was not what I expected, and from what I could find in the documentation it is also not mentioned there.

So in order to disable the highlighting but still allow the itemRollOver events to fire I chose to override the drawItem function of the Tree control:

protected override function drawItem(item:IListItemRenderer,
    selected:Boolean = false,
    highlighted:Boolean = false,
    caret:Boolean = false,
    transition:Boolean = false):void
{
    super.drawItem(item, selected, false, caret, transition);
}

Friday, April 29, 2011

Flex: Custom context menu

Background

I never really liked the context menus supplied by the flash player that you are bound to use when developing flex applications. Mostly because of the non-customizable look and feel and the fact that your application specific menu items will be in the same list as the built in items (you can't hide all of them). Since we are using context menus in many places in our applications I have been looking at the following solution for a while to replace the built in menus:

http://code.google.com/p/custom-context-menu/

This solution uses javascript to capture the right click event over the SWF to prevent the flash player from opening its built-in context menu. The event is then passed on to a function that communicates with Flash over the ExternalInterface. The function called in action script is then free to do whatever it likes to act upon the performed right click.

The drawback of the solution is that it relies on using wmode='opaque' for the flash object and this does not work reliably across different browsers and operating systems.

Anyway, when running into the following bug with the latest Safari browser (5.0) on Mac:

http://bugs.adobe.com/jira/browse/FP-4825

I decided to go ahead and implement custom context menus, at least for our Mac users.

Implementation

The implementation relies on the solution mentioned above for handling the right click events and passing them on to the Flex application. An action script function then traverses the components currently located below the mouse pointer until it finds one that has a context menu defined. The found ContextMenu object then gets wrapped in a CustomContextMenu wrapper that uses the original context menu to create and show a regular flex menu.

The CustomContextMenu wrapper also makes sure that the enabled and visible statuses of the context menu items are also reflected in the items of the generated menu. Last but not least the wrapper makes sure that any user actions on the generated menu are dispatched as events on the original context menu so that the behavior of the original context menu is preserved in the new menu.

That's it. Enough talking. Let's look at the code, feel free to re-use it in any way you deem fit:

This is the code for the CustomContextMenu wrapper:

CustomContextMenu.as

package com.flexceptional.components
{
    import flash.events.ContextMenuEvent;
    import flash.ui.ContextMenu;
    import flash.ui.ContextMenuItem;
    
    import mx.controls.Menu;
    import mx.events.MenuEvent;
    
    public class CustomContextMenu
    {
        private static var SEPARATOR:Object = {type: "separator"};
        
        private var _menu:Menu;
        private var _contextMenu:ContextMenu;
        
        public function CustomContextMenu(contextMenu:ContextMenu)
        {   
            _contextMenu = contextMenu;
            
            // Create menu
            _menu = Menu.createMenu(null, null);
            
            // Add event listeners
            _menu.addEventListener(MenuEvent.MENU_SHOW, menuShowHandler);
            _menu.addEventListener(MenuEvent.ITEM_CLICK, itemClickHandler);
            
            // Set properties
            _menu.setStyle("openDuration", 0);
            _menu.variableRowHeight = true;
            _menu.id = "contextMenu";
            
            // Create custom menu items
            var menuItems:Array = [];
            for each (var item:ContextMenuItem in contextMenu.customItems)
            {
                if (item.separatorBefore)
                {
                    menuItems.push(CustomContextMenu.SEPARATOR);
                }
                menuItems.push(new CustomContextMenuItem(item));
            }
            _menu.dataProvider = menuItems;
        }
        
        private function menuShowHandler(event:MenuEvent):void
        {
            _contextMenu.dispatchEvent(new ContextMenuEvent(ContextMenuEvent.MENU_SELECT));
        }
        
        private function itemClickHandler(event:MenuEvent):void
        {
            event.item.dispatchEvent(new ContextMenuEvent(ContextMenuEvent.MENU_ITEM_SELECT));
        }
        
        public function show(xShow:Object = null, yShow:Object = null):void
        {
            _menu.show(xShow, yShow);
        }
        
        public function hide():void
        {
            _menu.hide();
        }
    }
}

import flash.events.ContextMenuEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.ui.ContextMenuItem;

// ContextMenuItem wrapper
class CustomContextMenuItem extends EventDispatcher
{   
    private var _contextMenuItem:ContextMenuItem;
    
    public function CustomContextMenuItem(contextMenuItem:ContextMenuItem)
    {
        _contextMenuItem = contextMenuItem;
        
        // Dispatch event on the proxied ContextMenuItem
        addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function(event:Event):void
        {
            _contextMenuItem.dispatchEvent(event);
        });
    }
    
    public function get label():String
    {
        return _contextMenuItem.caption;
    }
    
    public function get enabled():Boolean
    {
        return _contextMenuItem.enabled;
    }
    
    public function get visible():Boolean
    {
        return _contextMenuItem.visible;
    }
}

This is the function invoked by the java script, place it in your main application (the optional x and y arguments can be used for automated testing):

private var customContextMenu:CustomContextMenu;

private function rightClickHandler(clickedX:Number = NaN, clickedY:Number = NaN):void {
    // Close previous context menu
    if (customContextMenu)
    {
        customContextMenu.hide();
    }
    
    clickedX = isNaN(clickedX) ? mouseX : clickedX;
    clickedY = isNaN(clickedY) ? mouseY : clickedY;
    
    // Get objects under clicked point
    var objects:Array = systemManager.getObjectsUnderPoint(new Point(clickedX, clickedY));
    if (objects.length > 0)
    {
        // Get the top most object clicked
        var object:Object = objects[objects.length-1];
        
        // Check if any of the parent objects have
        // a context menu defined
        while (object)
        {
            if (object.hasOwnProperty("contextMenu") && object.contextMenu)
            {
                customContextMenu = new CustomContextMenu(object.contextMenu);
                customContextMenu.show(clickedX, clickedY);
                break;
            }
            object = object.parent;
        }
    }
}

The code snippet for making the above function available through the ExternalInterface, place it in the initializeHandler of your main application file:

// Enable custom right click functionality
ExternalInterface.addCallback("rightClick", rightClickHandler);

We use the following javascript function to initialize the right click handling only for Mac users running Safari 5, place it in your html template and call it on the onload event on the body tag:

function initRightClick() {
    if (BrowserDetect.OS == "Mac" &&
        BrowserDetect.browser == "Safari" &&
        BrowserDetect.version == "5") {
        RightClick.init();
    }
}

The BrowserDetect object referenced in the above function comes from a file created using the code posted on this page:

http://www.quirksmode.org/js/detect.html

So, big post, feel free to comment on it if you have any questions or doubts. The solution provides a nice workaround for the Mac Safari 5 context menu bug and since our context menus can now be invoked by calling a function from javascript it also allows for us to do automated testing of our context menus using our integration test setup. More on testing in a later post.

Friday, April 15, 2011

Install stand alone Flash player on 64 bit Ubuntu

We are running our Flex unit tests on a 64 bit Ubuntu machine as part of our continuos integration environment. In order to run the tests we need to have the stand alone version of the Flash player installed. Unfortunately there is not yet a 64 bit version of the flash player projector for linux so to run our tests we need to use the 32 bit version.

These are the steps needed to install the 32 bit stand alone flash player under a 64 bit Ubuntu:

  1. Download the 32 bit Flash player projector from http://www.adobe.com/support/flashplayer/downloads.html

    > wget http://download.macromedia.com/pub/flashplayer/updaters/10/flashplayer_10_sa.tar.gz

  2. Unpack the flash player executable and make sure you put it on your path.

    > tar -xzvf flashplayer_10_sa.tar.gz

    Now, if you try to run the Flash player, chances are you will get an error message similar to the following:

    > flashplayer
    flashplayer: error while loading shared libraries: libX11.so.6: cannot open shared object file: No such file or directory

    This is because the 32 bit Flash player also requires 32 bit versions of certain libraries to be installed. If you run ldd (print shared library dependencies) on the flash player executable you will be presented with a list of the required libraries:

    > ldd flashplayer

  3. Install required 32 bit libraries. Luckily, most of these libraries can be installed by installing a single package using apt-get:

    > apt-get install ia32-libs

    If you now run ldd on the flash player again you should see that the library dependencies have been resolved and, if you are lucky, the flash player will now launch.

Good luck!

Note that these were the steps required for our installation, another platform might require additional steps or libraries.