Chromium Code Reviews| Index: chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js |
| diff --git a/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js |
| index 98aa57ddb5a251bb78c1c27cab04ecc29c90b2c3..3d1569bfc1867a5f8b5c7ab2a0479187a387e243 100644 |
| --- a/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js |
| +++ b/chrome/browser/resources/chromeos/chromevox2/cvox2/background/background.js |
| @@ -25,6 +25,9 @@ cvox2.Background = function() { |
| */ |
| this.whitelist_ = ['http://www.chromevox.com/', 'chromevox_next_test']; |
| + /** @type {AutomationElement} @private */ |
| + this.currentElement_ = null; |
| + |
| // Only needed with unmerged ChromeVox classic loaded before. |
| // TODO(dtseng): Refactor all tabs handlers out of |
| // accessibility_api_handler.js. |
| @@ -86,9 +89,10 @@ cvox2.Background.prototype = { |
| * @param {AutomationEvent} evt The event. |
| */ |
| onAutomationEvent: function(evt) { |
| - var output = evt.target.attributes.name + ' ' + evt.target.role; |
| - cvox.ChromeVox.tts.speak(output, cvox.AbstractTts.QUEUE_MODE_FLUSH); |
| - cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output)); |
| + switch (evt.type) { |
| + case 'focus': |
| + this.onFocus(evt.target); |
| + } |
| }, |
| /** |
| @@ -96,6 +100,98 @@ cvox2.Background.prototype = { |
| * @param {string} command |
| */ |
| onGotCommand: function(command) { |
| + if (!this.current_) |
| + return; |
| + |
| + function find(cur, r, pred) { |
| + if (pred(cur)) |
| + return cur; |
| + var child = r ? cur.lastChild() : cur.firstChild(); |
| + while (child) { |
| + var ret = find(child, r, pred); |
| + if (ret) |
| + return ret; |
|
dmazzoni
2014/09/22 06:44:26
nit: indent
David Tseng
2014/09/22 23:45:34
Done.
|
| + child = r ? child.previousSibling() : child.nextSibling(); |
| + } |
| + } |
| + |
| + function findNextSubtree(cur, r) { |
| + while (cur) { |
| + var next = r ? cur.previousSibling() : cur.nextSibling(); |
| + if (next) |
| + return next; |
| + |
| + cur = cur.parent(); |
| + } |
| + } |
| + |
| + function moveNext(cur, r, pred) { |
| + var next = cur; |
| + do { |
| + if (!(next = findNextSubtree(cur, r))) |
| + return null; |
| + cur = next; |
| + next = find(next, r, pred); |
| + } while (!next); |
| + return next; |
| + } |
| + |
| + var previous = this.current_; |
| + var current = this.current_; |
| + switch (command) { |
| + case 'nextHeading': |
| + current = moveNext(current, false, function(e) { |
| + return e.role == 'heading'; |
| + }); |
| + break; |
| + case 'previousHeading': |
| + current = moveNext(current, true, function(e) { |
|
Peter Lundblad
2014/09/22 09:30:59
I think using predicates like this is nice. I sug
David Tseng
2014/09/22 23:45:34
Done.
|
| + return e.role == 'heading'; |
| + }); |
| + break; |
| + case 'nextLine': |
| + current = moveNext(current, false, function(e) { |
| + return e.role == 'inlineTextBox'; |
|
dmazzoni
2014/09/22 06:44:26
FWIW, since inline text boxes aren't actually node
David Tseng
2014/09/22 23:41:29
I actually think leaving them in the tree will sim
|
| + }); |
| + break; |
| + case 'previousLine': |
| + current = moveNext(current, true, function(e) { |
| + return e.role == 'inlineTextBox'; |
| + }); |
| + break; |
| + case 'nextLink': |
| + current = moveNext(current, false, function(e) { |
| + return e.role == 'link'; |
| + }); |
| + break; |
| + case 'previousLink': |
| + current = moveNext(current, true, function(e) { |
| + return e.role == 'link'; |
| + }); |
| + break; |
| + } |
| + if (current) |
| + current.focus(); |
| + this.onFocus(current || previous); |
| + }, |
| + |
| + /** |
| + * Provides all feedback once ChromeVox's focus changes. |
| + * @param {AutomationElement} element The newly focused element. |
| + */ |
| + onFocus: function(element) { |
| + var container = element; |
| + while (container && (container.role == 'inlineTextBox' || |
| + container.role == 'staticText')) |
| + container = container.parent(); |
| + |
| + var role = container ? container.role : element.role; |
| + |
| + var output = |
| + [element.attributes.name, element.attributes.value, role].join(','); |
| + cvox.ChromeVox.tts.speak(output, cvox.AbstractTts.QUEUE_MODE_FLUSH); |
| + cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output)); |
| + this.current_ = element; |
| }, |
| /** |