LP#1916403 Staff catalog search form labels
authorStephanie Leary <stephanie.leary@equinoxOLI.org>
Mon, 5 Dec 2022 20:25:31 +0000 (14:25 -0600)
committerJane Sandberg <sandbergja@gmail.com>
Tue, 28 Feb 2023 15:08:18 +0000 (07:08 -0800)
Provides label tags for staff catalog search form fields.

Most labels in the form are visible. I have used the sr-only class to
make labels available to screen reader users while hiding them from
sight on the publication date range fields, which I think are easy
enough to use without visible labels. However, this combination of year
and operator dropdowns is not well organized for screen reader users,
and we should rethink the order and wording of these fields.

To test, visit staff/catalog/search and inspect each form field. Verify
that each one has a <label> tag where the for attribute matches the ID
of the associated form element. (Checkboxes wrapped in the <label> tag
still need matching ID and for attributes for consistent ARIA support.)

Signed-off-by: Stephanie Leary <stephanie.leary@equinoxOLI.org>
fix

Signed-off-by: Stephanie Leary <stephanie.leary@equinoxOLI.org>
Signed-off-by: Susan Morrison <smorrison@georgialibraries.org>
Signed-off-by: Jane Sandberg <sandbergja@gmail.com>
Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.css
Open-ILS/src/eg2/src/app/staff/catalog/search-form.component.html

index 4d2842e..5248bf1 100644 (file)
@@ -26,3 +26,10 @@ select.form-control:not([size]):not([multiple]) {
   margin-top: 25px;
   font-weight: bold;
 }
+
+.select-label,
+.input-label {
+  display: block;
+  font-size: 0.88rem;
+  margin-bottom: 0;
+}
\ No newline at end of file
index e75ef48..5969fc1 100644 (file)
@@ -39,7 +39,8 @@
             *ngFor="let q of context.termSearch.query; let idx = index; trackBy:trackByIdx">
             <div class="col-lg-2 pr-1">
               <div *ngIf="idx === 0">
-                <select class="form-control" [(ngModel)]="context.termSearch.format">
+                <label i18n class="select-label" for="context-termSearch-format">Format</label>
+                <select class="form-control" id="context-termSearch-format" [(ngModel)]="context.termSearch.format">
                   <option i18n value=''>All Formats</option>
                   <ng-container
                     *ngTemplateOutlet="ccvmOption;context:{list:ccvmMap.search_format}">
@@ -47,7 +48,8 @@
                 </select>
               </div>
               <div *ngIf="idx > 0">
-                <select class="form-control"
+                <label i18n class="select-label" for="context-termSearch-joinOp-{{idx}}">Join with</label>
+                <select class="form-control" id="context-termSearch-joinOp-{{idx}}"
                   [(ngModel)]="context.termSearch.joinOp[idx]">
                   <option i18n value='&&'>And</option>
                   <option i18n value='||'>Or</option>
@@ -55,7 +57,8 @@
               </div>
             </div>
             <div class="col-lg-2 pl-0 pr-2">
-              <select class="form-control" 
+              <label i18n class="select-label" for="context-termSearch-fieldClass-{{idx}}">Catalog Field</label>
+              <select class="form-control" id="context-termSearch-fieldClass-{{idx}}"
                 (change)="preventBogusCombos(idx)"
                 [(ngModel)]="context.termSearch.fieldClass[idx]">
                 <option i18n value='keyword'>Keyword</option>
@@ -69,7 +72,8 @@
               </select>
             </div>
             <div class="col-lg-2 pl-0 pr-2">
-              <select class="form-control" 
+              <label i18n class="select-label" for="context-termSearch-matchOp-{{idx}}">Matching</label>
+              <select class="form-control" id="context-termSearch-matchOp-{{idx}}"
                 [(ngModel)]="context.termSearch.matchOp[idx]">
                 <option i18n value='contains'>Contains</option>
                 <option i18n value='nocontains'>Does not contain</option>
@@ -83,6 +87,7 @@
             <div class="col-lg-4 pl-0 pr-2">
               <div class="form-group">
                 <div *ngIf="idx === 0">
