Article written

  • on 14.11.2009
  • at 08:20 PM
  • by mich

Onscreen Keyboard with AIR 9

Nov14

In one of my last projects I had to develop an air application with an onscreen keyboard that is working with flash as with the internal html browser of air.

I realized pretty quickly that this isn’t that easy as it seams. There are multiple problems especially with the html view:

  • how do i get the focus in the html view to add letters.
  • how do i get the selection to add chars on the right position.
  • how do i know when a user clicks and inputfield/textarea.
  • how do i prevent that flash do set the focus on the keyboard when I click on a letter sprite.

After some experiments I discovered the really nice javascript support of the internal browser. So my first problem was already gone, when I found the javascript command:

var webView:HTMLLoader = new HTMLLoader();
//...later, to get the element with the focus call:
var element:Object = webView.window.document.activeElement;

I wasn’t really into javascript so I was surprised to discover even more possibilities. Now with the focus I can place an onscreen keyboard made with flash and get the activeElement of the htmlloader and add characters to it. something like this:

var inputField:Object = webView.window.document.activeElement;
if( inputField != null ) {
   var select:Number = addScreenBoardText( e.char, inputField, "value", "selectionStart", "selectionEnd" );
   inputField.setSelectionRange( select, select );
}

The function where I add the char and return the selection where the cursor should be set:

private function addScreenBoardText( insert:String, object:Object, textAttribute:String, selectionStartAttribute:String, selectionEndAttribute:String ):Number {
  var selectionStart:Number = object[ selectionStartAttribute ];
  var selectionEnd:Number = object[ selectionEndAttribute ];
  var original:String = object[ textAttribute ];
  var newText:String = original.substring( 0, selectionStart ) + insert + original.substr( selectionEnd );
  object[ textAttribute ] = newText;
  return selectionStart + insert.length;
}

Why I make this weird looking function is because I can use it also for the flash TextField just with different parameters. So now we can add letters to a textfield in a html view as a flash TextField. But one big problem is that we loose the focus every time we click on our on screen keyboard. And there is a way to prevent the change of the focus which is very handy in this situation:

 // in our main application class we listen to the mouse focus change event.
addEventListener( FocusEvent.MOUSE_FOCUS_CHANGE, onMouseFocus );

// in the listener we check if the relatedObject is a Key,Screenboard ( these are my classes for the Keyboard that get mouseclicks )
// then we prevent the default behaviour of the event. which means no focus change is triggered.
private function onMouseFocus( fe:FocusEvent ):void {
if( fe.relatedObject is Key || fe.relatedObject is ScreenBoard ) fe.preventDefault();
}

We saw earlier that is was possible to write to javascript objects as normal in actionscript. I was even more surprised as its possible to listen to javascript events with actionscript functions. That allows me to listen to javascript focus changes and hide/show the keyboard. This way I can make an overlay keyboard that is only visible when I click in a textfield which I find is a very nice solution. So this is how I listened to the javascript events ( keep in mind that this is all actionscript ):

// register everytime the page has loaded!
private function onPageLoaded( e:Event ):void {
  webView.window.addEventListener( "focus", onJavaScriptFocusIn, true );
  webView.window.addEventListener( "blur", onJavaScriptFocusOut, true );
 }

// if we get a focus in event from js, check if its a inputfield or a textarea. then show the keyboard.
private function onJavaScriptFocusIn( e:Object ):void {
  if( e.target.localName == "input" || e.target.localName == "textarea" ) {
    dispatchEvent( new JavaScriptEvent( JavaScriptEvent.FOCUS_IN ) );
  }
}

// we lost focus - hide keyboard
private function onJavaScriptFocusOut( e:Object ):void {
  dispatchEvent( new JavaScriptEvent( JavaScriptEvent.FOCUS_OUT ) );
}

With all this you can build your onscreen keyboard that is working in flash as in html. I made a quick flexbuilder air project that you can download with a keyboard, textfield and htmlloader.

subscribe to comments RSS

