Funky Town: Friendly Siebel Applets

This post is part of the Funky Town series of articles, where we take ridiculous User Centric Design (UCD) requirements and put them into practice.

[Scenario]

The business wanted yet another button on a common applet, but the applet was already crowded with buttons (pictured below). The plan was to consolidate the functionality behind the different buttons, and reduce the clutter on this applet, as it was becoming a real eye sore.



I advised on removing the last two buttons, as they were too specific and its appropriateness was questionable, but i was told that users loved those buttons as they are the two most heavily used buttons in the application! Since the client was paying my wages, who am I to argue?

The second idea was to combine the 3 search buttons into one, since they all perform the same basic functionality "Search"

"Search Client Id"
"Search Client Name"
"Search Client Address"

The problem was, in the current design, the above buttons each invoked a separate VBC Search applet which called an external interface that only allowed mutually exclusive queries by Id, Name or Address, which is why they were designed separately in the beginning.

The agreed design going forward, was to combine all the fields of the above 3 applets into one super search applet, but we needed a way of preventing the user from entering data into different search categories on the same interface call.

The standard approach is to use validation to return an error message when the user hit the "Submit" button. This option achieves the requirement, but it provides a horrible user experience. Imagine the user filling in every section of the form, because it allowed them to, but when they click "Submit", an error pops up, the form is returned to the user, and they have to go through and re-fill the form correctly.

We should aim to design our application to be more intuitive (take inspiration from what Apple did with the Smart phone market =), so the proposed design was to have the fields in the relevant section dynamically became read only or read write as the user typed, this will block out fields that cannot not be filled in.

[Requirement]

a) There are 3 sections, A, B & C on a Search applet.

When the user begins typing in any one section, all the fields in the other two sections should be disabled.



Eg.
If a user types something in a field under section A, all the fields in section B&C would be disabled.

If a user types something in a field under section B, all the fields in section A&C would be disabled.

If a user types something in a field under section C, all the fields in section A&B would be disabled.

b) When the user clears the all field values from any section, all the fields in the entire applet should be re-enabled again.

[Solution]

In HI, there are two control events that are usable on form applets.

onBlur
onFocus

We will use onBlur, because when the user moves from one field to the next, we can implement logic to dynamically enable or disable the rest of the fields on the applet.

Firstly put in our trigger on each control that is editable by the user, put the following code in the onBlur handler

setSectionReadOnly( [section id] );

[section id] is a predefined identifier that you assign to each section in the form. It can be called anything. In our form applet, there are 3 sections, which we'll call a, b, c.

So for all the fields under section "a", you would put the following in each fields onBlur handler

setSectionReadOnly("a");

For every field under section "b", you would put

setSectionReadOnly("b");

and so on.. what this does, is tell our yet to be created function, that every time the user leaves an editable field, send the current field section to our function to determine the UI behaviour.

Now we define the function that is responsible fore enabling/disabling the fields dynamically.

declarations()
var thisApplet = this;

function setSectionReadOnly(sSection)
{
//control object defining allowable applet search sections
var oCTRL = {};
oCTRL.a = ["Id Type","Id Num"];
oCTRL.b = ["Family Name","Given Name"];
oCTRL.c = ["Address Line 1","Address Line 2","Address Line 3", "Address Line 4"];
var bNotEmpty = false;
try {
//check current search section for existence of a search value
for (var i=0;oCTRL[sSection].length>i;i++){
if (thisApplet.FindControl(oCTRL[sSection][i]).GetProperty("ReadOnly")=="true")
return;//abort if active field is RO
if (ctrl.GetValue().length>0){
bNotEmpty=true;//flag first non empty field
break;
}
}

//if current search section has a search value make every other section RO
if (bNotEmpty){
for (var key in oCTRL){
if (sSection!==key){
for (var i=0;oCTRL[key].length>i;i++){
thisApplet.FindControl(oCTRL[key][i]).SetProperty("ReadOnly", "TRUE");
}
}
}
} else {//if current search section is empty then make the whole applet RW
for (var key in oCTRL){
for (var i=0;oCTRL[key].length>i;i++){
thisApplet.FindControl(oCTRL[key][i]).SetProperty("ReadOnly", "FALSE");
}
}
}
}
catch(e) {
//handle error
}
}


Compile your super friendly search applet, and watch your users frustration disappear =). I'm sure you'll agree that dynamically disabling irrelevant fields, and preventing users from entering invalid data is much more friendly, than allowing them to enter invalid data, and complain that the user got it wrong afterwards.

The implementation in this example, was used to illustrate a working concept, there are numerous ways of optimizing this code to perform better, so it should not be copy and pasted across your application.

[Conclusion]

1. Will it perform well?
Yes, there are no server calls, and all the magic happens client side, saving a round trip to the server.

2. Is it maintainable?
Yes, if the logic is made production ready

3. Can it be upgraded?
Yes, as it does not use any undocumented methods

and finally the litmus test

4. Is it sexy?
Yes, and it is also very intuitive


0 comments:

Post a Comment

Comments are open to all, please make it constructive.