1 - Datalist JSON suggestion - Research and finding - Web Experience Toolkit (WET) documentation

Purpose

Customizable autocomplete feature.

Requirements

Early prototype

UX feedback from early prototype

Others

Remarks

Terminology issue: There is a confusion about the right terminology to properly name this features. Some call it auto-complete, other call it datalist and other call it combobox.

Here the definition we will now use forward. It’s based on how it is descrbied in W3C ARIA specification.

All this research documents, as May 28 - 2018, is about the “combobox functionality”, the initial version only support listbox and don’t support autocomplete feature.

Similar tools

Here a list of similar tools that was found on a February 2018 research

Similar tools added on August 6th 2018

Similar tools added on December 2nd 2020

Website using custom datalist

Feature request description

last review: April 6, 2018

Feature that might worth to considerate

Resources

Quote from spec

To be keyboard accessible, authors SHOULD manage focus of descendants for all instances of this role, as described in Managing Focus.

Source: listbox (role) - WAI ARIA 1.1

the interaction model conveyed by the listbox role to assistive technologies does not support interacting with elements inside of an option. Because of these traits of the listbox widget, it does not provide an accessible way to present a list of interactive elements, such as links, buttons, or checkboxes. To present a list of interactive elements, see the grid pattern.

Source: Listbox - WAI ARIA practices

A composite widget containing a single-line textbox and another element, such as a listbox or grid, that can dynamically pop up to help the user set the value of the textbox.

Source: combobox (role) - WAI ARIA 1.1

For instance, a combobox where the value of aria-autocomplete would be none is a search field that displays suggested values by listing the 5 most recently used search terms without any filtering of the list based on the user’s input.

Source: aria-autocomplete (property) - WAI ARIA 1.1

User Road Map / User story for Autofill

From: Ivan Hughes as April 16, 2018

Test case

Wireframe

Visual

Wireframe - visual representation of the User interface

Behaviour

Conditional submission:

Code sample

Take a look also at the working example from the WAI ARIA practices cite in the resources which have clue on how the enhanced user interface should be coded.

Simple datalist

<input list="datalist-id" />

<datalist id="datalist-id">
	<option>Lorem ipsum</option>
	<option>dolor sit amet</option>
	<option>consectetur</option>
	<option>adipiscing elit</option>
</datalist>

With a minimalist template, like the suggestion is loaded from a JSON files

<input list="datalist-id" />

<datalist id="datalist-id">
	<template>
		<option></option>
	</template>
</datalist>

A highly customized template where that content can’nt be holded by the datalist element. That kind of content would need to be in a overlay.

<input list="datalist-id" />

<datalist id="datalist-id">
	<template>
		<div class="row">
			<div class="col-xs-1">
				<p>:-)</p>
			</div>
			<div class="col-xs-11">
				<p></p>
			</div>
		</div>
	</template>
</datalist>

A highly customized template with fallback on standard datalist implementation

<input list="datalist-id" />

<datalist id="datalist-id">
	<template>
		<div class="row">
			<div class="col-xs-1">
				<p>:-)</p>
			</div>
			<div class="col-xs-11">
				<p></p>
			</div>
		</div>
	</template>
	<option>Lorem ipsum</option>
	<option>dolor sit amet</option>
	<option>consectetur</option>
	<option>adipiscing elit</option>
</datalist>

Fieldflow plain working example

<div class="wb-fieldflow">
	<p>Please something, something....</p>
	<ul>
		<li><a href="redirect/page-1.html">Lorem ipsum</a></li>
		<li><a href="redirect/page-2.html">dolor sit amet</a></li>
		<li><a href="redirect/page-3.html">consectetur</a></li>
		<li><a href="redirect/page-4.html">adipiscing elit</a></li>
	</ul>
</div>

Fieldflow with datalist working example

<div class="wb-fieldflow" data-wb-fieldflow='{"renderas":"datalist"}'>
	<p>Please something, something....</p>
	<ul>
		<li><a href="redirect/page-1.html">Lorem ipsum</a></li>
		<li><a href="redirect/page-2.html">dolor sit amet</a></li>
		<li><a href="redirect/page-3.html">consectetur</a></li>
		<li><a href="redirect/page-4.html">adipiscing elit</a></li>
	</ul>
