4

Front end CiviCRM (5.21 and older) forms have drop down select list labels which are not accessible. When using a screenreader such as jaws, the reader reads the selected value of the control instead of the label.

This is counter to the way that the rest of the input controls work. The value should be read when clicking the control. Tabbing to it should read the label.

WARNING: latest version of select2 (4.0.2) breaks admin toolbar. Patch the one included with CiviCRM

5

Solution is to either patch the ../web/libraries/civicrm/bower_components/select2/select2.js and select2.min.js files

or

WARNING: select2 4.0.12 is not compatible with CiviCRM 5.21. The admin toolbar will disappear if you do the following. Use the patches. Do not bower install select2! ;-):

Move the select2 folder out of bower_components and run:

$ bower install select2

to get latest version of select2 (4.0.12 as of this writing) , which is accessible. I've not fully tested the latest version of select2, but it seems to be behaving on our stage server.

Patching existing select2 is the only option until regression testing is done by the CiviCRM folks, unless you want to patch latest version of select2 to fix toolbar issue.

Do this!: patches (if you want to keep current version of select2)...

select2.js.patch:

--- select2.js.original 2020-01-24 13:55:52.164674038 +0000
+++ select2.js  2020-01-24 13:56:20.955011734 +0000
@@ -2269,7 +2269,7 @@

             // add aria associations
             selection.find(".select2-chosen").attr("id", "select2-chosen-"+idSuffix);
-            this.focusser.attr("aria-labelledby", "select2-chosen-"+idSuffix);
+            this.focusser.attr("aria-labelledby", "s2id_autogen"+idSuffix);
             this.results.attr("id", "select2-results-"+idSuffix);
             this.search.attr("aria-owns", "select2-results-"+idSuffix);

select2.min.js.patch:

--- select2.min.js.original 2020-01-24 13:53:46.859556059 +0000
+++ select2.min.js  2020-01-24 13:54:48.440139669 +0000
@@ -124,7 +124,7 @@
         null!==s&&this.container.css("width",s)}}),A=k(R,{createContainer:function(){var t=e(document.createElement("div")).attr({"class":"select2-container"}).html("<a href='javascript:void(0)' class='select2-choice' tabindex='-1'>   <span class='select2-chosen'>&#160;</span><abbr class='select2-search-choice-close'></abbr>   <span class='select2-arrow' role='presentation'><b role='presentation'></b></span></a><label for='' class='select2-offscreen'></label><input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' /><div class='select2-drop select2-display-none'>   <div class='select2-search'>       <label for='' class='select2-offscreen'></label>       <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'       aria-autocomplete='list' />   </div>   <ul class='select2-results' role='listbox'>   </ul></div>")
         return t},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.focusser.prop("disabled",!this.isInterfaceEnabled())},opening:function(){var t,s,i
         this.opts.minimumResultsForSearch>=0&&this.showSearch(!0),this.parent.opening.apply(this,arguments),this.showSearchInput!==!1&&this.search.val(this.focusser.val()),this.opts.shouldFocusInput(this)&&(this.search.focus(),t=this.search.get(0),t.createTextRange?(s=t.createTextRange(),s.collapse(!1),s.select()):t.setSelectionRange&&(i=this.search.val().length,t.setSelectionRange(i,i))),this.prefillNextSearchTerm(),this.focusser.prop("disabled",!0).val(""),this.updateResults(!0),this.opts.element.trigger(e.Event("select2-open"))},close:function(){this.opened()&&(this.parent.close.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},focus:function(){this.opened()?this.close():(this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},isFocused:function(){return this.container.hasClass("select2-container-active")},cancel:function(){this.parent.cancel.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus()},destroy:function(){e("label[for='"+this.focusser.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments),P.call(this,"selection","focusser")},initContainer:function(){var i,n,o=this.container,a=this.dropdown,r=L()
-        this.opts.minimumResultsForSearch<0?this.showSearch(!1):this.showSearch(!0),this.selection=i=o.find(".select2-choice"),this.focusser=o.find(".select2-focusser"),i.find(".select2-chosen").attr("id","select2-chosen-"+r),this.focusser.attr("aria-labelledby","select2-chosen-"+r),this.results.attr("id","select2-results-"+r),this.search.attr("aria-owns","select2-results-"+r),this.focusser.attr("id","s2id_autogen"+r),n=e("label[for='"+this.opts.element.attr("id")+"']"),this.opts.element.on("focus.select2",this.bind(function(){this.focus()})),this.focusser.prev().text(n.text()).attr("for",this.focusser.attr("id"))
+        this.opts.minimumResultsForSearch<0?this.showSearch(!1):this.showSearch(!0),this.selection=i=o.find(".select2-choice"),this.focusser=o.find(".select2-focusser"),i.find(".select2-chosen").attr("id","select2-chosen-"+r),this.focusser.attr("aria-labelledby","s2id_autogen"+r),this.results.attr("id","select2-results-"+r),this.search.attr("aria-owns","select2-results-"+r),this.focusser.attr("id","s2id_autogen"+r),n=e("label[for='"+this.opts.element.attr("id")+"']"),this.opts.element.on("focus.select2",this.bind(function(){this.focus()})),this.focusser.prev().text(n.text()).attr("for",this.focusser.attr("id"))
         var l=this.opts.element.attr("title")
         this.opts.element.attr("title",l||n.text()),this.focusser.attr("tabindex",this.elementTabIndex),this.search.attr("id",this.focusser.attr("id")+"_search"),this.search.prev().text(e("label[for='"+this.focusser.attr("id")+"']").text()).attr("for",this.search.attr("id")),this.search.on("keydown",this.bind(function(e){if(this.isInterfaceEnabled()&&229!=e.keyCode){if(e.which===U.PAGE_UP||e.which===U.PAGE_DOWN)return g(e),t
             switch(e.which){case U.UP:case U.DOWN:return this.moveHighlight(e.which===U.UP?-1:1),g(e),t

Hope someone finds this useful :-)

Neil Davis

Developer

National Federation of the Blind

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.