JAWS doesn't read dynamic content. IE11 - javascript

I have a search form. When user submits form, ajax request is sent to the server. When the response comes, I update found items count value, but JAWS reads previous items count value.
To get JAWS read new content I use aria attributes and role="status". But JAWS still doesn't work as expected.
What I've tried:
Getting screen reader to read new content added with JavaScript,
aria-live and JAWS, ARIA Live Regions and etc.
What am I doing wrong?
HTML
<form class="search-form">
<label class="keyword-search-input-label" for="keyword-search-input">
<span class="hide">Search</span>
<input class="form-control" type="text" id="keyword-search-input" name="keyword"/>
</label>
<button id="clear-field-button" type="reset">
<span class="hide">Clear Search Field</span>
</button>
<button id="search-button" type="submit" aria-describedby="number-found-items">
<span class="symbol-label">Search</span>
</button>
</form>
<div id="number-found-items" role="status" aria-live="assertive" aria-atomic="true" aria-relevant="all">
<span id="number-found">0</span>
items found
</div>
JS
function updateNumberFound(value) {
$numberFound.text(value || 0);
}
jsFiddle
To reproduce the problem try to focus on search input, type some text and press search button, while JAWS is on.

The correct way to do this is to use a role="log" region that is inserted into the document when it loads and is off screen. Then to append the text that you want announced to that region when updates occur.
I have modified your fiddle to include the a11yfy library's code which does this: https://jsfiddle.net/17mkL2n5/1/embedded/result/
jQuery.a11yfy.assertiveAnnounce(value + ' items found');
I have tested this on OS X with VO, Windows with NVDA and Windows IE 11 with JAWS 14 and they all work correctly.

Related

click() function on input field using browser console