</div>
<label for="myid">Label</label>
<select id="myid" data-wb5-enhance="autofill@autofillTemplateID">
	<option value="L">Lorem ipsum</option>
	<option value="D">dolor sit amet</option>
	<option value="C">consectetur</option>
	<option value="A">adipiscing elit</option>
</select>
<template id="autofillTemplateID">
	<div class="row" data-wb5-for="(option, index) in select.children()">
		<div class="col-xs-1">
			<p>:-)</p>
		</div>
		<div class="col-xs-11">
			<p><button data-wb5-on="click@selectOption(index)"></button></p>
		</div>
	</div>
	<button data-wb5-on="click@selectOption( select.children().length - 1 )">Default option</button>
</template>

Review of existing tools

jQuery accessible autocomplete list (with some ARIA)

Working example: jQuery accessible autocomplete list (with some ARIA) Source code: Github.com/nico3333fr/jquery-acc […] autocomplete-list-aria.js

mfranzke - datalist-polyfill

Working example: JSFiddle Source code: Github.com/mfranzke/datalist-polyfill

Accessible autocomplete

Working example: Accessible autocomplete Source code:

selectWoo and Select2

Working example:

Source code:

Chosen

Working example: Chosen is a library for making long, unwieldy select boxes more friendly. Source code: Github.com/harvesthq/chosen

React autosuggest

Working example: Reach autosuggest Source code: github.com/moroshko/react-autosuggest

Datalist JSON suggestion

Working example: Datalist JSON suggestion Source code: github.com/wet-boew/GCWeb

List of modules

Behaviour

Design pattern - Single selection

Basic HTML interface

Free input

<input list="datalist_id">
<datalist id="datalist_id">
	<option>Lorem</option>
	<option>ipsum</option>
	<option>dolor</option>
	<option>sit</option>
</datalist>
<div class="wb-fieldflow" data-wb-fieldflow='{"renderas":"combobox", "fallback": { [action object] } }'>
	<p>Please something, something....</p>
	<ul>
		<li><a href="redirect/page-1.html">Lorem ipsum</a></li>
		<li><a href="redirect/page-2.html">dolor sit amet</a></li>
		<li><a href="redirect/page-3.html">consectetur</a></li>
		<li><a href="redirect/page-4.html">adipiscing elit</a></li>
	</ul>
</div>

Predefined list

<select>
	<option>Lorem</option>
	<option>ipsum</option>
	<option>dolor</option>
	<option>sit</option>
</select>
<div class="wb-fieldflow" data-wb-fieldflow='{"renderas":"combobox"}'>
	<p>Please something, something....</p>
	<ul>
		<li><a href="redirect/page-1.html">Lorem ipsum</a></li>
		<li><a href="redirect/page-2.html">dolor sit amet</a></li>
		<li><a href="redirect/page-3.html">consectetur</a></li>
		<li><a href="redirect/page-4.html">adipiscing elit</a></li>
	</ul>
</div>

Enhanced interface

The interface as the same for Predefined option and Free input. The difference is the “predefined option” will log a custom error message if the input don’t match one items in list of suggested items.

<div role="combobox" aria-expanded="true" aria-owns="datalist_id" aria-haspopup="listbox">
    <input aria-autocomplete="list" aria-controls="datalist_id" aria-activedescendant="wb_auto_1">
</div>
<ul id="datalist_id" role="listbox">
    <li id="wb_auto_1" role="option">Lorem</li>
    <li id="wb_auto_2" role="option">ipsum</li>
    <li id="wb_auto_3" role="option">dolor</li>
    <li id="wb_auto_4" role="option">sit</li>
</ul>
{ hidden }
	<div class="wb-fieldflow" data-wb-fieldflow='{"renderas":"combobox", "fallback": { [action object] } }'>
		<p>Please something, something....</p>
		<ul>
			<li id="wb_auto_7"><a href="redirect/page-1.html">Lorem ipsum</a></li>
			<li id="wb_auto_8"><a href="redirect/page-2.html">dolor sit amet</a></li>
			<li id="wb_auto_9"><a href="redirect/page-3.html">consectetur</a></li>
			<li id="wb_auto_10"><a href="redirect/page-4.html">adipiscing elit</a></li>
		</ul>
	</div>
{/ hidden }

<div role="combobox" aria-expanded="true" aria-owns="wb_auto_6" aria-haspopup="listbox">
	<label for="wb_auto_5">Please something, something.... </label>
    <input id="wb_auto_5" aria-autocomplete="list" aria-controls="wb_auto_6" aria-activedescendant="wb_auto_1">
</div>
<ul id="wb_auto_6" role="listbox">
    <li role="option" data-wb-fieldflow='{"bind":"wb_auto_7","actions":[{"action":"redir","url":"redirect/page-1.html"}]}'>Lorem ipsum</li>
    <li role="option" data-wb-fieldflow='{"bind":"wb_auto_8","actions":[{"action":"redir","url":"redirect/page-2.html"}]}'>dolor sit amet</li>
    <li role="option" data-wb-fieldflow='{"bind":"wb_auto_9","actions":[{"action":"redir","url":"redirect/page-3.html"}]}'>consectetur</li>
    <li role="option" data-wb-fieldflow='{"bind":"wb_auto_10","actions":[{"action":"redir","url":"redirect/page-4.html"}]}'>adipiscing elit</li>
</ul>

Design pattern - Single selection with customized layout

Predefined list

This example kept simple list items, but the intention is to display inside a custom interface with a fallback.

The template will be created in a new <div role="grid">

The next example re-use the option as the data provider. The “value” are the filterable content

<select data-wb5-enhance="combobox">
	<template>
		<ul role="row">
			<li role="gridcell" data-wb5-for="option in select.options()" data-wb5-on="click@$emit('select', option.value )"></li>
		</ul>
		<div role="row">
			<div role="gridcell">
				<button data-wb5-on="click@$emit('select', 'sit')">Default persistent option</button>
			</div>
		</div>
	</template>
	<option value="Lorem">Lorem</option>
	<option value="ipsum">ipsum</option>
	<option value="dolor">dolor</option>
	<option value="sit">sit</option>
</select>

Free input

<input list="datalist_id" data-wb5-enhance="combobox">
<datalist id="datalist_id">
	<template>
		<ul role="row">
			<li role="gridcell" data-wb5-for="option in datalist.options()" data-wb5-on="click@$emit('select', option.value )"></li>
		</ul>
		<div role="row">
			<div role="gridcell">
				<button data-wb5-on="click@$emit('select', input.value)"></button>
			</div>
		</div>
	</template>
	<option>Lorem</option>
	<option>ipsum</option>
	<option>dolor</option>
	<option>sit</option>
</datalist>

(incomplete) predefined list with custom layout of items

<select data-wb5-enhance="combobox" data-wb5-provider="html@mySuggestionList" data-wb5-config='{"prvdr": { "image": "CSS Selector",...}  }'>
	<template>
		<div class="row" data-wb5-for="(option, index) in select.options()">
			<div class="col-xs-1">
				<p>:-)</p>
			</div>
			<div class="col-xs-11">
				<p><button data-wb5-on="click@selectOption(index)"></button></p>
			</div>
		</div>
		<button data-wb5-on="click@selectOption( select.children().length - 1 )">Default option</button>
	</template>
	<option>Lorem</option>
	<option>ipsum</option>
	<option>dolor</option>
	<option>sit</option>
</select>

{ hidden }
	<div class="hidden" id="mySuggestionList">
		<div data-wb5-slot="value">Item 1</div>
	</div>
{/ hidden }

Tasklist

Fieldflow

Early prototype requirement

Code sample and expected results

Scenario: The user need to select one option. In order to select an option, the user can filter the suggested list, there is a persistant available option regardless the filter. A second phase will to limit the number of display of result with pagination.

Template requirement: As the display is not a linear list, the template must implement the grid.

