Results 1 to 9 of 9

Thread: HTML5 app - How to make spatial navigation with arrow keys work?

  1. #1
    Join Date
    Sep 2011
    Posts
    2

    Unhappy HTML5 app - How to make spatial navigation with arrow keys work?

    Hi everybody,

    How are you?

    I am working on an HTML5 app for Boxee and encountered the following problem:

    I need to have a 'spatial' navigation in my app, so that a user could freely navigate through the focusable items of the page by using UP/DOWN/LEFT/RIGHT keys on the remote control.

    I've set an HTML5 app as described in http://developer.boxee.tv/blog/2011/...html5-o-boxee/ and
    put boxee.setMode(boxee.KEYBOARD_MODE); into the controller.js so that Boxee enables its keyboard mode:

    In this mode of operation, remote control navigation is translated to arrow keys. For example if the user hits the remote’s “up” button, the browser will act as if “arrow up” was pressed on the keyboard.


    Then I set proper CSS styles for focused items. But unfortunately, focus hangs somewhere, perhaps on the body.

    I have experience in writing HBBTV apps where this spatial navigation works right "from the box".

    I also tried adding tabindex attribute in my focusable items without success...

    And finally, got it partially working by using browser.focusPrev(); and browser.focusNext(); but it's a pain as it doesn't allow to navigate freely...
    In this case it would have been better to have methods like browser.focusUp(); browser.focusDown(); browser.focusLeft(); browser.focusRight(); ...

    So, my question is:
    Does Boxee have auto spatial navigation?
    So when user clicks on an arrow key focus moves to the next focusable item?

    If it does, how I may enable it in my HTML5 app? Or there is no such spatial navigation support like in other HBBTV compatible devices which use Opera browser...?

    Thank you!

    Kind regards,
    Alexander

  2. #2

    Default

    The quick answer is no, but its pretty easy to implement on your own, relevant function is update_focus:

    Code:
    <!doctype html>
    <html>
    <head>
    <meta name="boxee-control" content="http://example.com/your-borwser-test-keyboard.js" />
    <style type="text/css">
            .nav_area{width:600px;padding:0 0 0 0;float:right}
            .clickable{border:3px solid #aaa;padding:0;margin:0 3px 6px 3px;background-color:#eee;text-align:center;vertical-align:middle;line-height:100px}
            .box3{width:188px;height:188px;display:inline-block}
            .box1{width:588px;height:188px;display:inline-block}
            .box2{width:288px;height:188px;display:inline-block}
            .clickable-focused{
                border-color:#80ddff;
                background-color:#888;
            }
            .hidden{display:inline-block;float:left}
    </style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <title>JavaScript Key Events into Movable focus</title>
    </head>
    <body>
    <div class="hidden">
    <input id='key_catch' />
    <div id="logger"></div>
    
    <script language="JavaScript">
        var logger = $('#logger');
        logger.html('Press a Key');
        var key_catch = $('#key_catch');
        var keycode = 0;
        var last_key_down = 0;
        var last_key_up = 0;
        var keys_pressed = [];
        key_catch.keydown(function(event) {
            last_key_down = event.keyCode;
            var new_pressed = true;
            for(var i =0; i < keys_pressed.length; i++)
            {
                if (keys_pressed[i] == event.keyCode)
                {
                    new_pressed = false;
                    break;Â 
                }
            }
            if(new_pressed)
                keys_pressed.push(event.keyCode);
            update_focus(event.keyCode);
            return false;
        });
        key_catch.keyup(function(event) {
            last_key_up = event.keyCode;
            push_back = [];
            while(keys_pressed.length > 0)
            {
                key_code = keys_pressed.pop();
                if (key_code !== event.keyCode)
                    push_back.push(key_code);
            }
            if (keys_pressed.length == 0)
                keys_pressed = [];
            while(push_back.length > 0)
            {
                keys_pressed.push(push_back.pop());
            }
            return false;
        });
        key_catch.keypress(function(event) {
          //logger.html(last_key_down+' press');
            return false;
        });
        key_catch.focus();
        setInterval(function(event){
            logger.html(last_key_down+' down<br/>'+last_key_up+' up<br />'+keys_pressed.concat()+' pressed');
        }, 100);
    
        function update_focus(direction)
        {
            var LEFT_CODE = 37;
            var UP_CODE = 38;
            var RIGHT_CODE = 39;
            var DOWN_CODE = 40;
            var ce = $('.clickable-focused'); 
            var te = null;
            var curr_box = ce.position();
    
            var elms = $('.clickable').each(function(){
                var check_box = $(this).position();
    
                if(direction==LEFT_CODE)
                {
                    if ((te == null || check_box.left > te.position().left) && check_box.left <curr_box.left &&  check_box.top == curr_box.top)
                        te=$(this);
                }
                else if(direction==UP_CODE)
                {
                    if ((te == null || check_box.top > te.position().top) && check_box.top < curr_box.top)
                        te=$(this);
                }
                else if(direction==RIGHT_CODE)
                {
                    if ((te == null || check_box.left < te.position().left) && check_box.left >curr_box.left &&  check_box.top == curr_box.top)
                        te=$(this);
                }
                else if(direction==DOWN_CODE)
                {
                    if ((te == null || check_box.top < te.position().top) && check_box.top >curr_box.top)
                        te=$(this);
                }
            }) ;
    
    
            if(te!==null)
            {
                ce.removeClass('clickable-focused');
                te.addClass('clickable-focused');
            }
        }
    
    </script>
        </div>
    <div class="nav_area">
    <div id="bx1" class="clickable box3">1</div><div id="bx2" class="clickable box3">2</div><div id="bx3" class="clickable box3 clickable-focused">3</div><div id="bx4" class="clickable box1">4</div><div id="bx5" class="clickable box2">5</div><div id="bx6" class="clickable box2">6</div>
    </div>
    </body>
    </html>
    update_focus gets a direction as an argument which is a keycode and checks against the arrow keys codes.
    ce stands for current focused element (has the class clickable-focused)
    te stands for target focused element (determined by the update focus function logic)
    the clickable elements are marked with the "clickable" class.

    Using div#logger as a log window method is useful when debugging javascript in the boxee browser. There are better javascript logging and console scripts out there, even firebug has a lite version that is cross-browser (http://getfirebug.com/firebuglite) - i have yet to test in the boxee browser.

    The rest is just some css and jquery sugar.

    Disclaimer: The code above was written by me late at night, its not a "boxee" code and neither boxee or me take any responsibility regarding it. Its free to use and abuse
    Last edited by Lilo; September 21st, 2011 at 04:13 PM. Reason: some explaining of what the code does.
    Liel Dulev fights bugs on boxee's servers
    liel ( @ ) boxee.tv

  3. #3
    Join Date
    Mar 2010
    Posts
    6

    Default

    Quote Originally Posted by Lilo View Post
    The quick answer is no, but its pretty easy to implement on your own, relevant function is update_focus:
    [snip]
    In some cases, I believe this may be too simplistic. In a UI where all the elements are visible, it should work, but what about when you have scrolling type components, where some focusable elements are not visible on the screen? Will the position() call work properly in that case.

    In other platforms where I've had to support spatial navigation, I've found it more flexible to develop my own components, where each component has a setUp, setDown, setLeft, and setRight method. After I create and append the components, I then call the appropriate methods to make the component aware of its neighbors. Internally the component will determine when it is appropriate to call the focus() method on its neighbor.

  4. #4

    Default

    Quote Originally Posted by stevelaw18 View Post
    In other platforms where I've had to support spatial navigation, I've found it more flexible to develop my own components, where each component has a setUp, setDown, setLeft, and setRight method. After I create and append the components, I then call the appropriate methods to make the component aware of its neighbors. Internally the component will determine when it is appropriate to call the focus() method on its neighbor.
    Sounds legit - Why not do that here as well?

    The HTML5 App on boxee is basically a website displayed by the boxee browser, any solution that works in other standards-loving browsers (opera/safari/firefox/chrome) should work here as well.

    The D-Pad navigation is no more than the arrow keys on your keyboard. There is no need for "special" setDirection methods, but if you wish - just write them on your own - or open a feature request on jira.boxee.tv and collect some votes
    Liel Dulev fights bugs on boxee's servers
    liel ( @ ) boxee.tv

  5. #5
    Join Date
    Mar 2010
    Posts
    6

    Default

    Quote Originally Posted by Lilo View Post
    Sounds legit - Why not do that here as well?
    I've only poked around with using the Python API, as the documentation was a little more complete. I will be trying to create an HTML5 one soon, as we've also been using HTML5 lately to develop on the Samsung platform.

  6. #6
    Join Date
    Sep 2011
    Posts
    2

    Default

    Thank you for answering!

    I tried this snippet and did my own and they all work

    Cheers,
    Alex

  7. #7

    Default

    For those developing HTML5 apps, there's also some helpful javascript here:

    http://code.google.com/tv/web/lib/jquery/#keyboard
    (Google TV jQuery UI)

    And for simple keyboard navigation needs (for example, a single grid layout per page) this can work well and is very easy to implement:
    http://mike-hostetler.com/jquery-key...igation-plugin

  8. #8
    Join Date
    Jul 2012
    Posts
    1

    Default Wordpress integration

    Hello, I think this is awesome for accessibility reasons. Could you perhaps show how to load this globally into Wordpress? I hop you get my message I would love to work with or get some feedback in the area of accessibility that I'm working in. Thanks for the code so far though.

  9. #9

    Default

    I'm haven't used wordpress for a really long time so I can't help you there. Maybe someone who wrote a wordpress theme or plugin can help you out.
    Liel Dulev fights bugs on boxee's servers
    liel ( @ ) boxee.tv

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •