Index: chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js |
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js |
index 101e896d2d767232cb3e4f80d33e3cf07bb21949..b28aa02762c946b3f7008ed695ca4c33bb817a4b 100644 |
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js |
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js |
@@ -51,17 +51,23 @@ Output = function() { |
/** @type {!Array.<Object>} */ |
this.locations_ = []; |
/** @type {function()} */ |
- this.speechStartCallback_ = function() {}; |
+ this.speechStartCallback_; |
/** @type {function()} */ |
- this.speechEndCallback_ = function() {}; |
+ this.speechEndCallback_; |
/** @type {function()} */ |
- this.speechInterruptedCallback_ = function() {}; |
+ this.speechInterruptedCallback_; |
/** |
* Current global options. |
* @type {{speech: boolean, braille: boolean, location: boolean}} |
*/ |
this.formatOptions_ = {speech: true, braille: false, location: true}; |
+ |
+ /** |
+ * Speech properties to apply to the entire output. |
+ * @type {!Object.<string, *>} |
+ */ |
+ this.speechProperties_ = {}; |
}; |
/** |
@@ -81,7 +87,8 @@ Output.RULES = { |
braille: '' |
}, |
alert: { |
- speak: '@aria_role_alert $name $earcon(ALERT_NONMODAL)' |
+ speak: '!doNotInterrupt' + |
dmazzoni
2015/02/04 08:50:16
is there supposed to be a space after the !doNotIn
David Tseng
2015/02/04 16:57:13
Good catch! The parser splits expressions on space
|
+ '@aria_role_alert $name $earcon(ALERT_NONMODAL) $descendants' |
}, |
button: { |
speak: '$name $earcon(BUTTON, @tag_button)' |
@@ -307,15 +314,26 @@ Output.prototype = { |
var onEvent = function(evt) { |
switch (evt.type) { |
- case 'start': this.speechStartCallback_(); break; |
- case 'end': this.speechEndCallback_(); break; |
- case 'interrupted': this.speechInterruptedCallback_(); break; |
+ case 'start': |
+ this.speechStartCallback_(); |
+ break; |
+ case 'end': |
+ this.speechEndCallback_(); |
+ break; |
+ case 'interrupted': |
+ this.speechInterruptedCallback_ && this.speechInterruptedCallback_(); |
+ break; |
} |
}.bind(this); |
if (buff.toString()) { |
+ if (this.speechStartCallback_ || |
+ this.speechEndCallback_ || |
+ this.speechInterruptedCallback_) |
+ this.speechProperties_['onEvent'] = onEvent; |
+ |
cvox.ChromeVox.tts.speak( |
- buff.toString(), cvox.QueueMode.FLUSH, {onEvent: onEvent}); |
+ buff.toString(), cvox.QueueMode.FLUSH, this.speechProperties_); |
} |
var actions = buff.getSpansInstanceOf(Output.Action); |
@@ -457,6 +475,19 @@ Output.prototype = { |
if (node) |
this.format_(node, formatString, buff); |
} |
+ } else if (token == 'descendants') { |
+ // Construct a range to the leftmost and rightmost leaves. |
+ var leftmost = AutomationUtil.findNodePre( |
+ node, Dir.FORWARD, AutomationPredicate.leaf); |
+ var rightmost = AutomationUtil.findNodePre( |
+ node, Dir.BACKWARD, AutomationPredicate.leaf); |
+ if (!leftmost || !rightmost) |
+ return; |
+ |
+ var subrange = new cursors.Range( |
+ new cursors.Cursor(leftmost, 0), |
+ new cursors.Cursor(rightmost, 0)); |
+ this.range_(subrange, null, 'navigate', buff); |
} else if (node.attributes[token]) { |
this.addToSpannable_(buff, node.attributes[token], options); |
} else if (node.state[token]) { |
@@ -506,6 +537,8 @@ Output.prototype = { |
if (msg) { |
this.addToSpannable_(buff, msg, options); |
} |
+ } else if (prefix == '!') { |
+ this.speechProperties_[token] = true; |
} |
}.bind(this)); |
}, |