before initialization (Basic)

Author code:

<label for="id_select">Please choose an option</label>
<select id="id_select" data-wb5-enhance="combobox@listbox" name="selLoremIpsum">
	<template>
		<ul>
			<li role="option" data-wb5-for="option in select.options()" data-wb5-on="click@$emit('select', option.value )"></li>
		</ul>
		<hr class="brdr-bttm">
		<p role="option" data-wb5-on="click@$emit('select', 'sit')">Default persistent option</p>
	</template>
	<option value="Lorem">Lorem</option>
	<option value="ipsum">ipsum</option>
	<option value="dolor">dolor</option>
	<option value="sit">sit</option>
</select>

on initialization (Enhanced)

The enhanced code, on initialization, will look like:

<label for="id_select">Please choose an option</label>
<div role="combobox" aria-expanded="false" aria-haspopup="listbox" aria-owns="wb_auto_1">
    <input id="id_select" aria-autocomplete="list" aria-controls="wb_auto_1" name="selLoremIpsum" aria-activedescendant="" />
</div>
<div id="wb_auto_1" role="listbox">
</div>

Note:

on focus (Enhanced)

The enhanced code, on focus, will look like:

<label for="id_select">Please choose an option</label>
<div role="combobox" aria-expanded="true" aria-haspopup="listbox" aria-owns="wb_auto_1">
    <input id="id_select" aria-autocomplete="list" aria-controls="wb_auto_1" name="selLoremIpsum" aria-activedescendant="" />
</div>
<div id="wb_auto_1" role="listbox" class="overlay">
	<ul>
		<li id="wb_auto_2" role="option" data-wb5-on="click@$emit('select', 'Lorem' )">Lorem</li>
		<li id="wb_auto_3" role="option" data-wb5-on="click@$emit('select', 'ipsum' )">ipsum</li>
		<li id="wb_auto_4" role="option" data-wb5-on="click@$emit('select', 'dolor' )">dolor</li>
		<li id="wb_auto_5" role="option" data-wb5-on="click@$emit('select', 'sit' )">sit</li>
	</ul>
	<hr class="brdr-bttm">
	<p id="wb_auto_6" role="option" data-wb5-on="click@$emit('select', 'sit')">Default persistent option</p>
</div>

on selecting an item (Enhanced)

The item “ipsum” is currently focused.

<label for="id_select">Please choose an option</label>
<div role="combobox" aria-expanded="true" aria-haspopup="listbox" aria-owns="wb_auto_1">
    <input id="id_select" aria-autocomplete="list" aria-controls="wb_auto_1" name="selLoremIpsum" aria-activedescendant="wb_auto_3" />
</div>
<div id="wb_auto_1" role="listbox" class="overlay">
	<ul>
		<li id="wb_auto_2" role="option" data-wb5-on="click@$emit('select', 'Lorem' )">Lorem</li>
		<li aria-selected="true" id="wb_auto_3" role="option" data-wb5-on="click@$emit('select', 'ipsum' )">ipsum</li>
		<li id="wb_auto_4" role="option" data-wb5-on="click@$emit('select', 'dolor' )">dolor</li>
		<li id="wb_auto_5" role="option" data-wb5-on="click@$emit('select', 'sit' )">sit</li>
	</ul>
	<hr class="brdr-bttm">
	<p id="wb_auto_6" role="option" data-wb5-on="click@$emit('select', 'sit')">Default persistent option</p>
</div>

Only the item with the role option will be selectable, as that is the design pattern for listbox. If other element need to be selectable then it should be rendered as a grid.

after selecting an item (Enhanced)

The item “dolor” is selected by the user.

<label for="id_select">Please choose an option</label>
<div role="combobox" aria-expanded="true" aria-haspopup="listbox" aria-owns="wb_auto_1">
    <input id="id_select" aria-autocomplete="list" aria-controls="wb_auto_1" name="selLoremIpsum" aria-activedescendant="" value="dolor" />