+                  <label i18n class="input-label" for='first-query-input'>Search Terms</label>
                   <input type="text" class="form-control"
                     id='first-query-input'
                     [(ngModel)]="context.termSearch.query[idx]"
@@ -90,6 +95,7 @@
                     placeholder="Query..."/>
                 </div>
                 <div *ngIf="idx > 0">
+                  <label i18n class="input-label" for='context-termSearch-query-{{idx}}'>Search Terms</label>
                   <input type="text" class="form-control"
                     [(ngModel)]="context.termSearch.query[idx]"
                     (keyup.enter)="searchByForm()"
           </div>
           <div class="row">
             <div class="col-lg-12 form-inline">
-                <select class="form-control mr-2" [(ngModel)]="context.sort">
+              <div class="form-inline-group">
+                <label i18n class="select-label" for="context-sort">Sort Results</label>
+                <select class="form-control mr-2" id="context-sort" [(ngModel)]="context.sort">
                   <option value='' i18n>Sort by Relevance</option>
                   <optgroup label="Sort by Title" i18n-label>
                     <option value='titlesort' i18n>Title: A to Z</option>
                     <option value='poprel' i18n>Popularity Adjusted Relevance</option>
                   </optgroup>
                 </select>
+              </div>
                 <div class="checkbox pl-2 ml-2 pt-2">
-                  <label>
-                    <input type="checkbox" [(ngModel)]="context.termSearch.available"/>
+                  <label for="context-termSearch-available">
+                    <input type="checkbox" [(ngModel)]="context.termSearch.available" id="context-termSearch-available" />
                     <span class="pl-1" i18n>Limit to Available</span>
                   </label>
                 </div>
                 <div class="checkbox pl-3 pt-2">
-                  <label>
-                    <input type="checkbox"
+                  <label for="context-termSearch-groupByMetarecord">
+                    <input type="checkbox" id="context-termSearch-groupByMetarecord"
                       [(ngModel)]="context.termSearch.groupByMetarecord"/>
                     <span class="pl-1" i18n>Group Formats/Editions</span>
                   </label>
                 </div>
                 <div class="checkbox pl-3 pt-2">
-                  <label>
-                    <input type="checkbox" [(ngModel)]="context.global"/>
+                  <label for="context-global">
+                    <input type="checkbox" id="context-global" [(ngModel)]="context.global"/>
                     <span class="pl-1" i18n>Results from All Libraries</span>
                   </label>
                 </div>
                 <div class="checkbox pl-3 pt-2" *ngIf="showExcludeElectronic()">
-                  <label>
-                    <input type="checkbox" 
+                  <label for="context-termSearch-excludeElectronic">
+                    <input type="checkbox" id="context-termSearch-excludeElectronic"
                       [(ngModel)]="context.termSearch.excludeElectronic"/>
                     <span class="pl-1" i18n>Exclude Electronic Resources</span>
                   </label>
           </div>
           <div class="row" *ngIf="showFilters()">
             <div class="col-lg-3 mt-3" *ngIf="searchFilters().includes('item_type')">
-              <select class="form-control"  multiple="true"
+              <label i18n class="select-label" for="context-termSearch-ccvmFilters-item_type">Item Type</label>
+              <select class="form-control"  multiple="true" id="context-termSearch-ccvmFilters-item_type"
                 [(ngModel)]="context.termSearch.ccvmFilters.item_type">
                 <option value='' i18n>All Item Types</option>
                 <ng-container
               </select>
             </div>
             <div class="col-lg-3 mt-3" *ngIf="searchFilters().includes('item_form')">
-              <select class="form-control" multiple="true"
+              <label i18n class="select-label" for="context-termSearch-ccvmFilters-item_form">Form</label>
+              <select class="form-control" multiple="true" id="context-termSearch-ccvmFilters-item_form"
                 [(ngModel)]="context.termSearch.ccvmFilters.item_form">
                 <option value='' i18n>All Item Forms</option>
                 <ng-container
               </select>
             </div>
             <div class="col-lg-3 mt-3" *ngIf="searchFilters().includes('item_lang')">
