minutekey / ez-access-web

Automatically exported from code.google.com/p/ez-access-web
0 stars 0 forks source link

Proposed change to speech output data structure #30

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
I am proposing that the speech output string be a concatenation of the 
substrings: name, role, connecting phrase & value.

I think it would make it easier to implement additional data-ez- tags for 
custom elements. It might also make it a little easier to read the code. 

name - is the label or other title that is associated with the object. For 
non-interactive objects (like p or img), this would be the text (and alt-text) 
content. The name might need to be calculated with precedence rules.
E.g., sayalt > aria-label > label > content (I haven't thought through the 
precedence here completely, so it might need to be different that what is here)

role - is the type of control or element. Non-interactive objects would leave 
this blank. Again, there would be precedence rules: e.g., sayrole > aria-role > 
[native role].

connecting_phrase - connects the role and value in speech to make it sensible.

value - is the value or status associated with the element. Again, 
non-interactive objects would leave this blank in general. For checkboxes, this 
would be the checked/unchecked status. For text fields, this would be the typed 
content. Etc.
data-ez-sayvalue would take precedence.

For most elements, they would be read thusly:
name + role + connecting_phrase + value

name = Red
role = checkbox
connecting_phrase = is
value = checked.

name = Color
role = menu (dropdown)
connecting_phrase = is
value = blue.

In contrast, links <a href=""> I would like read in role + name order.

So what you might do is have a complete string (say "speech") that gets 
concatenated in the default way usually, but which can be over-ridden in a 
particular if-else statement. For example...

...
else if (obj.tagName == "a" && obj.hasAttribute(href)) {
//get values for substrings

speech = role + ': ' + name + '.';
}
...
//Generic concatenation
if (speech == '') speech = name + role + phrase + value + '.';

Note that reading when the user presses EZ Action would need to be handled in a 
different function, but might have similar substrings.

Original issue reported on code.google.com by jbjor...@gmail.com on 22 May 2013 at 5:58

GoogleCodeExporter commented 8 years ago
You might also want to have another substring for text after the value: maybe 
called "extra".

extra could store extra information about particular elements, (such as "option 
1 of 6"). Although ideally, that extra information would only be provided when 
a person activates a control--that way they only hear the extra information 
when they are interested in that particular control.

Original comment by jbjor...@gmail.com on 22 May 2013 at 6:51

GoogleCodeExporter commented 8 years ago
Some code ideas

/* General checks for precedence */
var name = '';
if (obj.hasAttribute(data-ez-sayalt)) name = obj.getAttribute(data-ez-sayalt);
else if (obj.hasAttribute(aria-label)) name = obj.getAttribute(aria-label);
else if (label) name = label; //assuming you get the label earlier

var role = '';
if (obj.hasAttribute(data-ez-sayrole)) role = obj.getAttribute(data-ez-sayrole);
var ariaRole = obj.getAttribute(aria-role);
else if (obj.hasAttribute(aria-role) && (ariaRole == 'button' || ariaRole == 
'checkbox' || ariaRole == 'radio')) {
  role = ariaRole;
}

var value = '';
if (obj.hasAttribute(data-ez-sayvalue)) value = 
obj.getAttribute(data-ez-sayvalue);

/* Specific enhancements for particular elements */
//example
...
if(obj.tagName == 'INPUT') {
    if(obj.getAttribute('readonly') || obj.getAttribute('disabled')) {
        if(name == '') {
            name = "Disabled field";
        }
        else {
            phrase = 'is';
        }
        if(obj.value !== undefined) { //This may be safer, b/c what if value=0, which is falsy?
            value = obj.value;
        } else {
            value = "blank.";
        }
//Continue with other elements
//Be sure to check if name, role, or value already have a value before writing 
a new one, for example
...
else if(obj.type == 'submit') {
    if (name == '') {
        if(obj.value) name = obj.value;
        else name = "Submit";
    }
    role = " Button";
} ...

//At the end, the standard concatenation might look like this:
if (speech == '') { //i.e., it has not been "over-ridden"
    speech = name + ' ' + role + ' ' + phrase + ' ' + value + ' ' + extra + '.';
}

Original comment by jbjor...@gmail.com on 22 May 2013 at 7:18

GoogleCodeExporter commented 8 years ago
More function-based approach

function getName( obj ) {
var ret = '';
if (obj.hasAttribute(data-ez-sayalt)) ret = obj.getAttribute(data-ez-sayalt);
else if (obj.hasAttribute(aria-labelledby) {
    var labelID = obj.getAttribute(aria-labelledby);
    //since aria-labelledby could be a space-delimited list of IDs,
    //you will need to concatenate if there is a list
    //so the code will be a little more involved than:
    ret += document.getElementById(labelID).textContent;
}
else if (obj.hasAttribute(aria-label)) ret = obj.getAttribute(aria-label);
else if ( findLabel() != '') ret = findLabel();
else if (obj.hasAttribute(placeholder) ret = obj.getAttribute(placeholder);

//Could get other possible name/labels here or not
//Could get inner text content here or not

return ret;
}

//If you don't catch everything in getName(), you will need to handle for a 
return of a blank name elsewhere--perhaps with code for individual elements.

Original comment by jbjor...@gmail.com on 22 May 2013 at 7:32

GoogleCodeExporter commented 8 years ago
I'll handle this one.

Original comment by jbjor...@gmail.com on 28 May 2013 at 2:23

GoogleCodeExporter commented 8 years ago
Implemented in a fashion with r137.

Note that there is no connecting phrase, which should be included in the value 
string.

Original comment by jbjor...@gmail.com on 28 May 2013 at 4:13

GoogleCodeExporter commented 8 years ago

Original comment by jbjor...@gmail.com on 28 May 2013 at 9:09