</div>
<div id="wb_auto_1" role="listbox" class="overlay">
	<ul>
		<li id="wb_auto_2" role="option" data-wb5-on="click@$emit('select', 'Lorem' )">Lorem</li>
		<li id="wb_auto_3" role="option" data-wb5-on="click@$emit('select', 'ipsum' )">ipsum</li>
		<li id="wb_auto_4" role="option" data-wb5-on="click@$emit('select', 'dolor' )">dolor</li>
		<li id="wb_auto_5" role="option" data-wb5-on="click@$emit('select', 'sit' )">sit</li>
	</ul>
	<hr class="brdr-bttm">
	<p id="wb_auto_6" role="option" data-wb5-on="click@$emit('select', 'sit')">Default persistent option</p>
</div>

on focus out (Enhanced)

The focus is move to the next element, the grid overlay are hidden and the user has selected the option “dolor” before focusing out.

<label for="id_select">Please choose an option</label>
<div role="combobox" aria-expanded="true" aria-haspopup="listbox" aria-owns="wb_auto_1">
    <input id="id_select" aria-autocomplete="list" aria-controls="wb_auto_1" name="selLoremIpsum" aria-activedescendant="" value="dolor" />
</div>
<div id="wb_auto_1" role="listbox" class="hidden">
	<ul>
		<li id="wb_auto_2" role="option" data-wb5-on="click@$emit('select', 'Lorem' )">Lorem</li>
		<li id="wb_auto_3" role="option" data-wb5-on="click@$emit('select', 'ipsum' )">ipsum</li>
		<li id="wb_auto_4" role="option" data-wb5-on="click@$emit('select', 'dolor' )">dolor</li>
		<li id="wb_auto_5" role="option" data-wb5-on="click@$emit('select', 'sit' )">sit</li>
	</ul>
	<hr class="brdr-bttm">
	<p id="wb_auto_6" role="option" data-wb5-on="click@$emit('select', 'sit')">Default persistent option</p>
</div>

on resize when open (Enhanced)

? Close the overlay or recalculate the possition of the overlay.

on validation error (Enhanced)

This may require the form validation plugin in order to display the error message. However, on error, this plugin would set the custom error message to the input text field.

Developper note during the creation of the early prototype

2018-04-18

General notes

Integration with WET validation plugin

Templating

Async loading

Datalist

Integration with fieldflow

UX feedback from early prototype

From early prototype 1 to 5

Date: April 18, 2018 UX research lead: Ivan Hughes Tester: With less than five coworker Prototype tested: Select transformed into a comboxbox along with the WET validation plugin. Number of display result are limited to 7 and there is a possibility of 200. Commented by the developer: April 18, 2018

Tested with group one

Other than that, the overall was fine.

Testing with group two

The CSS that was added and not inlcuded into prototype 1 to 5

[role=combobox]:after {
	content: "\25BC\a0";
}

2018-04-20 - Status update

Todo:

See the code in 2018-1-combobox-prototype-WIP.html

2018-06-06 - Status update

Notes on experimental structure of the Javascript Object for the combo box

Working documents on how the information structure that are templated to generate the combobox should be ideally structured

Plugin core structure

* input
* listbox
	- option

// Events for core structure are directly monitored in the code to allow bi-directional binding

// Note: During "for" iteraction, number of true items is cumulated under the "active" properties of the object being iterated

------------

Combobox default template - Enhanced



--------------

Combobox JSON instance structure

Baseline plugin
{
	settings: {}, // Settings defined on the instance
	elm: {} // main DOM element
}

Special reactive attribute on Array
{
	wbLen: Lenght of the array before it get iterated
	wbActive: Number of array item that passed the "if" condition
}

Combobox
{
	popupId: wb.getId(), // ID for the listbox
	fieldId: false, // ID for the input
	fieldName: "", // Name for the input (if undefined, no attribute)
	filter: "", // Two-way binding with the input value. The filter is the current selected value
	options: [], // Array of available option
	config: settings,
	i18n: {},
	horay: "testMe",
	select: function(v) {
		this.selectValue = v;
	},
	nbdispItem: function(x) {
		this.cntdisplayeditem = x;
	}
}