trap enter and escape keypresses when updating select menu

This commit is contained in:
Sarah Higley 2019-04-23 21:35:51 -07:00
Родитель c963711c9a
Коммит 7ba3da7869
17 изменённых файлов: 65 добавлений и 101 удалений

Просмотреть файл

@ -11,11 +11,10 @@
"dist/"
],
"scripts": {
"build": "stencil build --docs && npm run copy-assets",
"start": "stencil build --dev --watch --serve && npm run copy-assets",
"build": "stencil build --docs",
"start": "stencil build --dev --watch --serve",
"test": "stencil test --spec --e2e",
"test.watch": "stencil test --spec --e2e --watchAll",
"copy-assets": "cp -r src/assets/ www/ && cp src/style.css www/ && cp src/*.html www/"
"test.watch": "stencil test --spec --e2e --watchAll"
},
"dependencies": {},
"devDependencies": {

Просмотреть файл

@ -170,6 +170,7 @@ export class ComboAutocomplete {
case MenuActions.CloseSelect:
this.selectOption(this.activeIndex);
case MenuActions.Close:
event.preventDefault();
return this.updateMenuState(false);
case MenuActions.Open:
return this.updateMenuState(true);

Просмотреть файл

@ -159,9 +159,11 @@ export class ComboAutoselect {
event.preventDefault();
return this.onOptionChange(getUpdatedIndex(this.activeIndex, max, action));
case MenuActions.CloseSelect:
event.preventDefault();
this.selectOption(this.activeIndex);
return this.updateMenuState(false);
case MenuActions.Close:
event.preventDefault();
this.activeIndex = 0;
this.value = this.selectedValue;
this.filteredOptions = this.options;

Просмотреть файл

@ -156,6 +156,7 @@ export class ComboFilter {
case MenuActions.CloseSelect:
this.selectOption(this.activeIndex);
case MenuActions.Close:
event.preventDefault();
return this.updateMenuState(false);
case MenuActions.Open:
return this.updateMenuState(true);

Просмотреть файл

@ -55,14 +55,16 @@ export class ComboNative {
return ([
<label htmlFor={htmlId} class="combo-label">{label}</label>,
<select
id={htmlId}
class="combo combo-input"
required={required ? true: null }
onChange={(event: Event) => this.selectHandler((event.target as HTMLSelectElement).value)}
>
{options.map((option) => <option value={option.value}>{option.name}</option>)}
</select>
<div class="combo">
<select
id={htmlId}
class="combo-input"
required={required ? true: null }
onChange={(event: Event) => this.selectHandler((event.target as HTMLSelectElement).value)}
>
{options.map((option) => <option value={option.value}>{option.name}</option>)}
</select>
</div>
]);
}
}

Просмотреть файл

@ -143,6 +143,7 @@ export class ComboNoFilter {
case MenuActions.CloseSelect:
this.selectOption(this.activeIndex);
case MenuActions.Close:
event.preventDefault();
return this.updateMenuState(false);
case MenuActions.Open:
return this.updateMenuState(true);

Просмотреть файл

@ -116,6 +116,7 @@ export class ComboNoInput {
case MenuActions.CloseSelect:
this.selectOption(this.activeIndex);
case MenuActions.Close:
event.preventDefault();
return this.updateMenuState(false);
case MenuActions.Type:
this.activeIndex = Math.max(0, getIndexByLetter(this.options, key));

Просмотреть файл

@ -128,6 +128,7 @@ export class ComboReadonly {
case MenuActions.CloseSelect:
this.selectOption(this.activeIndex);
case MenuActions.Close:
event.preventDefault();
return this.updateMenuState(false);
case MenuActions.Type:
this.activeIndex = Math.max(0, getIndexByLetter(this.options, key));

Просмотреть файл

@ -164,6 +164,7 @@ export class ListboxButton {
case MenuActions.CloseSelect:
this.selectOption(this.activeIndex);
case MenuActions.Close:
event.preventDefault();
return this.updateMenuState(false);
case MenuActions.Type:
this.activeIndex = Math.max(0, getIndexByLetter(this.options, key));

Просмотреть файл

@ -180,8 +180,10 @@ export class MultiselectButtons {
event.preventDefault();
return this.onOptionChange(getUpdatedIndex(this.activeIndex, max, action));
case MenuActions.CloseSelect:
event.preventDefault();
return this.updateOption(this.activeIndex);
case MenuActions.Close:
event.preventDefault();
return this.updateMenuState(false);
case MenuActions.Open:
return this.updateMenuState(true);

Просмотреть файл

@ -167,8 +167,10 @@ export class MultiselectCSV {
event.preventDefault();
return this.onOptionChange(getUpdatedIndex(this.activeIndex, max, action));
case MenuActions.CloseSelect:
event.preventDefault();
return this.updateOption(this.activeIndex);
case MenuActions.Close:
event.preventDefault();
return this.updateMenuState(false);
case MenuActions.Open:
return this.updateMenuState(true);

Просмотреть файл

@ -186,8 +186,10 @@ export class MultiselectInline {
event.preventDefault();
return this.onOptionChange(getUpdatedIndex(this.activeIndex, max, action));
case MenuActions.CloseSelect:
event.preventDefault();
return this.updateOption(this.activeIndex);
case MenuActions.Close:
event.preventDefault();
return this.updateMenuState(false);
case MenuActions.Open:
return this.updateMenuState(true);

Просмотреть файл

@ -1,36 +0,0 @@
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0">
<title>Order Pizza</title>
<link rel="stylesheet" href="/style.css"></style>
<script src="/build/caiacc.js"></script>
</head>
<body>
<div class="example-form">
<h1 id="page-title">Find a Pizza Store</h1>
<form aria-labelledby="page-title" novalidate>
<combo-nofilter label="State" class="state-select"></combo-nofilter>
<combo-readonly label="Store" class="store-select"></combo-readonly>
</form>
</div>
<script type="module">
import { states } from './assets/stateData.js';
const stateCombo = document.querySelector('.state-select');
stateCombo.options = states;
const storeCombo = document.querySelector('.store-select');
storeCombo.options = [{ name: 'Amherst', value: 'amherst'}, { name: 'Hadley', value: 'hadley'}, { name: 'Northampton', value: 'northampton'}, { name: 'Greenfield', value: 'greenfield'}];
const multiCombo = document.querySelector('.multi-select');
multiCombo.options = countries;
</script>
</body>
</html>

Просмотреть файл

@ -22,8 +22,8 @@ body {
}
.combo::after {
border-bottom: 1px solid rgba(0,0,0,.42);
border-right: 1px solid rgba(0,0,0,.42);
border-bottom: 2px solid rgba(0,0,0,.5);
border-right: 2px solid rgba(0,0,0,.5);
content: '';
display: block;
height: 12px;
@ -37,7 +37,7 @@ body {
.combo-input {
background-color: #f5f5f5;
border: 1px solid rgba(0,0,0,.42);
border: 2px solid rgba(0,0,0,.5);
border-radius: 4px;
display: block;
min-height: calc(1.4em + 26px);
@ -46,6 +46,12 @@ body {
width: 100%;
}
select.combo-input {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.open .combo-input {
border-radius: 4px 4px 0 0;
}

Просмотреть файл

@ -8,6 +8,7 @@
}
body {
background-color: #f5f5f5;
font-family: "Segoe UI", SegoeUI, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
line-height: 1.4em;
@ -16,7 +17,8 @@ body {
}
.example-form {
border: 1px solid #ccc;
background-color: #fff;
border: 1px solid rgba(0,0,0,.5);
border-radius: 5px;
max-width: 460px;
margin: 100px auto;
@ -26,17 +28,30 @@ body {
.example-form h1 {
font-size: 2rem;
line-height: 1.1;
margin: 0 0 1em;
}
input[type=text] {
background-color: #f5f5f5;
border: 1px solid rgba(0,0,0,.42);
.example-form label {
font-weight: bold;
margin-top: 1em;
}
.example-form button[type=submit] {
background-color: #0067b8;
border: 1px solid #fff;
border-radius: 4px;
display: block;
min-height: calc(1.4em + 26px);
padding: 12px 16px 14px;
text-align: left;
width: 100%;
color: #fff;
display: inline-block;
font-size: 1.1rem;
font-weight: bold;
margin-top: 1.5em;
padding: 0.5em 0.75em;
text-transform: uppercase;
}
.example-form button[type=submit]:focus {
box-shadow: 0 0 6px 2px #0067b8;
outline: 4px solid transparent;
}
.form-input {

Просмотреть файл

@ -1,41 +0,0 @@
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0">
<title>Travel profile form</title>
<link rel="stylesheet" href="/style.css"></style>
<script src="/build/caiacc.js"></script>
</head>
<body>
<div class="example-form">
<h1 id="page-title">Create your travel profile</h1>
<form aria-labelledby="page-title" novalidate>
<label for="name">Name (required)</label>
<input type="text" class="form-input" id="name" required>
<combo-native label="Gender (required)" required="true" class="gender-select form-input"></combo-native>
<combo-filter label="Current country of residence" class="country-select form-input"></combo-filter>
<multiselect-csv label="I want to visit (choose all countries that apply):" class="multi-select form-input"></multiselect-csv>
</form>
</div>
<script type="module">
import { states } from './assets/stateData.js';
import { countries } from './assets/countryData.js';
const genderCombo = document.querySelector('.gender-select');
genderCombo.options = [{ name: 'Female', value: 'f' }, { name: 'Male', value: 'm' }, { name: 'Other', value: 'o' }, { name: 'Prefer not to say', value: 'na' }];
const countryCombo = document.querySelector('.country-select');
countryCombo.options = countries;
const multiCombo = document.querySelector('.multi-select');
multiCombo.options = countries;
</script>
</body>
</html>

Просмотреть файл

@ -9,5 +9,10 @@ export const config: Config = {
type: 'www',
serviceWorker: null // disable service workers
}
],
copy: [
{ src: 'assets' },
{ src: 'studies' },
{ src: 'style.css' }
]
};