1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 /** 6 * @fileoverview A simple container object for the description of a 7 * navigation from one object to another. 8 * 9 */ 10 11 12 goog.provide('cvox.NavDescription'); 13 14 goog.require('cvox.AbstractTts'); 15 goog.require('cvox.ChromeVox'); 16 goog.require('cvox.CursorSelection'); 17 18 /** 19 * A class representing the description of navigation from one object to 20 * another. 21 * @param {{context: (undefined|string), 22 * text: (string), 23 * userValue: (undefined|string), 24 * annotation: (undefined|string), 25 * earcons: (undefined|Array.<number>), 26 * personality: (undefined|Object), 27 * hint: (undefined|string), 28 category: (undefined|string)}} kwargs The arguments for this 29 * description. 30 * context The context, for example descriptions of objects 31 * that were crossed into, like "Toolbar" or "Menu Bar" or "List with 32 * 5 items". This is all spoken with an annotation voice. 33 * text The text of the object itself, including text from 34 * titles, labels, etc. 35 * userValue The text that the user has entered. 36 * annotation The role and state of the object. 37 * earcons A list of the earcon ids to play along 38 * with the spoken description of this object. 39 * personality Optional TTS personality to use for the text. 40 * hint Optional Hint text (.e.g. aria-describedby). 41 * category Optional category (for speech queueing behavior). 42 * @constructor 43 */ 44 cvox.NavDescription = function(kwargs) { 45 this.context = kwargs.context ? kwargs.context : ''; 46 this.text = kwargs.text ? kwargs.text : ''; 47 this.userValue = kwargs.userValue ? kwargs.userValue : ''; 48 this.annotation = kwargs.annotation ? kwargs.annotation : ''; 49 this.earcons = kwargs.earcons ? kwargs.earcons : []; 50 this.personality = kwargs.personality; 51 this.hint = kwargs.hint ? kwargs.hint : ''; 52 this.category = kwargs.category ? kwargs.category : null; 53 }; 54 55 56 /** 57 * @return {boolean} true if this description is empty. 58 */ 59 cvox.NavDescription.prototype.isEmpty = function() { 60 return (this.context.length == 0 && 61 this.earcons.length == 0 && 62 this.text.length == 0 && 63 this.userValue.length == 0 && 64 this.annotation.length == 0); 65 }; 66 67 68 /** 69 * @return {string} A string representation of this object. 70 */ 71 cvox.NavDescription.prototype.toString = function() { 72 return 'NavDescription(context="' + this.context + '" ' + 73 ' text="' + this.text + '" ' + 74 ' userValue="' + this.userValue + '" ' + 75 ' annotation="' + this.annotation + 76 (this.category ? '" category="' + this.category + '")' : '') + 77 '")'; 78 }; 79 80 81 /** 82 * Modifies the earcon to play along with the spoken description of the object. 83 * @param {number} earconId An earcon id to be pushed on to the list of earcon 84 * ids to play along with the spoken description of this object. 85 */ 86 cvox.NavDescription.prototype.pushEarcon = function(earconId) { 87 this.earcons.push(earconId); 88 }; 89 90 91 /** 92 * Speak this nav description with the given queue mode. 93 * @param {number=} queueMode The queue mode: cvox.AbstractTts.QUEUE_MODE_FLUSH 94 * for flush, cvox.AbstractTts.QUEUE_MODE_QUEUE for adding to queue. 95 * @param {function()=} startCallback Function called when this starts speaking. 96 * @param {function()=} endCallback Function called when this ends speaking. 97 */ 98 cvox.NavDescription.prototype.speak = function( 99 queueMode, startCallback, endCallback) { 100 /** 101 * Return a deep copy of PERSONALITY_ANNOTATION for modifying. 102 * @return {Object} The newly created properties object. 103 */ 104 function makeAnnotationProps() { 105 var properties = {}; 106 var src = cvox.AbstractTts.PERSONALITY_ANNOTATION; 107 for (var key in src) { 108 properties[key] = src[key]; 109 } 110 return properties; 111 } 112 113 var speakArgs = new Array(); 114 if (this.context) { 115 speakArgs.push([this.context, queueMode, makeAnnotationProps()]); 116 queueMode = 1; 117 } 118 119 speakArgs.push([this.text, 120 queueMode, 121 this.personality ? this.personality : {}]); 122 queueMode = 1; 123 124 if (this.userValue) { 125 speakArgs.push([this.userValue, queueMode, {}]); 126 } 127 128 if (this.annotation) { 129 speakArgs.push([this.annotation, queueMode, makeAnnotationProps()]); 130 } 131 132 if (this.hint) { 133 speakArgs.push([this.hint, queueMode, makeAnnotationProps()]); 134 } 135 136 var length = speakArgs.length; 137 for (var i = 0; i < length; i++) { 138 if (i == 0 && startCallback) { 139 speakArgs[i][2]['startCallback'] = startCallback; 140 } 141 if (i == length - 1 && endCallback) { 142 speakArgs[i][2]['endCallback'] = endCallback; 143 } 144 if (this.category) { 145 speakArgs[i][2]['category'] = this.category; 146 } 147 cvox.ChromeVox.tts.speak.apply(cvox.ChromeVox.tts, speakArgs[i]); 148 } 149 }; 150 151 152 /** 153 * Compares two NavDescriptions. 154 * @param {cvox.NavDescription} that A NavDescription. 155 * @return {boolean} True if equal. 156 */ 157 cvox.NavDescription.prototype.equals = function(that) { 158 return this.context == that.context && 159 this.text == that.text && 160 this.userValue == that.userValue && 161 this.annotation == that.annotation; 162 }; 163