Kbase P16591: How to create an auto-completion function ?
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  11/5/2009 |
|
Status: Verified
GOAL:
How to create an auto-completion function ?
GOAL:
How to create a type-ahead function ?
GOAL:
How to implement an auto complete feature in 4GL ?
FACT(s) (Environment):
Progress 9.x
OpenEdge 10.x
All Supported Operating Systems
FIX:
An auto-completion function is a function that lets an application complete the value in an input area based on what the user has already entered.
The value with which to complete the input is re-determined every time the user adds to the input area.
For example, if the user has entered "A", the application will fill this out with "A & A Athletic & Recreation". If the user continues typing to "ABC", the application will complete the field with "ABC Mountain Bikes". If no record is found, only the entered data will be displayed.
This can be implemented in the 4GL in the following way:
By trapping the ANY-PRINTABLE event on the input area (usually a FILL-IN), and using the LAST-EVENT:LABEL, it is possible to trap what data has been entered so far. This can then be used in a FIND statement or a query to find a record which matches the input so far, which can then be displayed in the fill-in.
The main problem you will run into is that when assigning a screen value, Progress automatically truncates all trailing spaces of the character string. Thus, if the user enters a space it is lost when refreshing the fill-in by assigning a screen-value to it. The only way to do this is by programmatically "re-typing" the input so far with the APPLY statement and key-label events.
An example is included below, using:
- A trigger procedure for maximum code reusability.
- Text selection to both visualize and manage what the user has entered.
- The handle of a buffer or temp-table. This allows it to work with both static and dynamic objects.
Sample trigger: ON ANY-PRINTABLE OF fcCustName IN FRAME DEFAULT-FRAME /* Name */
DO:
DEFINE VARIABLE p AS HANDLE NO-UNDO.
p = BUFFER customer:HANDLE.
RUN autoComplete (p,"Name").
RETURN NO-APPLY.
END.Sample trigger procedure: PROCEDURE autoComplete :
DEFINE INPUT PARAMETER tableHandle AS HANDLE NO-UNDO.
DEFINE INPUT PARAMETER fieldName AS CHARACTER NO-UNDO.
DEFINE VARIABLE searchQuery AS HANDLE NO-UNDO.
DEFINE VARIABLE searchBuffer AS HANDLE NO-UNDO.
DEFINE VARIABLE searchField AS HANDLE NO-UNDO.
DEFINE VARIABLE cValue AS CHARACTER NO-UNDO.
DEFINE VARIABLE iCount AS INTEGER NO-UNDO.
IF tableHandle:TYPE = "TEMP-TABLE" THEN tableHandle = tableHandle:DEFAULT-BUFFER-HANDLE.
CREATE BUFFER searchBuffer FOR TABLE tableHandle.
searchField = searchBuffer:BUFFER-FIELD(fieldName).
CREATE QUERY searchQuery.
cValue = SELF:SELECTION-TEXT + LAST-EVENT:LABEL.
searchQuery:SET-BUFFERS(searchBuffer).
searchQuery:QUERY-PREPARE("FOR EACH " + tableHandle:NAME + " WHERE " +
tableHandle:NAME + "." + fieldName + " BEGINS '" + cValue + "'").
searchQuery:QUERY-OPEN.
searchQuery:GET-FIRST(NO-LOCK).
IF searchBuffer:AVAILABLE AND
LENGTH(STRING(searchField:BUFFER-VALUE)) >= LENGTH(cValue) THEN DO:
searchField = searchBuffer:BUFFER-FIELD(fieldName).
SELF:SCREEN-VALUE = searchField:STRING-VALUE.
END.
ELSE DO:
 .; SELF:SCREEN-VALUE = "".
DO iCount = 1 TO LENGTH(cValue):
APPLY SUBSTRING(cValue,iCount,1) TO SELF.
END.
END.
SELF:SET-SELECTION(1,LENGTH(cValue) + 1).
searchQuery:QUERY-CLOSE.
DELETE OBJECT searchQuery.
DELETE OBJECT searchBuffer.
END PROCEDURE..