por el autor invitado Chris Belanger, un desarrollador 4D de Canadá
El typeahead de las cajas de lista(un método para buscar progresivamente) no es una característica nativa de las cajas de lista. Sin embargo, usted puede implementar fácilmente esta característica con algo de codificación creativa. En esta entrada del blog, demostraré la técnica junto con un ejemplo de base de datos y un documento exhaustivo que explica los detalles paso a paso.
El resultado final se resume en el GIF siguiente, que ilustra dos «búsquedas». Una para E-L-L-I-O-T, y otra (tras una ordenación por columnas) para H-A-N-N-A-H:
¿Qué queremos hacer?
Cuando el cuadro de lista tiene el foco (pero no en «modo de entrada»), queremos poder escribir algunos caracteres y que el cuadro de lista se desplace y seleccione la coincidencia más cercana según la «columna de ordenación». Por ejemplo, si está ordenado por nombre de empresa, queremos empezar a escribir el nombre de una empresa y que se localice y resalte en el cuadro de lista. Sin embargo, cuando un cuadro de lista es el objeto enfocado, no puede responder a las pulsaciones de las teclas.
Entonces, ¿cómo podemos resolver este problema ya que no parece haber una forma de recoger las pulsaciones de las teclas?
Colocar el cuadro de lista en un subformulario
El primer paso es colocar el cuadro de lista en un subformulario (en la base de datos de ejemplo, este formulario se llama LB). Bien… ¿pero cómo recogemos las pulsaciones? Utilizando botones invisibles con «atajos» asignados.
A su vez, todos los atajos llaman a un método para determinar el texto de búsqueda, localizarlo en el cuadro de lista y resaltarlo para el usuario. Puede seguir esta explicación si abre el formulario LB de la base de datos Listbox Clairvoyance.
El cuadro de lista tiene el nombre de objeto, LB_Browser. Sus propiedades incluyen:
La selección de la entidad se llama Form.es (en el contexto del subformulario LB).
En la parte inferior del formulario LB , hay una colección de botones. Cada uno tiene asignada una tecla de acceso directo. La fila inferior puede parecer poco clara, pero manejan las teclas ESPACIO, – y _. Puedes añadir más si es necesario.
Las propiedades de cada uno de estos botones se ilustran utilizando la tecla «A» como ejemplo.
El nombre del objeto termina en la LETRA, NÚMERO o SÍMBOLO que genera. SPACE es una excepción; utiliza el símbolo ␣ y se «traduce» a SPACE.
El título es sólo para clarificar, el tamaño horizontal es Mover, y el atajo es la pulsación de la tecla. El único evento que debe ser comprobado es On Clicked.
Cuando un usuario presiona una tecla de acceso directo, el script para ese botón se dispara con un On Clicked Form event code.
El guión de cada botón es:
LB_SEARCH_DO (Form; OBJECT Get name)
Interpretación de la pulsación del botón
El método de proyecto LB_SEARCH_DO procesa las pulsaciones de teclas. Utiliza el carácter final del nombre del objeto para saber la pulsación de tecla que debe procesar.
$char:=$2[[Length($2)]]
// get the last character in the object’s name.
Este carácter se añadirá a la cadena de búsqueda o la sustituirá, dependiendo del tiempo transcurrido desde la última pulsación. En la base de datos de ejemplo, cualquier «espera» superior a 1,5 segundos iniciará una nueva búsqueda.
$now:=Milliseconds
If (($now-$obj_Search.lastMillisecond)>1500) //allow up to 1.50 seconds between keystrokes.
$obj_Search. searchFor :=$char //reset .searchFor
Else
$obj_Search.searchFor :=$obj_Search.searchFor +$char //add to .searchFor
End if
$obj_Search .lastMillisecond:=$now
La búsqueda en la «columna de búsqueda» se realiza determinando qué registro de la selección de entidades sería la primera coincidencia y, a continuación, localizando este registro en la selección de entidades («.es«).
C_OBJECT($es_GreaterEqual) // the entity selection of the >= group that match the searchFor string.
$es_GreaterEqual :=$1.es.query($attrName+" >= :1";$obj_Search.searchFor).orderBy($attrName+" ASC")
El $itemPosition dentro de la selección de entidades se determina con:
If ($es_GreaterEqual.length>0) // if there was at least one match
$match :=$es_GreaterEqual[0] // $match = the FIRST RECORD in the collection
$itemPosition :=$es_GreaterEqual[0].indexOf($1.es)+1 // location of the matching entity within the selection
Else
$itemPosition :=$1.es.length
End if
Ahora actualizamos la selección de filas del cuadro de lista y nos desplazamos para que el usuario pueda ver el resultado. Lo mostramos en la línea 5 del cuadro de lista para dar algo de contexto.
C_LONGINT($show) // used to cause the ITEM POSITION to show in the 5th line (or higher, if it is < 5).
LISTBOX SELECT ROW (*;$lbName;$itemPosition;lk replace selection)
$show :=Choose($itemPosition<4;1;$itemPosition-4) // it will be line 5, or closer to the top
OBJECT SET SCROLL POSITION (*;$lbName;$show;*)
Por último, para la demostración, cargamos la entidad seleccionada en un objeto al que pueda acceder el formulario padre.
Form.en_edit:=Form.es[$itemPosition-1]
// for the parent form’s use
Y más
Descargue el IDH anterior para ver más de cerca el concepto. Además, se incluye un documento exhaustivo que explica la configuración del formulario padre para operar el cuadro de lista, así como consejos para diseñar la interfaz de usuario y mejorar la experiencia del usuario.
¡Espero que esto le ayude en su próximo proyecto 4D!