-              <select class="form-control" 
+              <label i18n class="select-label" for="context-termSearch-ccvmFilters-item_lang">Language</label>
+              <select class="form-control" id="context-termSearch-ccvmFilters-item_lang"
                 [(ngModel)]="context.termSearch.ccvmFilters.item_lang" multiple="true">
                 <option value='' i18n>All Languages</option>
                 <ng-container
               </select>
             </div>
             <div class="col-lg-3 mt-3" *ngIf="searchFilters().includes('audience')">
-              <select class="form-control" 
+              <label i18n class="select-label" for="context-termSearch-ccvmFilters-audience">Audience</label>
+              <select class="form-control" id="context-termSearch-ccvmFilters-audience"
                 [(ngModel)]="context.termSearch.ccvmFilters.audience" multiple="true">
                 <option value='' i18n>All Audiences</option>
                 <ng-container
               </select>
             </div>
             <div class="col-lg-3 mt-3" *ngIf="searchFilters().includes('vr_format')">
-              <select class="form-control" 
+              <label i18n class="select-label" for="context-termSearch-ccvmFilters-vr_format">Video Format</label>
+              <select class="form-control" id="context-termSearch-ccvmFilters-vr_format"
                 [(ngModel)]="context.termSearch.ccvmFilters.vr_format" multiple="true">
                 <option value='' i18n>All Video Formats</option>
                 <ng-container
               </select>
             </div>
             <div class="col-lg-3 mt-3" *ngIf="searchFilters().includes('bib_level')">
-              <select class="form-control" 
+              <label i18n class="select-label" for="context-termSearch-ccvmFilters-bib_level">Bibliographic Level</label>
+              <select class="form-control" id="context-termSearch-ccvmFilters-bib_level"
                 [(ngModel)]="context.termSearch.ccvmFilters.bib_level" multiple="true">
                 <option value='' i18n>All Bib Levels</option>
                 <ng-container
               </select>
             </div>
             <div class="col-lg-3 mt-3" *ngIf="searchFilters().includes('lit_form')">
-              <select class="form-control" 
+              <label i18n class="select-label" for="context-termSearch-ccvmFilters-lit_form">Literary Form</label>
+              <select class="form-control" id="context-termSearch-ccvmFilters-lit_form"
                 [(ngModel)]="context.termSearch.ccvmFilters.lit_form" multiple="true">
                 <option value='' i18n>All Literary Forms</option>
                 <ng-container
               </select>
             </div>
             <div class="col-lg-3 mt-3">
-              <select class="form-control" 
+              <label i18n class="select-label" for="context-termSearch-copyLocations">Shelving Location</label>
+              <select class="form-control" id="context-termSearch-copyLocations"
                 [(ngModel)]="context.termSearch.copyLocations" multiple="true">
                 <option value='' i18n>All Shelving Locations</option>
                 <option *ngFor="let loc of copyLocations" value="{{loc.id()}}" i18n>
             <div class="col-lg-12">
               <div class="form-inline">
                 <label for="pub-date1-input" i18n>Publication Year is</label>
-                <select class="form-control ml-2" [(ngModel)]="context.termSearch.dateOp">
+                <label class="sr-only" for="pub-date-operator-select" i18n>compare publication dates using...</label>
+                <select id="pub-date-operator-select" class="form-control ml-2" [(ngModel)]="context.termSearch.dateOp">
                   <option value='is' i18n>Is</option>
                   <option value='before' i18n>Before</option>
                   <option value='after' i18n>After</option>
                   <option value='between' i18n>Between</option>
                 </select>
-                <input class="form-control ml-2" type="number"
+                <label i18n class="sr-only" for="context-termSearch-date1">Year, or beginning of year range</label>
+                <input class="form-control ml-2" type="number" id="context-termSearch-date1"
                   [(ngModel)]="context.termSearch.date1"/>
-                <input class="form-control ml-2" type="number"
+                <label i18n class="sr-only" for="context-termSearch-date2">End of year range</label>
+                  <input class="form-control ml-2" type="number"
                   *ngIf="context.termSearch.dateOp === 'between'"
                   [(ngModel)]="context.termSearch.date2"/>
               </div>