Document Properties
Kbid27Y346
Last Modified23-Jun-2020
Added to KB02-Dec-2015
Public AccessEveryone
StatusOnline
Doc TypeGuidelines, Concepts & Cookbooks
Product
  • ICM 7.6
  • Omni-Channel Services Toolset
  • ICM 7.7
  • ICM 7.8

Guide - OCST (Omni-Channel Services Toolset) Keyboard Interaction

1 Introduction

The OCST respects the keyboard shortcuts defined by the common operating systems and browsers to avoid confusion of the user with divergent shortcuts. Therefore, the CC has a set of shortcuts of its own.

There are several websites that deal with the shortcuts of operating systems and browsers:

2 Useful Libraries

The plugin jQuery Hotkeys supports the handling of keyboard events.

3 Shortcuts

Controls have to be put in a useful order so that the user can navigate them via tab key. Therefore they should have an attribute tabindex to specify the position in the tabbing order.
It must be possible to interact with the OCST with defined shortcuts.

3.1 Implementation

The global shortcuts are defined in ContactRoute.js and can be adapted easily:

...
function(Ember, AuthenticatedRoute) {
      var ContactRoute = AuthenticatedRoute.extend({
          needs: ['coBrowse'],
          shortcuts: {
              'alt+b': 'coBrowse',
              'alt+i': 'showContactOverview',
              'alt+q': 'endContact',
              'alt+c': 'showCouponPage',
              'alt+o': 'showQuickOrderPage',
              'alt+l': 'showStoreFinder',
              'alt+s': 'showProductSearch',
          },
          actions: {
              coBrowse:            function coBrowse() { ... }
              showContactOverview: function showContactOverview() { ... }
              endContact:          function endContact() { ... }
              showCouponPage:      function showCouponPage() { ... }
              showQuickOrderPage:  function showQuickOrderPage() { ... }
              showStoreFinder:     function showStoreFinder() { ... }
              showProductSearch:   function showProductSearch() { ... }
          },
...

The template Contact.jsp contains the global links with the their defined shortcuts. The shortcuts are appended to the link wrapped in a <kbd> which handles this switchable visibility.

<li class="pull-right">
    <a href="#"{{action "coBrowse"}}><span class="glyphicon glyphicon-new-window"></span> {{i18n "co_browse.button.label"}} <kbd>Alt+b</kbd></a>
</li>
{{#link-to 'contact.overview' tagName="li"}}
    {{#link-to 'contact.overview' name="overviewPage"}}{{i18n "application.overview.link"}}<kbd>Alt+i</kbd>{{/link-to}}
{{/link-to}}
{{#link-to 'quickOrder' tagName="li"}}
    {{#link-to 'quickOrder' name="linkOrderPage"}}{{i18n "application.quick_order.link"}}<kbd>Alt+o</kbd>{{/link-to}}
{{/link-to}}
{{#link-to 'promotions' tagName="li"}}
    {{#link-to 'promotions' name="linkCouponPage"}}{{i18n "application.promotions.link"}}<kbd>Alt+c</kbd>{{/link-to}}
{{/link-to}}
{{#link-to 'contact.storeFinder' tagName="li"}}
    {{#link-to 'contact.storeFinder' name="linkStoreFinderPage"}}{{i18n "application.store_finder.link"}}<kbd>Alt+l</kbd>{{/link-to}}
{{/link-to}}

3.2 Used Shortcuts

3.2.1 General

Key EventAction
Alt+K

Shows all possible shortcuts of the page (shortcut hints)

For example before using this shortcut:

For example after using this shortcut:

Alt+QFinishes the current session

3.2.2 Customer Search Form

Key EventAction
Alt+eShow the extended search
EnterSearch for a customer

4 Navigation with Arrow-Keys

In order to support navigation with arrow keys, a concept has been implemented that allows developers to define groups of selectable elements. Within a group the selected entry can be changed by using the up and down arrow keys (↑,↓).
If a page contains multiple groups the keys left and right (←,→) can be used to switch the group. A selected entry can be opened or confirmed using the Enter key.

This general behavior is implemented in the main JavaScript cc-app.js:

cc-app.js
 // General key up/down handler for arrows
        $(document).keydown(function(e){
            if(e.which == 37) { // left
                var currentFocusGroupItems = $('[data-keyboard-focus-group]');
                var currentFocusGroup = $(':focus').closest('[data-keyboard-focus-group]');
                var prevIndex = ( currentFocusGroupItems.index(currentFocusGroup) - 1);
                if (prevIndex < 0) prevIndex = 0;
                
                $(currentFocusGroupItems).eq(prevIndex).find('[data-keyboard-focus]:first').focus();
            }
            if(e.which == 39) { // right
                var currentFocusGroupItems = $('[data-keyboard-focus-group]');
                var currentFocusGroup = $(':focus').closest('[data-keyboard-focus-group]');
                var nextIndex = ( currentFocusGroupItems.index(currentFocusGroup) + 1);
                
                $(currentFocusGroupItems).eq(nextIndex).find('[data-keyboard-focus]:first').focus();
            }
            if(e.which == 38) { // up
                var currentFocusElement = $(':focus');
                var currentFocusGroupItems = currentFocusElement.closest('[data-keyboard-focus-group]').find('[data-keyboard-focus]');
                var prevIndex = ( currentFocusGroupItems.index(currentFocusElement) - 1);
                if (prevIndex < 0) prevIndex = 0;
                
                $(currentFocusGroupItems).eq(prevIndex).focus();
            }
            if(e.which == 40) { // down
                var currentFocusElement = $(':focus');
                var currentFocusGroupItems = currentFocusElement.closest('[data-keyboard-focus-group]').find('[data-keyboard-focus]');
                var nextIndex = ( currentFocusGroupItems.index(currentFocusElement) + 1);
                
                $(currentFocusGroupItems).eq(nextIndex).focus();
            }
        }).keyup(function(e){
            if(e.which == 13) { // enter
                $(':focus').click();
            }
        });

To define an focus group container any container element (like a <div>) has to be marked with the attribute data-keyboard-focus-group="".
Within this container the selectable items must be attributed with data-keyboard-focus="" and they additionally should have a tabindex.
As mentioned above it is possible two have multiple focus group containers at one page. Therefore, multiple <div> containers can be defined.

jsp file
    <!--- Define a data-keyboard-focus-group --->
    <div class="row" data-keyboard-focus-group="">
        
        <a href="#" tabindex="-1" data-keyboard-focus="">
            {{show-address address=selectedCommonShipToAddress}}
        </a>
        
        <a href="#" tabindex="-1" data-keyboard-focus="">
            {{show-address address=selectedInvoiceToAddress}}
        </a>
        
        ...
    </div>
    
    <!--- Define another data-keyboard-focus-group --->
    <div class="row" data-keyboard-focus-group="">
    
        ...
    
    </div>

5 Testability

EmberJS is able to define keyboard events onmost of the HTML elements.

Testing the existing keyboard events is possible and as easy as it could be.

Go to the view where the element is contained in and add a keyDown event the the view.

Example of binding a keyevent
CCApp.ServiceRequestView = Ember.View.extend({
    keyDown: function(e) {
    	if (e.keyCode == 85) {
        	this.get('controller').send('assignCustomer');
        	return false;
        }
    }
});

Note

Events will be triggered only when the focus is on a HTML input element.

There is an alternative option for defining global keyboard events.

Example of the binding of a global keyboard event
$(document).bind('keydown', 's', function (evt) {
	$("[name='customerSearch']").click();
	console.log("Customer link " + $("[name='customerSearch']").attr('href') + " clicked!");
	return false;
});

5.1 QUnit

If you want to test mouse or keyboard events in QUnit, you have to use one of the following code snippets.

Test events with Qunit
// click the given element
click('[data-testing-id="organization"]');
 
andThen(function() {
	// assertion area
});
 
// fire the keydown event with the keycode '13' on the given element
keyEvent('[data-testing-id="organization"]', 'keydown', 13);
 
andThen(function() {
	// assertion area
});

5.2 Geb + Spock

Click tests based on Geb and Spock can also test keyboard interactions using the following code snippet:

$("input", name: "firstName") << Keys.chord(Keys.CONTROL, "P")

Disclaimer

The information provided in the Knowledge Base may not be applicable to all systems and situations. Intershop Communications will not be liable to any party for any direct or indirect damages resulting from the use of the Customer Support section of the Intershop Corporate Web site, including, without limitation, any lost profits, business interruption, loss of programs or other data on your information handling system.

Customer Support
Knowledge Base
Product Resources
Support Tickets