I need to make a simulated click on input field using javascript in browser console.
The site isn't mine.
I use the code:
document.getElementById('bets-stake-amount-1').click();
I have to click the element with this ID: bets-stake-amount-1 .
I think that only option is to click with mouse button.
I have tried to change the type of the field but it not work.
<div class="bet p-1 ng-star-inserted">
<div class="bet-icons pull-right">
<a class="bet-remove ng-star-inserted">
<span class="fa fa-times" title="Rimuovi">
</span>
</a>
</div>
</div>
<div class="combis mt-2 mb-2">
<app-betslip-input grouping="1" class="ng-star-inserted">
<div class="radio p-1 ng-star-inserted">
<div class="flex-row">
<div class="input-group flex-col-7">
<input autocomplete="off" class="form-control text-right" tabindex="1" type="text" id="bets-stake-amount-1" readonly="">
<span class="input-group-addon ng-star-inserted">€
</span>
</div>
</div>
</div>
</app-betslip-input>
</div>
The output is undefined .
In IE you have to confirm ActiveX after 1st console command (in local page tested), next time it works.
In FF & Chrome works without problems, but not sure how you recognize "pass" result.
For example calling onclick in Chrome reports this error:
document.getElementById('bets-stake-amount-1').onclick()
VM49:1 Uncaught TypeError: document.getElementById(...).onclick is not a function
at :1:48
And without brackets return null as there is no method to call.
In IE you can see even focus by this command document.getElementById('bets-stake-amount-1').focus() and in FF you cannot get focus or cursor in at all. Also Chrome no change after focus, but it can show focus after entering by tab or mouse click.
According to documentation https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/text, the input field responds to two possible events: input and change.
Okay, but how does this work you may ask?
Suppose that you have the following input field
<input value="0.005" autofocus="" name="price" placeholder="Amount">
All you have to do is to set a value (because this field responds to value change)
document.getElementsByName("price")[0].setAttribute("value", "10")
Then trigger the input event like this
document.getElementsByName("price")[0].dispatchEvent(new Event('input', {bubbles:true}));
This way it works to programatically launch events on input fields.
Triggering the event without setting a value will not work, because remember, the input field reacts to changes of it's value. If there is no change, no event will happen.
Hope my answer will help others.
P.S.: Always remember to read the documentation carefully. Most of the times the answer to our questions is right there :)
Have a good day!
You can simulate a click to an element (by ID) with this code
document.getElementById('elementID').click();
other option is to use this code (https://stackoverflow.com/a/2706236/7584019)
if (el.fireEvent) {
el.fireEvent('on' + etype);
} else {
var evObj = document.createEvent('Events');
evObj.initEvent(etype, true, false);
el.dispatchEvent(evObj);
}

HTML required fields are not showing a message when it's not filled out

I have a big form for a website, with multiple required fields, and all of them are working perfectly, when i click submit on the form, the web page scroll to the field's location with an error message, except on two parts, the "Number of travelers" and the "Date of the trip".
This is the HTML for both of them:
<div class="sect-txt" style="margin-top:100px;" id="op">
<h1> Date of the trip </h1>
<div class="al">
<h1 style="font-family:Montserrat;font-size:14px;color:#161616;margin-bottom:5px;"> Check In </h1>
<input type="date" class="hide-replaced" data-date-size="1" placeholder="Check-in" name="checkin" required />
</div>
<div class="al">
<h1 style="font-family:Montserrat;font-size:14px;color:#161616;margin-bottom:5px;"> Check Out </h1>
<input type="date" class="hide-replaced" data-date-size="1" placeholder="Check-out" name="checkout" required />
</div>
<a href="#four">
<div class="btn-nxt" style="position:relative;top:137px;">
NEXT
</div>
</a>
</div>
<div class="sect-txt">
<h1> Number of travelers </h1>
<input type="number" class="f-2" placeholder="Adults" name="adults" required/>
<input type="number" class="f-3" placeholder="Children" name="childrens" required/>
<a href="#fif">
<div class="btn-nxt-b">
NEXT
</div>
</a>
</div>
And this is a link to the page in action: http://www.eliteware.co/92/form/
Your button is not focusable because you are trying to hide it when it has to receive focus again. Check the following link for more information about why this happens. Basically, you are hiding the object that is supposed to receive focus when validation is needed. If you don't want this to happen, you can probably do validation before hiding, or unhide the object if validation fails.
https://stackoverflow.com/a/28340579/616813
Also, do remember, if an error log exists, that is the first point to check if you receive an error. That is the whole point of error log, to give you a starting point to debug.
Or as Andreas said, "Fix the damn errors in the console... :)".
Edit:
Because it was killing me, I tried to reverse engineer your application. All it took was comparing the textbox that was working, and the one that was failing to find the problem. Really, that easy.
aria-required="true"
Your "Adults" and "Children" input fields have this property. You need required="true" instead.
Check your css and update that. And no, I have no idea why "aria=required" and "required" property behave differently. It is something new to learn for sure.

Several radio button groups in nested ng-repeat, but only last group shows the value

I have a page where I want to update a form with several radio buttons. I query an api, and use the returned array of objects to populate the current values for the radio buttons. The problem that I have is that only the last set of radio buttons actually shows the value. This is the code that I have (I am using [[ and ]] for the start and end symbols for angular):
<fieldset data-ng-repeat="s in sections">
<div class="form-group">
<div class="col-md-12">
<h2>[[ s.section.name ]]</h2>
</div>
</div>
<!-- Field Item -->
<div class="form-group m-b-20 bg-light" data-ng-repeat="f in s.fields">
<div class="col-md-12 m-b-30">
<h4>[[ f.field.name ]]</h2>
<input type="text" data-ng-model="f.comments" class="form-control input-md underline" placeholder="Comments">
</div>
<div class="col-sm-3">
<input type="radio" name="section-[[s.section.section_id]]-field-[[f.field.field_id]]" value="pass" class="form-control" data-ng-model="f.field_condition">
<label class="eval-pass"><i class="fa fa-check-circle green"></i> Pass</label>
</div>
<div class="col-sm-3">
<input type="radio" name="section-[[s.section.section_id]]-field-[[f.field.field_id]]" value="fail" class="form-control" data-ng-model="f.field_condition">
<label class="eval-fail"> <i class="fa fa-exclamation-circle red"></i> Fail</label>
</div>
<div class="col-sm-3">
<input type="radio" name="section-[[s.section.section_id]]-field-[[f.field.field_id]]" value="n/a" class="form-control" data-ng-model="f.field_condition">
<label class="eval-na"> <i class="fa fa-circle blue"></i> N/A</label>
</div>
<div class="col-sm-3">
<input type="radio" name="section-[[s.section.section_id]]-field-[[f.field.field_id]]" value="caution" class="form-control" data-ng-model="f.field_condition">
<label class="eval-caution"><i class="fa fa-exclamation-triangle yellow"></i> Caution</label>
</div>
</div>
[[ f.field_condition ]]
<hr>
</fieldset>
So basically, I have several sections, and each section has several fields. Each field has it's own radio button group (I am using the section and field ids to name the radio group). What I currently see is only the last field in each section actually shows the selected radio button. The other fields don't have any selection, even though the value for ng-model definitely does (I am showing the value of f.field_condition just to make sure there is a value).
For each field, I can see that the model is set. And if I select a value manually, I can see that the model changes, so it seems to me that the model is setup correctly. I just don't know why it won't initially show as selected for all rows but the last one.
I should also mention that if I save the form even with the missing radio button selections, the database is updated properly (it doesn't set the values to null, and if I manually change the selected value, it is updated in the db as well).
Does anyone have any ideas? Thanks!
EDIT
Here is a fiddle for this, although, it is working as expected in the fiddle. http://jsfiddle.net/dq8r196v/367/
I tried using the static data that I used in the fiddle, but I am still having the same problem. Does anyone know if this could be a CSS problem? The radio buttons are styled, and I didn't write the HTML or CSS.
UPDATE
I am still having this issue, so I built a new angular app and only used the code that is included in the fiddle that I have created. I am having the same problem with this new app, even though the same code works in the fiddle. I really don't understand what's happening here, but if anyone could shed some light, I would really appreciate it.
I have literally copied and pasted the code from my fiddle into a new angular app, and only the last group of radio buttons in each section is showing the value in the app.
Here is my complete code for the new angular app if someone else wants to try it out and see exactly what is happening: https://pastebin.com/qSR33yfM
I created the app on a single page for simplicity.
Here is the link to a pastebin with the exact json that I am using in my app: https://pastebin.com/utfVVQfT
I fixed the problem you're having by simply adding an array of objects ($scope.values) representing the different radio button options, and using an ng-repeat to create your radio buttons. See the following for the updated code: https://pastebin.com/s3hNzaXX
I know there are semantics around ng-repeat creating new $scopes, and imagine there is a conflict in scopes with your nested ng-repeats where it's binding to the radio buttons incorrectly and at a scope different than you want (the section level ng-repeat).
To confirm this suspicion, you could convert all of your interpolations in the code to use functions and console.log s and f at different points and confirm that field_condition is being set at a level you didn't intend.
Either way, it' best practice to create your radio buttons through data (and using ng-repeat), as is done with the $scope.values array, and a good side effect to doing this is not only can you update the different value options using data through AJAX or however you would like, but you won't have weird angular scoping issues as you're experiencing in your current code above.

Can't assign a new value to my autocomplete box

I've created a search page that can be toggled between french and english. So when the user searches a record and toggles to french it displays the same record they were viewing on the english page.
What I want to do is display the record name in the search box when the page is toggled.I assumed it was as simple as doing a $('#inputID').val(record); but it doesn't seem to be working. I've alerted the record name and it works fine, so I'm stumped. All the scripts are linked correctly as well so that's not the problem.
Autocomplete Box Code
<div id="ui-widgit">
<label for="searchParams">
<h1>Search All Programs (By Screen Number or By Error Code):</h1>
</label>
<input type="text" id="inputID" name="inputID" value="" class="ipt_Design" style="width:255px;" />
<input type="button" value="Search" name="searchBtn" class="btn_Design" onclick="showSearch(inputID.value)"/>
</div>
Try to change the value of inputID with this
$('#inputID').val(recordToggle);
also have tried this:
$('#inputID input').val(recordToggle);
It is hard to tell with your presented markup but I am assuming you are trying to change the value of $('#inputID') after the page refreshed. It is important where you put this code. If it is placed before <input type="text" id="inputID" name="inputID" value="" class="ipt_Design" style="width:255px;" /> you will not return anything with $('#inputID') so you will change the value of nothing to your text. It will give no error. To fix this you can use:
$( document ).ready(function(){
$('#inputID').val(recordToggle);
});
Be sure to read about jQuery's ready function because load may be the better choice.
If this doesn't fix your problem let me know. I will update my answer.

JQuery .replaceWith() suddenly putting new element in the wrong place?

This one is really baffling me. I'm using replaceWith() to "clear" a file input field. However, when it replaces it, it puts it back in the wrong place, and I have no idea why. I used the term "suddenly" in the title because what's even more mysterious is that when I stopped working for the weekend the replacement was working exactly as expected. Now I get back to work and suddenly it's not.
Here's the source HTML before calling replaceWith():
<label>Audio</label>
<i style="color:#888888;">MP3 or OGG format recommended</i>
<br>
<button id="clear_audio_input" style="display:none;">Clear</button>
<input type="file" value="" name="source_audio" style="width:300px;">
<br>
<div style="margin-top:15px;">
<b>Current: </b>
<i id="current_audio_source">1360954394_121RuleOfRosePianoEtudeI.mp3</i>
<br>
<input id="source_audio_value" class="required_media" type="hidden" value="1360954394_121RuleOfRosePianoEtudeI.mp3" name="source_audio">
<span id="current_audio_info_a"><input type="checkbox" style="position:relative;top:3px;margin-left:0px;" value="yes" name="source_audio_delete">
Delete current audio?
Current audio will be replaced
Note the location of the FILE input field, named "source_audio". It's immediately after the "Clear" button.
Now, after I call replaceWith(), the HTML looks like this:
<label>Audio</label>
<i style="color:#888888;">MP3 or OGG format recommended</i>
<br>
<button id="clear_audio_input" style="display: none;">Clear</button>
<br>
<div style="margin-top:15px;">
<b>Current: </b>
<i id="current_audio_source">1360954394_121RuleOfRosePianoEtudeI.mp3</i>
<br>
<input type="file" value="" name="source_audio" style="width:300px;">
<input id="source_audio_value" class="required_media" type="hidden" value="1360954394_121RuleOfRosePianoEtudeI.mp3" name="source_audio">
<span id="current_audio_info_a" style="display: inline;"><input type="checkbox" style="position:relative;top:3px;margin-left:0px;" value="yes" name="source_audio_delete">
Delete current audio?
Current audio will be replaced
Notice that it is now several lines down and inside another DIV.
Here is the script that controls the "Clear" button's actions:
$("#clear_audio_input").live("click", function() {
$("input[name='source_audio']").replaceWith($("input[name='source_audio']").val('').clone(true));
$("#source_audio_value").val($("#current_audio_source").text());
$(this).hide();
$("#current_audio_info_a").show();
$("#current_audio_info_b").hide();
checkRequiredMedia();
return false;
});
Here's the basic intended workflow. On load, the clear button is hidden because there is nothing yet to clear. After the user has selected a file, the clear button appears. Clicking the button will clear the file input (by replacing it) and then the button will hide again, essentially returning the form to the same state it was in on load.
Any reason why this oddity is happening (especially since it wasn't happening a few days ago, and I haven't changed anything since then)?
The issue is because you have two inputs with the name source_audio. To get around this, you will need to either give the two inputs fields an id, or change the name.
For example:
$('#my_file_input').replaceWith('<input id="my_file_input" type="file" name="source_audio" />');
$('#my_hidden_file_input').val('');

Categories