There are 9 comments for this post

  1. Paddy says:

    I am trying to develop a small personal interface that uses a touch screen. I have been looking for a virtual keyboard that is web based. That I can load from a webpage. Is that what your above keyboard does?

  2. mich says:

    hi paddy
    in a way it is – but it runs as an air application so the keyboard is build with flash and then uses the browser that comes with the adobe air runtime.

    if i get your idea right you want a keyboard that runs inside any browser?
    then you probably build better a frameset and search for a virtual javascript keyboard if this exists…

    how you do this also depends on the os you are working with..

    feel free to ask if you need more infos.

  3. Paddy Haig says:

    Hi mich, I have looked high and low for a virtual keyboard that may suit my needs and cannot seem to find anything. I cannot believe the is nothing out there. What I am trying to develop is a kiosk type application that is run within a browser session. e.g. If you were to open up Firefox and hit the F11 key for full screen, Then click on a link on a web form interface that would bring up a virtual keyboard filling the lower third of the screen using Flash or Flash/Air or Java. This would then be used in touch screen kiosk mode. I want it in a browser session so that it is consistent across all operating systems. Again it’s for a touch screen kiosk using web/php forms running through a web browser.

  4. mich says:

    Hi paddy,

    Your main problem is that your air/java app that is started out of the browser should communicate with firefox which is as far as i know not possible. also to start the external app it is not possible without a bunch of confirmation boxes. you probably should choose a different approach:
    start an air/java app, that can display webpages. in air for example that would be the html control.

    If you need the firefox browser, you probably stick with some of the plugins
    This way you dont need to code.

    let me know which way you choose.

  5. Nim says:

    I have i try but cannot handle input text field of an html object.
    My air app is an desktop touch app with a virtual keyboard, i call an Facebook login and how do i know when a user clicks and inputfield/textarea of facebook login page to show my Keyboard.
    Is it can or cannot?
    Please help!

  6. mich says:

    hi nim,

    to know when a user clicks on an inputfield/textarea you have to register a function to the “focus” event of javascript like this:
    webView.window.addEventListener( "focus", onJavaScriptFocusIn, true );
    That will call the onJavaScriptFocusIn function when the user clicks on an element that can get a focus.
    have a look on the last code snippet in the article where i listen to the focus and blur event to know when the webview got or loses the focus on something.

  7. roman says:

    Hellow mich.
    To be honest i’ve lost any hope trying to find exectly that example.

    i’m building Air desktop app’ that will be in a tuch-screen kiosk, basicaly a user creats a custumized picture after taking a snapshot with the buitin camera and uploads it to his facebook.

    i’ve come as far as creating a custumized keyboard with a software, much like microsofts on screen keyboard and lunching it as a process throught air when the login dialog appears, then turning it of when login finished/canceled.
    - bad idia

    im developing with flash cs and the htmlloader is created and lunched through the facebook’s api, i’ve already modified most of it to prevent unwanted user interaction.

    I hope i’d be able to reverse-engeener you example and implent it because it’s basicaly the last issue I have in this project.

    thank you!

  8. roman says:

    I DID IT! :)

    hopefully this will help the next one who finds this through google:

    in com.facebook.graph.windows.AbstractWindow.as:

    need to add:

    public static var focusChangeFunction:Function;

    and to the handleHtmlDomInit() (triggers on Event.HTML_DOM_INITIALIZE):

    html.window.addEventListener( "focus", onJavaScriptFocusIn, true );

    when onJavaScriptFocusIn changed to:

    protected function onJavaScriptFocusIn( event:Object ):void {
    if( event.target.localName == "input" || event.target.localName =="textarea" ) {
    focusChangeFunction(html.window.document.activeElement);
    }
    }

    ——————————————

    in your project, import com.facebook.graph.windows.AbstractWindow and:

    import com.facebook.graph.windows.AbstractWindow;

    private var focusedBox:Object = null;

    AbstractWindow.focusChangeFunction = function(obj:Object)
    {
    focusedBox = obj;
    }

    modify:

    function onMouseFocus( fe:FocusEvent ):void {
    if( fe.relatedObject is Key || fe.relatedObject is ScreenBoard )
    {
    fe.preventDefault();
    }
    else focusedBox = null;
    }

    everything else stays basicaly the same, instead of using webView.focus just use focusedBox.

    thank you again mich!!!!

  9. roman says:

    i’d help anyone who stumbles on this problem, event if you find it a year from now

    roman@maxsave.co.il

Please, feel free to post your own comment

* these are required fields

Developed by Dariusz Siedlecki and brought to you by FreebiesDock.com