Thursday, September 25, 2008

Enhancing user experience using Shortcuts


If you get around the blog you’ll notice I targeted a wide range of dynamics usability issues. I’ve done so since I my experience taught me that application “interactivity” plays a major role in end users satisfaction which most agree to be one of the important key factors in successful dynamics implementations.

Most customers will identify the need to shorten the time and complexity (in clicks) it takes to accomplish a certain task and of course invest some of the project founds in building comfortable shortcuts like adding buttons on the grids or even replacing menu items with toolbar buttons. It seems odd that the whole shortcut mechanism is hardly ever used.

Up to a certain point users won’t mind switching between keyboard and mouse in order to fill out an entire form but as users get more and more acquainted with dynamics they search for better and more productive ways to interact with the system. Suddenly switching between devices seems like a waist of good energy. I asked my self that same question! Way can’t I just press (Alt + tab #) to navigate between tabs, or (Alt + S) to send out an email when I finish filling out the form. What about reassigning the form to another user, why do I need to navigate to the third tab to do so, can’t I just ( Alt + w ) to open the assignment window and of course the list goes on and on.

In order to address this I’ve created a very handy utility class which facilitates the creation of shortcuts on all types of crm functions i.e menu items, toolbar buttons, navigation links, fields and tabs. The nice thing about this feature is that it teaches the user to use those shortcuts from a very early stage. Each time the user uses the mouse to click on a “function” with a shortcut the shortcut combination is presented to him and soon he learns to use that instead.

In order to create shortcuts you need to create an instance of the ShortcutMaker class. This class facilitates the creation of all shortcuts on the form.
To create a new shortcut simply use the Add method by passing it a “function” id then use the return Shortcut object SetKeys method to set the special key (Alt or Ctrl), the accompanying letter (Capital) and the type of the function (Button, Menu item, Navigation link and so on). To finish the job use the ShortcutMaker Create method by passing the Shortcut object.


function OnCrmPageLoad()
{
//Create an instance of the ShortcutMaker class
var scMaker = new ShortcutMaker();

//Create a shortcut on the Send Email Button
var FollowUpSC = scMaker.Add( "_MBdocumentallRelatedInformationPaneExpanddocumentallRelatedInformationPaneLoadContextDatafollowup" );
FollowUpSC.SetKeys( scMaker.Keys.Alt , "O" , scMaker.UIType.Button );
scMaker.Create( FollowUpSC );

//Create a shortcut on the toolbar Follow up button
var SendEmailSC = scMaker.Add( "_MBlocAddActTo4202" );
SendEmailSC.SetKeys( scMaker.Keys.Alt , "E" , scMaker.UIType.Button );
scMaker.Create( SendEmailSC );

//Create a shortcut on the History naviation link
var actHistorySC = scMaker.Add( "navActivityHistory" );
actHistorySC.SetKeys( scMaker.Keys.Alt , "H" , scMaker.UIType.Navigation );
scMaker.Create( actHistorySC );

//Create a shortcut on the owner lookup field
var owneridSC = scMaker.Add( "ownerid" );
owneridSC.SetKeys( scMaker.Keys.Alt , "W" , scMaker.UIType.Field );
scMaker.Create( owneridSC );

//Create shortcuts on all form Tabs
var generalTabSC = scMaker.Add( "tab0Tab" ); //General Tab
generalTabSC.SetKeys( scMaker.Keys.Alt , "1" , scMaker.UIType.Tab );
scMaker.Create( generalTabSC );
var notesTabSC = scMaker.Add( "tab1Tab" ); //Notes Tab
notesTabSC.SetKeys( scMaker.Keys.Alt , "2" , scMaker.UIType.Tab );
scMaker.Create( notesTabSC );
var moreTabSC = scMaker.Add( "tab2Tab" ); //Another Tab
moreTabSC.SetKeys( scMaker.Keys.Alt , "3" , scMaker.UIType.Tab );
scMaker.Create( moreTabSC );

//Create shortcut on the AddNote menu item
var addnoteSC = scMaker.Add( "_MIlocAddObjTo5" );
addnoteSC.SetKeys( scMaker.Keys.Alt , "G" , scMaker.UIType.Menu );
scMaker.Create( addnoteSC );
}

function ShortcutMaker()
{
var Instance = this;
var ShortCuts = [];

Instance.Keys = {
Alt : "18",
Ctrl : "17"
}

Instance.UIType = {
Navigation : 1,
Button : 2 ,
Field : 3,
Menu : 4,
Tab : 5
}

Instance.Add = function( controlId ){
return new ShortCut( controlId );
}

Instance.Create = function( shortcut )
{
if( !shortcut )
return;

var hashName = shortcut.SpecialKey + shortcut.KeyCode;
if( shortcut.Control )
{
var controlWithTitle = shortcut.Control;
if( shortcut.UiType == Instance.UIType.Navigation )
controlWithTitle = controlWithTitle.childNodes[1];
controlWithTitle.title = controlWithTitle.title + " (" + shortcut.SpecialKeyName + " + " + shortcut.Letter + ")";
controlWithTitle.title = controlWithTitle.title.replace( /^\s/ , "" );
}
ShortCuts[ hashName ] = shortcut;
}

Instance.OnKeyDownCheckShortcuts = function()
{
var hashName = getSpecialKey( event ) + event.keyCode;
var shortcut = ShortCuts[ hashName ];
if( shortcut )
{
if( shortcut.UiType == Instance.UIType.Menu )
window.execScript( shortcut.Control.action );
else
shortcut.Control.click();

event.cancelBubble = true;
event.returnValue = false;
return false;
}
}

function getSpecialKey( evt ) {
if( evt.altKey ) return Instance.Keys.Alt;
else if( evt.ctrlKey ) return Instance.Keys.Ctrl;
return "0";
}

function ShortCut( controlId )
{
this.Control = document.getElementById( controlId );
this.Letter = "";
this.SpecialKey = 0;
this.KeyCode = 0;
this.UiType = 0;

this.SetKeys = function( spKey , letter , uiType )
{
if( !spKey || !letter )
return;

this.Letter = letter;
this.KeyCode = letter.charCodeAt(0);
this.SpecialKey = spKey;
this.SpecialKeyName = getSpecialKey(spKey);
this.UiType = uiType;
}

function getSpecialKey( spKey ) {
if( spKey == Instance.Keys.Alt ) return "Alt";
else if( spKey == Instance.Keys.Ctrl ) return "Ctrl";
}
}

function Initialize(){
document.attachEvent( "onkeydown" , Instance.OnKeyDownCheckShortcuts );
}

Initialize();
}

OnCrmPageLoad();